* Re: [PATCH 2/2] fsl/embedded6xx: don't cast the result of of_get_property
From: Segher Boessenkool @ 2007-09-26 12:55 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linuxppc-dev, Jeremy Kerr
In-Reply-To: <20070926104419.1b92002e.sfr@canb.auug.org.au>
>> - avr_clock = *(u32*)of_get_property(avr, "clock-frequency", &len);
>> - phys_addr = ((u32*)of_get_property(avr, "reg", &len))[0];
>> + phys_addr = of_get_property(avr, "reg", &len);
>> + avr_clock_prop = of_get_property(avr, "clock-frequency", &len);
>
> If you don't use the value of the len variable, then you can pass NULL
> to
> of_get_property.
OTOH, it is almost always an error to not use the length (missing
error check).
Segher
^ permalink raw reply
* Re: jffs2 file system on MPC8272ADS board
From: Nethra @ 2007-09-26 12:34 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070925202257.559a78c5@ru.mvista.com>
Hello ,
>>
>> hi everyone,
>>
>> I m using custom board similar to MPC8272ADS board...
>>
>> 1) For the first time it boots up properly in case if we overwrite any
>> existing binaries using nfs mounted file system on the board, after
>> rebooting it displays fallowing message...
>>
>> Further such events for this erase block will not be printed
>> Eep. Child "null" (ino #1346) of dir ino #3 doesn't exist!
>> Eep. Child "autocomm" (ino #463) of dir ino #461 doesn't exist!
>> Eep. Child "calibration" (ino #464) of dir ino #461 doesn't exist!
>> Eep. Child "coredsp_driver.ko" (ino #939) of dir ino #336 doesn't exist!
>> Inode #1307 was a directory with children - removing those too...
>> Inode #564 was a directory with children - removing those too...
>> Inode #565 was a directory with children - removing those too...
>> Inode #1112 was a directory with children - removing those too...
>> Inode #1115 was a directory with children - removing those too...
>> Inode #1118 was a directory with children - removing those too...
>> Inode #1123 was a directory with children - removing those too...
>>
>> after this board boots up properly....but it not be having overwritten
>> files
>>
>Have you created jffs2 file system on flash prior to mounting it?
Yes I created jffs2 filesytem using mkfs.jffs2 prior to mounting and then I
am over-writing some of the binaries. In case of overwrites from NFS after
reboot
I see the above errors & the binaries/directories gets deleted from the
jffs2 partition.
>> 3) when board is running properly in between it starts printing on
>> console
>> repeatedly...
>>
>Do the proper MTD partitions setup, erase the partition and create jffs2
filesystem on it.
>If after all those steps you're still getting output, that is prolly flakey
flash.
>> Header CRC failed on REF_PRISTINE node at 0x00638a6c: Read 0xffffffff,
>> calculated 0x44660075
>> Node totlen on flash (0xffffffff) != totlen from node ref (0x00000254)
>> Header CRC failed on REF_PRISTINE node at 0x00638cc0: Read 0xffffffff,
>> calculated 0x44660075
[...]
>> and
>>
>> file system is created using fallowing command..
>>
>> mkfs.jffs2 -r RFS_NEW/ -e 0x20000 -o /tftpboot/jffs2_img -b
>>
>I am recalling playing with the options upper also cured the jffs2 warnings
(not as many as yours but anyway)
The other options I am wondering about,
-c, --cleanmarker=SIZE Size of cleanmarker (default 12)
-n, --no-cleanmarkers Don't add a cleanmarker to every eraseblock
cleanmaker size will it help the cause?
Nethra
--
View this message in context: http://www.nabble.com/jffs2-file-system-on-MPC8272ADS-board-tf4513530.html#a12900017
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* Re: [PATCH 1/7] PowerPC64: Not to insert EA=0 entry at initializing SLB
From: Arnd Bergmann @ 2007-09-26 12:15 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.132034.-1300539325.kouish@swc.toshiba.co.jp>
On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This is a workaround NOT to insert EA=0 entry at initializing SLB.
> Without this patch, you can see /sbin/init hanging at a machine
> which has less or equal than 256MB memory.
Can you elaborate? I don't understand why /sbin/init will hang
because of an incorrect SLB entry, or how that entry gets
initialized from get_paca()->kstack.
Are you still trying to find a better fix for 2.6.24, or do
you intend to have this patch go in for now?
Also, I did not get a patch 4/7 and 5/7. Did you send them to
some other mailing list, or did they get lost on the way?
Arnd <><
^ permalink raw reply
* Re: [PATCH 7/7] Celleb: update for PCI
From: Arnd Bergmann @ 2007-09-26 12:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.134050.1102532600.kouish@swc.toshiba.co.jp>
On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This is a patch kit to support PCI bus on Celleb with new "I/O routines
> for PowerPC." External PCI on Celleb must do explicit synchronization
> with devices (Bus has no automatic synchronization feature).
It seems you are duplicating a lot of
arch/powerpc/platforms/cell/io-workarounds.c, in order to work around
the same problem:
> +static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
> + unsigned long paddr)
> +{
> + int i, j;
> + struct resource *res;
> +
> + for (i = 0; i < celleb_pci_count; i++) {
> + struct celleb_pci_bus *bus = &celleb_pci_busses[i];
> + struct pci_controller *phb = bus->phb;
> + if (paddr)
> + for (j = 0; j < 3; j++) {
> + res = &phb->mem_resources[j];
> + if (paddr >= res->start && paddr <= res->end)
> + return bus;
> + }
> + res = &phb->io_resource;
> + if (vaddr && vaddr >= res->start && vaddr <= res->end)
> + return bus;
> + }
> + return NULL;
> +}
> +
> +static void celleb_io_flush(const PCI_IO_ADDR addr)
> +{
> + struct celleb_pci_bus *bus;
> + int token;
> +
> + token = PCI_GET_ADDR_TOKEN(addr);
> +
> + if (token && token <= celleb_pci_count)
> + bus = &celleb_pci_busses[token - 1];
> + else {
> + unsigned long vaddr, paddr;
> + pte_t *ptep;
> +
> + vaddr = (unsigned long)PCI_FIX_ADDR(addr);
> + if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
> + return;
> +
> + ptep = find_linux_pte(init_mm.pgd, vaddr);
> + if (ptep == NULL)
> + paddr = 0;
> + else
> + paddr = pte_pfn(*ptep) << PAGE_SHIFT;
> + bus = celleb_pci_find(vaddr, paddr);
> +
> + if (bus == NULL)
> + return;
> + }
> +
> + if (bus->dummy_read)
> + bus->dummy_read(bus->phb);
> +}
> +
> +static u8 celleb_readb(const PCI_IO_ADDR addr)
> +{
> + u8 val;
> + val = __do_readb(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static u16 celleb_readw(const PCI_IO_ADDR addr)
> +{
> + u16 val;
> + val = __do_readw(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static u32 celleb_readl(const PCI_IO_ADDR addr)
> +{
> + u32 val;
> + val = __do_readl(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static u64 celleb_readq(const PCI_IO_ADDR addr)
> +{
> + u64 val;
> + val = __do_readq(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static u16 celleb_readw_be(const PCI_IO_ADDR addr)
> +{
> + u16 val;
> + val = __do_readw_be(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static u32 celleb_readl_be(const PCI_IO_ADDR addr)
> +{
> + u32 val;
> + val = __do_readl_be(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static u64 celleb_readq_be(const PCI_IO_ADDR addr)
> +{
> + u64 val;
> + val = __do_readq_be(addr);
> + celleb_io_flush(addr);
> + return val;
> +}
> +
> +static void celleb_readsb(const PCI_IO_ADDR addr,
> + void *buf, unsigned long count)
> +{
> + __do_readsb(addr, buf, count);
> + celleb_io_flush(addr);
> +}
> +
> +static void celleb_readsw(const PCI_IO_ADDR addr,
> + void *buf, unsigned long count)
> +{
> + __do_readsw(addr, buf, count);
> + celleb_io_flush(addr);
> +}
> +
> +static void celleb_readsl(const PCI_IO_ADDR addr,
> + void *buf, unsigned long count)
> +{
> + __do_readsl(addr, buf, count);
> + celleb_io_flush(addr);
> +}
> +
> +static void celleb_memcpy_fromio(void *dest,
> + const PCI_IO_ADDR src,
> + unsigned long n)
> +{
> + __do_memcpy_fromio(dest, src, n);
> + celleb_io_flush(src);
> +}
> +
> +static void __iomem *celleb_ioremap(unsigned long addr,
> + unsigned long size,
> + unsigned long flags)
> +{
> + struct celleb_pci_bus *bus;
> + void __iomem *res = __ioremap(addr, size, flags);
> + int busno;
> +
> + bus = celleb_pci_find(0, addr);
> + if (bus != NULL) {
> + busno = bus - celleb_pci_busses;
> + PCI_SET_ADDR_TOKEN(res, busno + 1);
> + }
> + return res;
> +}
Is there a way that we can make that code common? I guess there could be a
file in arch/powerpc/sysdev that can handle this correctly for all hardware
that requires this particular workaround (currently celleb and QS20, but
potentially more).
Arnd <><
^ permalink raw reply
* Re: [PATCH 3/7] Celleb: Support for Power/Reset buttons
From: Arnd Bergmann @ 2007-09-26 11:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.132556.1723232353.kouish@swc.toshiba.co.jp>
On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This is a patch to support Power/Reset buttons on Beat on Celleb.
>
> On Beat, we have an event from Beat if Power button or Reset button
> is pressed. This patch catches the event and convert it to a signal
> to INIT process.
>
> /sbin/inittab have no entry to turn the machine power off so we have
> to detect if power button is pressed or not internally in our driver.
> This idea is taken from PS3's event handling subsystem.
>
> Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>
Basically looks good. At some point I want to do a similar driver
for the IBM cell blade, but I fear there is not much code we
can share.
> +static irqreturn_t beat_power_event(int virq, void *arg)
> +{
> + printk(KERN_DEBUG "Beat: power button pressed\n");
> + beat_pm_poweroff_flag = 1;
> + if (kill_cad_pid(SIGINT, 1)) {
> + /* Just in case killing init process failed */
> + beat_power_off();
> + }
> + return IRQ_HANDLED;
> +}
I think this should call ctrl_alt_del() instead of doing
kill_cad_pid() directly.
Also, I think you should better not call the low-level
beat_power_off() function, but rather a high-level function
that goes through the reboot notifiers first.
kernel_restart() seems appropriate for that.
> +static irqreturn_t beat_reset_event(int virq, void *arg)
> +{
> + printk(KERN_DEBUG "Beat: reset button pressed\n");
> + beat_pm_poweroff_flag = 0;
> + if (kill_cad_pid(SIGINT, 1)) {
> + /* Just in case killing init process failed */
> + beat_restart(NULL);
> + }
> + return IRQ_HANDLED;
> +}
same here, except calling kernel_halt() in the end.
> +static int __init beat_event_init(void)
> +{
> + if (!machine_is(celleb) || !firmware_has_feature(FW_FEATURE_BEAT))
> + return -EINVAL;
Shouldn't one of the two be sufficent? It seems to me that you want to
probe for either celleb or BEAT, but not both, considering that celleb
implies BEAT.
Arnd <><
^ permalink raw reply
* Re: [PATCH 2/7] Celleb: Move pause, kexec_cpu_down to beat.c
From: Arnd Bergmann @ 2007-09-26 11:40 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.132314.-432833655.kouish@swc.toshiba.co.jp>
On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This patch is an update for "Beat on Celleb"
> =A0 - Move beat_pause(), beat_kexec_cpu_down() from setup.c to beat.c
>=20
> Signed-off-by: <Kou.Ishizaki@toshiba.co.jp>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
The patch looks good, once you fix this one line:
> @@ -36,5 +36,9 @@ ssize_t beat_nvram_get_size(void);
> =A0ssize_t beat_nvram_read(char *, size_t, loff_t *);
> =A0ssize_t beat_nvram_write(char *, size_t, loff_t *);
> =A0int beat_set_xdabr(unsigned long);
> +void beat_power_save(void);
> +#ifdef CONFIG_KEXEC
> +void beat_kexec_cpu_down(int, int);
> +#endif
=46unction declarations in headers files should not be enclosed in #ifdef,
it only causes unnecessary rebuilds when the configuration changes, but
does not help.
Arnd <><
^ permalink raw reply
* Re: Please pull powerpc.git merge branch
From: Paul Mackerras @ 2007-09-26 11:33 UTC (permalink / raw)
To: torvalds; +Cc: linuxppc-dev, jk
In-Reply-To: <18168.62378.472571.655865@cargo.ozlabs.ibm.com>
I wrote:
> Linus,
>
> Please do
>
> git pull \
> git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge
>
> to get a patch from Roland McGrath that fixes a user-triggerable oops
> on 64-bit powerpc.
I have added another commit from Jeremy Kerr fixing a mismerge that
caused a user visible ABI regression from 2.6.22. The diffstat and
log below include both the patch from Roland and this new patch.
Thanks,
Paul.
arch/powerpc/kernel/process.c | 7 +++++++
arch/powerpc/platforms/cell/spufs/file.c | 4 ++--
2 files changed, 9 insertions(+), 2 deletions(-)
commit 603c461250b223ac42c10b8d1df653af1a361d44
Author: Jeremy Kerr <jk@ozlabs.org>
Date: Wed Sep 26 10:53:45 2007 +1000
[POWERPC] spufs: fix mismerge, making context signal{1,2} files readable again
The commit 8b6f50ef1d5cc86b278eb42bc91630fad455fb10 seems to have
been affected by a mismerge of a duplicate patch
(d054b36ffd302ec65aabec16a0c60ddd9e6b5a62) - both the
spufs_dir_contents and spufs_dir_nosched_contents have been given
write-only signal notification files.
This change reverts the spufs_dir_contents array to use the
readable signal notification file implementation.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
commit 474f81967217f3bec2389ae913da72641f2c40e3
Author: Roland McGrath <roland@redhat.com>
Date: Mon Sep 24 16:52:44 2007 -0700
[POWERPC] Ensure FULL_REGS on exec
When PTRACE_O_TRACEEXEC is used, a ptrace call to fetch the registers at
the PTRACE_EVENT_EXEC stop (PTRACE_PEEKUSR) will oops in CHECK_FULL_REGS.
With recent versions, "gdb --args /bin/sh -c 'exec /bin/true'" and "run" at
the (gdb) prompt is sufficient to produce this. I also have written an
isolated test case, see https://bugzilla.redhat.com/show_bug.cgi?id=301791#c15.
This change fixes the problem by clearing the low bit of pt_regs.trap in
start_thread so that FULL_REGS is true again. This is correct since all of
the GPRs that "full" refers to are cleared in start_thread.
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
^ permalink raw reply
* Re: [PATCH] add Altivec/VMX state to coredumps
From: Matt Sealey @ 2007-09-26 11:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1190758712.23457.0.camel@localhost.localdomain>
Benjamin Herrenschmidt wrote:
> On Tue, 2007-09-25 at 19:00 +0100, Matt Sealey wrote:
>> Kumar Gala wrote:
>>> I'm wondering how we distinguish a core dump w/altivec state vs one
>>> with SPE state.
>> Sheer number of registers saved?
>>
>> Why not put the PVR in core dumps that'd make it all easier..
>
> PVR wouldn't be very useful... What if you have altivec disabled ? Also
> that would mean your gdb has to know about all new processors...
Is that such a big deal? :D
Hypothetically it would be impossible to determine if you were running
on a G5 with the FPU and AltiVec turned off or an e500 core with SPE,
given the data saved. Is that a misfeature of GDB that we even have to
worry about this, or some noble plus point of a unified ISA? You decide :)
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
^ permalink raw reply
* [PATCH 5/5] ibmebus: More speaking error return code in ibmebus_store_probe()
From: Joachim Fenkes @ 2007-09-26 9:46 UTC (permalink / raw)
To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
arch/powerpc/kernel/ibmebus.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index c1e2963..0bd186c 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -268,10 +268,10 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
return -ENOMEM;
if (bus_find_device(&ibmebus_bus_type, NULL, path,
- ibmebus_match_path)) {
+ ibmebus_match_path)) {
printk(KERN_WARNING "%s: %s has already been probed\n",
__FUNCTION__, path);
- rc = -EINVAL;
+ rc = -EEXIST;
goto out;
}
--
1.5.2
^ permalink raw reply related
* [PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers
From: Joachim Fenkes @ 2007-09-26 9:45 UTC (permalink / raw)
To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>
Replace struct ibmebus_dev and struct ibmebus_driver with struct of_device
and struct of_platform_driver, respectively. Match the external ibmebus
interface and drivers using it.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
drivers/infiniband/hw/ehca/ehca_classes.h | 2 +-
drivers/net/ehea/ehea.h | 2 +-
include/asm-powerpc/ibmebus.h | 38 +++------------
arch/powerpc/kernel/ibmebus.c | 28 ++++++-----
drivers/infiniband/hw/ehca/ehca_eq.c | 6 +-
drivers/infiniband/hw/ehca/ehca_main.c | 32 ++++++------
drivers/net/ehea/ehea_main.c | 72 ++++++++++++++--------------
7 files changed, 79 insertions(+), 101 deletions(-)
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index c2edd4c..8ca4dd4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -106,7 +106,7 @@ struct ehca_sport {
struct ehca_shca {
struct ib_device ib_device;
- struct ibmebus_dev *ibmebus_dev;
+ struct of_device *ofdev;
u8 num_ports;
int hw_level;
struct list_head shca_list;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 8d58be5..830a66a 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -382,7 +382,7 @@ struct ehea_port_res {
#define EHEA_MAX_PORTS 16
struct ehea_adapter {
u64 handle;
- struct ibmebus_dev *ebus_dev;
+ struct of_device *ofdev;
struct ehea_port *port[EHEA_MAX_PORTS];
struct ehea_eq *neq; /* notification event queue */
struct workqueue_struct *ehea_wq;
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
index 87d396e..1a9d9ae 100644
--- a/include/asm-powerpc/ibmebus.h
+++ b/include/asm-powerpc/ibmebus.h
@@ -43,42 +43,18 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/mod_devicetable.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
extern struct bus_type ibmebus_bus_type;
-struct ibmebus_dev {
- struct of_device ofdev;
-};
+int ibmebus_register_driver(struct of_platform_driver *drv);
+void ibmebus_unregister_driver(struct of_platform_driver *drv);
-struct ibmebus_driver {
- char *name;
- struct of_device_id *id_table;
- int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id);
- int (*remove) (struct ibmebus_dev *dev);
- struct device_driver driver;
-};
-
-int ibmebus_register_driver(struct ibmebus_driver *drv);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv);
-
-int ibmebus_request_irq(struct ibmebus_dev *dev,
- u32 ist,
- irq_handler_t handler,
- unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+ unsigned long irq_flags, const char *devname,
void *dev_id);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
-
-static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver *drv)
-{
- return container_of(drv, struct ibmebus_driver, driver);
-}
-
-static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev)
-{
- return container_of(dev, struct ibmebus_dev, ofdev.dev);
-}
-
+void ibmebus_free_irq(u32 ist, void *dev_id);
#endif /* __KERNEL__ */
#endif /* _ASM_IBMEBUS_H */
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 43d4764..c1e2963 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -192,21 +192,26 @@ static int ibmebus_create_devices(const struct of_device_id *matches)
return ret;
}
-int ibmebus_register_driver(struct ibmebus_driver *drv)
+int ibmebus_register_driver(struct of_platform_driver *drv)
{
- return 0;
+ /* If the driver uses devices that ibmebus doesn't know, add them */
+ ibmebus_create_devices(drv->match_table);
+
+ drv->driver.name = drv->name;
+ drv->driver.bus = &ibmebus_bus_type;
+
+ return driver_register(&drv->driver);
}
EXPORT_SYMBOL(ibmebus_register_driver);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv)
+void ibmebus_unregister_driver(struct of_platform_driver *drv)
{
+ driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(ibmebus_unregister_driver);
-int ibmebus_request_irq(struct ibmebus_dev *dev,
- u32 ist,
- irq_handler_t handler,
- unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+ unsigned long irq_flags, const char *devname,
void *dev_id)
{
unsigned int irq = irq_create_mapping(NULL, ist);
@@ -214,12 +219,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev,
if (irq == NO_IRQ)
return -EINVAL;
- return request_irq(irq, handler,
- irq_flags, devname, dev_id);
+ return request_irq(irq, handler, irq_flags, devname, dev_id);
}
EXPORT_SYMBOL(ibmebus_request_irq);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
+void ibmebus_free_irq(u32 ist, void *dev_id)
{
unsigned int irq = irq_find_mapping(NULL, ist);
@@ -230,9 +234,7 @@ EXPORT_SYMBOL(ibmebus_free_irq);
static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
- const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
- return sprintf(buf, "%s\n", name);
+ return sprintf(buf, "%s\n", to_of_device(dev)->node->name);
}
static struct device_attribute ibmebus_dev_attrs[] = {
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 1d41faa..b4ac617 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -123,7 +123,7 @@ int ehca_create_eq(struct ehca_shca *shca,
/* register interrupt handlers and initialize work queues */
if (type == EHCA_EQ) {
- ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
+ ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
IRQF_DISABLED, "ehca_eq",
(void *)shca);
if (ret < 0)
@@ -131,7 +131,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
} else if (type == EHCA_NEQ) {
- ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
+ ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
IRQF_DISABLED, "ehca_neq",
(void *)shca);
if (ret < 0)
@@ -171,7 +171,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
u64 h_ret;
spin_lock_irqsave(&eq->spinlock, flags);
- ibmebus_free_irq(NULL, eq->ist, (void *)shca);
+ ibmebus_free_irq(eq->ist, (void *)shca);
h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c84e310..8a038b1 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -404,7 +404,7 @@ int ehca_init_device(struct ehca_shca *shca)
shca->ib_device.node_type = RDMA_NODE_IB_CA;
shca->ib_device.phys_port_cnt = shca->num_ports;
shca->ib_device.num_comp_vectors = 1;
- shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev;
+ shca->ib_device.dma_device = &shca->ofdev->dev;
shca->ib_device.query_device = ehca_query_device;
shca->ib_device.query_port = ehca_query_port;
shca->ib_device.query_gid = ehca_query_gid;
@@ -658,7 +658,7 @@ static struct attribute_group ehca_dev_attr_grp = {
.attrs = ehca_dev_attrs
};
-static int __devinit ehca_probe(struct ibmebus_dev *dev,
+static int __devinit ehca_probe(struct of_device *dev,
const struct of_device_id *id)
{
struct ehca_shca *shca;
@@ -666,16 +666,16 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
struct ib_pd *ibpd;
int ret;
- handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
+ handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
if (!handle) {
ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
- dev->ofdev.node->full_name);
+ dev->node->full_name);
return -ENODEV;
}
if (!(*handle)) {
ehca_gen_err("Wrong eHCA handle for adapter: %s.",
- dev->ofdev.node->full_name);
+ dev->node->full_name);
return -ENODEV;
}
@@ -686,9 +686,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
}
mutex_init(&shca->modify_mutex);
- shca->ibmebus_dev = dev;
+ shca->ofdev = dev;
shca->ipz_hca_handle.handle = *handle;
- dev->ofdev.dev.driver_data = shca;
+ dev->dev.driver_data = shca;
ret = ehca_sense_attributes(shca);
if (ret < 0) {
@@ -764,7 +764,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
}
}
- ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+ ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp);
if (ret) /* only complain; we can live without attributes */
ehca_err(&shca->ib_device,
"Cannot create device attributes ret=%d", ret);
@@ -814,12 +814,12 @@ probe1:
return -EINVAL;
}
-static int __devexit ehca_remove(struct ibmebus_dev *dev)
+static int __devexit ehca_remove(struct of_device *dev)
{
- struct ehca_shca *shca = dev->ofdev.dev.driver_data;
+ struct ehca_shca *shca = dev->dev.driver_data;
int ret;
- sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+ sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
if (ehca_open_aqp1 == 1) {
int i;
@@ -870,11 +870,11 @@ static struct of_device_id ehca_device_table[] =
{},
};
-static struct ibmebus_driver ehca_driver = {
- .name = "ehca",
- .id_table = ehca_device_table,
- .probe = ehca_probe,
- .remove = ehca_remove,
+static struct of_platform_driver ehca_driver = {
+ .name = "ehca",
+ .match_table = ehca_device_table,
+ .probe = ehca_probe,
+ .remove = ehca_remove,
};
void ehca_poll_eqs(unsigned long data)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 717b129..a4d4150 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -89,10 +89,10 @@ struct workqueue_struct *ehea_driver_wq;
struct work_struct ehea_rereg_mr_task;
-static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
+static int __devinit ehea_probe_adapter(struct of_device *dev,
const struct of_device_id *id);
-static int __devexit ehea_remove(struct ibmebus_dev *dev);
+static int __devexit ehea_remove(struct of_device *dev);
static struct of_device_id ehea_device_table[] = {
{
@@ -102,9 +102,9 @@ static struct of_device_id ehea_device_table[] = {
{},
};
-static struct ibmebus_driver ehea_driver = {
+static struct of_platform_driver ehea_driver = {
.name = "ehea",
- .id_table = ehea_device_table,
+ .match_table = ehea_device_table,
.probe = ehea_probe_adapter,
.remove = ehea_remove,
};
@@ -968,7 +968,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
dev->name);
- ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1,
+ ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
ehea_qp_aff_irq_handler,
IRQF_DISABLED, port->int_aff_name, port);
if (ret) {
@@ -986,7 +986,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
pr = &port->port_res[i];
snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
"%s-queue%d", dev->name, i);
- ret = ibmebus_request_irq(NULL, pr->eq->attr.ist1,
+ ret = ibmebus_request_irq(pr->eq->attr.ist1,
ehea_recv_irq_handler,
IRQF_DISABLED, pr->int_send_name,
pr);
@@ -1007,11 +1007,11 @@ out:
out_free_req:
while (--i >= 0) {
u32 ist = port->port_res[i].eq->attr.ist1;
- ibmebus_free_irq(NULL, ist, &port->port_res[i]);
+ ibmebus_free_irq(ist, &port->port_res[i]);
}
out_free_qpeq:
- ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
+ ibmebus_free_irq(port->qp_eq->attr.ist1, port);
i = port->num_def_qps;
goto out;
@@ -1028,14 +1028,14 @@ static void ehea_free_interrupts(struct net_device *dev)
for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
pr = &port->port_res[i];
- ibmebus_free_irq(NULL, pr->eq->attr.ist1, pr);
+ ibmebus_free_irq(pr->eq->attr.ist1, pr);
if (netif_msg_intr(port))
ehea_info("free send irq for res %d with handle 0x%X",
i, pr->eq->attr.ist1);
}
/* associated events */
- ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
+ ibmebus_free_irq(port->qp_eq->attr.ist1, port);
if (netif_msg_intr(port))
ehea_info("associated event interrupt for handle 0x%X freed",
port->qp_eq->attr.ist1);
@@ -2548,7 +2548,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
int ret;
port->ofdev.node = of_node_get(dn);
- port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev;
+ port->ofdev.dev.parent = &port->adapter->ofdev->dev;
port->ofdev.dev.bus = &ibmebus_bus_type;
sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++);
@@ -2729,7 +2729,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
const u32 *dn_log_port_id;
int i = 0;
- lhea_dn = adapter->ebus_dev->ofdev.node;
+ lhea_dn = adapter->ofdev->node;
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
@@ -2769,7 +2769,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
struct device_node *eth_dn = NULL;
const u32 *dn_log_port_id;
- lhea_dn = adapter->ebus_dev->ofdev.node;
+ lhea_dn = adapter->ofdev->node;
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
@@ -2875,31 +2875,31 @@ static ssize_t ehea_remove_port(struct device *dev,
static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
-int ehea_create_device_sysfs(struct ibmebus_dev *dev)
+int ehea_create_device_sysfs(struct of_device *dev)
{
- int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port);
+ int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
if (ret)
goto out;
- ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port);
+ ret = device_create_file(&dev->dev, &dev_attr_remove_port);
out:
return ret;
}
-void ehea_remove_device_sysfs(struct ibmebus_dev *dev)
+void ehea_remove_device_sysfs(struct of_device *dev)
{
- device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port);
- device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port);
+ device_remove_file(&dev->dev, &dev_attr_probe_port);
+ device_remove_file(&dev->dev, &dev_attr_remove_port);
}
-static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
+static int __devinit ehea_probe_adapter(struct of_device *dev,
const struct of_device_id *id)
{
struct ehea_adapter *adapter;
const u64 *adapter_handle;
int ret;
- if (!dev || !dev->ofdev.node) {
+ if (!dev || !dev->node) {
ehea_error("Invalid ibmebus device probed");
return -EINVAL;
}
@@ -2907,36 +2907,36 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
if (!adapter) {
ret = -ENOMEM;
- dev_err(&dev->ofdev.dev, "no mem for ehea_adapter\n");
+ dev_err(&dev->dev, "no mem for ehea_adapter\n");
goto out;
}
list_add(&adapter->list, &adapter_list);
- adapter->ebus_dev = dev;
+ adapter->ofdev = dev;
- adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
+ adapter_handle = of_get_property(dev->node, "ibm,hea-handle",
NULL);
if (adapter_handle)
adapter->handle = *adapter_handle;
if (!adapter->handle) {
- dev_err(&dev->ofdev.dev, "failed getting handle for adapter"
- " '%s'\n", dev->ofdev.node->full_name);
+ dev_err(&dev->dev, "failed getting handle for adapter"
+ " '%s'\n", dev->node->full_name);
ret = -ENODEV;
goto out_free_ad;
}
adapter->pd = EHEA_PD_ID;
- dev->ofdev.dev.driver_data = adapter;
+ dev->dev.driver_data = adapter;
/* initialize adapter and ports */
/* get adapter properties */
ret = ehea_sense_adapter_attr(adapter);
if (ret) {
- dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret);
+ dev_err(&dev->dev, "sense_adapter_attr failed: %d", ret);
goto out_free_ad;
}
@@ -2944,18 +2944,18 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
if (!adapter->neq) {
ret = -EIO;
- dev_err(&dev->ofdev.dev, "NEQ creation failed");
+ dev_err(&dev->dev, "NEQ creation failed");
goto out_free_ad;
}
tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
(unsigned long)adapter);
- ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1,
+ ret = ibmebus_request_irq(adapter->neq->attr.ist1,
ehea_interrupt_neq, IRQF_DISABLED,
"ehea_neq", adapter);
if (ret) {
- dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed");
+ dev_err(&dev->dev, "requesting NEQ IRQ failed");
goto out_kill_eq;
}
@@ -2971,7 +2971,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
ret = ehea_setup_ports(adapter);
if (ret) {
- dev_err(&dev->ofdev.dev, "setup_ports failed");
+ dev_err(&dev->dev, "setup_ports failed");
goto out_rem_dev_sysfs;
}
@@ -2985,7 +2985,7 @@ out_kill_wq:
destroy_workqueue(adapter->ehea_wq);
out_free_irq:
- ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+ ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
out_kill_eq:
ehea_destroy_eq(adapter->neq);
@@ -2996,9 +2996,9 @@ out:
return ret;
}
-static int __devexit ehea_remove(struct ibmebus_dev *dev)
+static int __devexit ehea_remove(struct of_device *dev)
{
- struct ehea_adapter *adapter = dev->ofdev.dev.driver_data;
+ struct ehea_adapter *adapter = dev->dev.driver_data;
int i;
for (i = 0; i < EHEA_MAX_PORTS; i++)
@@ -3011,7 +3011,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
destroy_workqueue(adapter->ehea_wq);
- ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+ ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
tasklet_kill(&adapter->neq_tasklet);
ehea_destroy_eq(adapter->neq);
--
1.5.2
^ permalink raw reply related
* [PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device
From: Joachim Fenkes @ 2007-09-26 9:45 UTC (permalink / raw)
To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>
The devtree root is now searched for devices matching a built-in whitelist
during boot, so these devices appear on the bus from the beginning. It is
still possible to manually add/remove devices to/from the bus by using the
probe/remove sysfs interface. Also, when a device driver registers itself,
the devtree is matched against its matchlist.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
arch/powerpc/kernel/ibmebus.c | 100 +++++++++++++++++++++++++++++++++-------
1 files changed, 82 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index cc80f84..43d4764 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -51,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */
struct bus_type ibmebus_bus_type;
+/* These devices will automatically be added to the bus during init */
+static struct of_device_id builtin_matches[] = {
+ { .compatible = "IBM,lhca" },
+ { .compatible = "IBM,lhea" },
+ {},
+};
+
static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
@@ -124,6 +131,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported = ibmebus_dma_supported,
};
+static int ibmebus_match_path(struct device *dev, void *data)
+{
+ struct device_node *dn = to_of_device(dev)->node;
+ return (dn->full_name &&
+ (strcasecmp((char *)data, dn->full_name) == 0));
+}
+
+static int ibmebus_match_node(struct device *dev, void *data)
+{
+ return to_of_device(dev)->node == data;
+}
+
+static int ibmebus_create_device(struct device_node *dn)
+{
+ struct of_device *dev;
+ int ret;
+
+ dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->dev.bus = &ibmebus_bus_type;
+ dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
+
+ ret = of_device_register(dev);
+ if (ret) {
+ of_device_free(dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ibmebus_create_devices(const struct of_device_id *matches)
+{
+ struct device_node *root, *child;
+ int ret = 0;
+
+ root = of_find_node_by_path("/");
+
+ for (child = NULL; (child = of_get_next_child(root, child)); ) {
+ if (!of_match_node(matches, child))
+ continue;
+
+ if (bus_find_device(&ibmebus_bus_type, NULL, child,
+ ibmebus_match_node))
+ continue;
+
+ ret = ibmebus_create_device(child);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to create device (%i)",
+ __FUNCTION__, ret);
+ of_node_put(child);
+ break;
+ }
+ }
+
+ of_node_put(root);
+ return ret;
+}
+
int ibmebus_register_driver(struct ibmebus_driver *drv)
{
return 0;
@@ -172,18 +240,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
__ATTR_NULL
};
-static int ibmebus_match_path(struct device *dev, void *data)
-{
- int rc;
- struct device_node *dn =
- of_node_get(to_ibmebus_dev(dev)->ofdev.node);
-
- rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
-
- of_node_put(dn);
- return rc;
-}
-
static char *ibmebus_chomp(const char *in, size_t count)
{
char *out = (char*)kmalloc(count + 1, GFP_KERNEL);
@@ -202,9 +258,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
const char *buf, size_t count)
{
struct device_node *dn = NULL;
- struct ibmebus_dev *dev;
char *path;
- ssize_t rc;
+ ssize_t rc = 0;
path = ibmebus_chomp(buf, count);
if (!path)
@@ -219,9 +274,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
}
if ((dn = of_find_node_by_path(path))) {
-/* dev = ibmebus_register_device_node(dn); */
+ rc = ibmebus_create_device(dn);
of_node_put(dn);
- rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
} else {
printk(KERN_WARNING "%s: no such device node: %s\n",
__FUNCTION__, path);
@@ -230,7 +284,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
out:
kfree(path);
- return rc;
+ if (rc)
+ return rc;
+ return count;
}
static ssize_t ibmebus_store_remove(struct bus_type *bus,
@@ -245,7 +301,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
ibmebus_match_path))) {
-/* ibmebus_unregister_device(dev); */
+ of_device_unregister(to_of_device(dev));
kfree(path);
return count;
@@ -265,6 +321,7 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
};
struct bus_type ibmebus_bus_type = {
+ .uevent = of_device_uevent,
.dev_attrs = ibmebus_dev_attrs,
.bus_attrs = ibmebus_bus_attrs
};
@@ -292,6 +349,13 @@ static int __init ibmebus_bus_init(void)
return err;
}
+ err = ibmebus_create_devices(builtin_matches);
+ if (err) {
+ device_unregister(&ibmebus_bus_device);
+ bus_unregister(&ibmebus_bus_type);
+ return err;
+ }
+
return 0;
}
postcore_initcall(ibmebus_bus_init);
--
1.5.2
^ permalink raw reply related
* [PATCH 2/5] ibmebus: Remove bus match/probe/remove functions
From: Joachim Fenkes @ 2007-09-26 9:44 UTC (permalink / raw)
To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>
Remove old code that will be replaced by rewritten and shorter functions in
the next patch. Keep struct ibmebus_dev and struct ibmebus_driver for now,
but replace ibmebus_{,un}register_driver() by dummy functions. This way, the
kernel will still compile and run during the transition and git bisect will
be happy.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
arch/powerpc/kernel/ibmebus.c | 199 ++---------------------------------------
1 files changed, 6 insertions(+), 193 deletions(-)
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index d6a38cd..cc80f84 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -41,6 +41,7 @@
#include <linux/kobject.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/of_platform.h>
#include <asm/ibmebus.h>
#include <asm/abs_addr.h>
@@ -123,183 +124,14 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
.dma_supported = ibmebus_dma_supported,
};
-static int ibmebus_bus_probe(struct device *dev)
-{
- struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
- struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
- const struct of_device_id *id;
- int error = -ENODEV;
-
- if (!ibmebusdrv->probe)
- return error;
-
- id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
- if (id) {
- error = ibmebusdrv->probe(ibmebusdev, id);
- }
-
- return error;
-}
-
-static int ibmebus_bus_remove(struct device *dev)
-{
- struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
- struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-
- if (ibmebusdrv->remove) {
- return ibmebusdrv->remove(ibmebusdev);
- }
-
- return 0;
-}
-
-static void __devinit ibmebus_dev_release(struct device *dev)
-{
- of_node_put(to_ibmebus_dev(dev)->ofdev.node);
- kfree(to_ibmebus_dev(dev));
-}
-
-static int __devinit ibmebus_register_device_common(
- struct ibmebus_dev *dev, const char *name)
-{
- int err = 0;
-
- dev->ofdev.dev.parent = &ibmebus_bus_device;
- dev->ofdev.dev.bus = &ibmebus_bus_type;
- dev->ofdev.dev.release = ibmebus_dev_release;
-
- dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
- dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
- dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
-
- /* An ibmebusdev is based on a of_device. We have to change the
- * bus type to use our own DMA mapping operations.
- */
- if ((err = of_device_register(&dev->ofdev)) != 0) {
- printk(KERN_ERR "%s: failed to register device (%d).\n",
- __FUNCTION__, err);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static struct ibmebus_dev* __devinit ibmebus_register_device_node(
- struct device_node *dn)
-{
- struct ibmebus_dev *dev;
- int i, len, bus_len;
-
- dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- dev->ofdev.node = of_node_get(dn);
-
- len = strlen(dn->full_name + 1);
- bus_len = min(len, BUS_ID_SIZE - 1);
- memcpy(dev->ofdev.dev.bus_id, dn->full_name + 1
- + (len - bus_len), bus_len);
- for (i = 0; i < bus_len; i++)
- if (dev->ofdev.dev.bus_id[i] == '/')
- dev->ofdev.dev.bus_id[i] = '_';
-
- /* Register with generic device framework. */
- if (ibmebus_register_device_common(dev, dn->name) != 0) {
- kfree(dev);
- return ERR_PTR(-ENODEV);
- }
-
- return dev;
-}
-
-static void ibmebus_probe_of_nodes(char* name)
-{
- struct device_node *dn = NULL;
-
- while ((dn = of_find_node_by_name(dn, name))) {
- if (IS_ERR(ibmebus_register_device_node(dn))) {
- of_node_put(dn);
- return;
- }
- }
-
- of_node_put(dn);
-
- return;
-}
-
-static void ibmebus_add_devices_by_id(struct of_device_id *idt)
-{
- while (strlen(idt->name) > 0) {
- ibmebus_probe_of_nodes(idt->name);
- idt++;
- }
-
- return;
-}
-
-static int ibmebus_match_name(struct device *dev, void *data)
-{
- const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
- const char *name;
-
- name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
-
- if (name && (strcmp(data, name) == 0))
- return 1;
-
- return 0;
-}
-
-static int ibmebus_unregister_device(struct device *dev)
-{
- of_device_unregister(to_of_device(dev));
-
- return 0;
-}
-
-static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
-{
- struct device *dev;
-
- while (strlen(idt->name) > 0) {
- while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
- (void*)idt->name,
- ibmebus_match_name))) {
- ibmebus_unregister_device(dev);
- }
- idt++;
- }
-
- return;
-}
-
int ibmebus_register_driver(struct ibmebus_driver *drv)
{
- int err = 0;
-
- drv->driver.name = drv->name;
- drv->driver.bus = &ibmebus_bus_type;
- drv->driver.probe = ibmebus_bus_probe;
- drv->driver.remove = ibmebus_bus_remove;
-
- if ((err = driver_register(&drv->driver) != 0))
- return err;
-
- /* remove all supported devices first, in case someone
- * probed them manually before registering the driver */
- ibmebus_remove_devices_by_id(drv->id_table);
- ibmebus_add_devices_by_id(drv->id_table);
-
return 0;
}
EXPORT_SYMBOL(ibmebus_register_driver);
void ibmebus_unregister_driver(struct ibmebus_driver *drv)
{
- driver_unregister(&drv->driver);
- ibmebus_remove_devices_by_id(drv->id_table);
}
EXPORT_SYMBOL(ibmebus_unregister_driver);
@@ -327,23 +159,6 @@ void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
}
EXPORT_SYMBOL(ibmebus_free_irq);
-static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
-{
- const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
- struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
- const struct of_device_id *ids = ebus_drv->id_table;
- const struct of_device_id *found_id;
-
- if (!ids)
- return 0;
-
- found_id = of_match_device(ids, &ebus_dev->ofdev);
- if (found_id)
- return 1;
-
- return 0;
-}
-
static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -404,7 +219,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
}
if ((dn = of_find_node_by_path(path))) {
- dev = ibmebus_register_device_node(dn);
+/* dev = ibmebus_register_device_node(dn); */
of_node_put(dn);
rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
} else {
@@ -430,7 +245,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
ibmebus_match_path))) {
- ibmebus_unregister_device(dev);
+/* ibmebus_unregister_device(dev); */
kfree(path);
return count;
@@ -450,8 +265,6 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
};
struct bus_type ibmebus_bus_type = {
- .name = "ibmebus",
- .match = ibmebus_bus_match,
.dev_attrs = ibmebus_dev_attrs,
.bus_attrs = ibmebus_bus_attrs
};
@@ -463,9 +276,9 @@ static int __init ibmebus_bus_init(void)
printk(KERN_INFO "IBM eBus Device Driver\n");
- err = bus_register(&ibmebus_bus_type);
+ err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
if (err) {
- printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
+ printk(KERN_ERR "%s: failed to register IBM eBus.\n",
__FUNCTION__);
return err;
}
@@ -481,4 +294,4 @@ static int __init ibmebus_bus_init(void)
return 0;
}
-__initcall(ibmebus_bus_init);
+postcore_initcall(ibmebus_bus_init);
--
1.5.2
^ permalink raw reply related
* [PATCH 1/5] PowerPC: Move of_device allocation into of_device.[ch]
From: Joachim Fenkes @ 2007-09-26 9:44 UTC (permalink / raw)
To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>
Extract generic of_device allocation code from of_platform_device_create()
and move it into of_device.[ch], called of_device_alloc(). Also, there's now
of_device_free() which puts the device node.
This way, bus drivers that build on of_platform (like ibmebus will) can
build upon this code instead of reinventing the wheel.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
include/asm-powerpc/of_device.h | 4 ++
include/linux/of_device.h | 5 ++
arch/powerpc/kernel/of_device.c | 80 +++++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/of_platform.c | 70 +-------------------------------
4 files changed, 91 insertions(+), 68 deletions(-)
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index ec2a8a2..9ab469d 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -17,6 +17,10 @@ struct of_device
struct device dev; /* Generic device interface */
};
+extern struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent);
+
extern ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len);
extern int of_device_uevent(struct device *dev,
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 91bf84b..212bffb 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev);
extern void of_device_unregister(struct of_device *ofdev);
extern void of_release_dev(struct device *dev);
+static inline void of_device_free(struct of_device *dev)
+{
+ of_release_dev(&dev->dev);
+}
+
#endif /* __KERNEL__ */
#endif /* _LINUX_OF_DEVICE_H */
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 89b911e..ecb8b0e 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -7,8 +7,88 @@
#include <linux/slab.h>
#include <asm/errno.h>
+#include <asm/dcr.h>
#include <asm/of_device.h>
+static void of_device_make_bus_id(struct of_device *dev)
+{
+ static atomic_t bus_no_reg_magic;
+ struct device_node *node = dev->node;
+ char *name = dev->dev.bus_id;
+ const u32 *reg;
+ u64 addr;
+ int magic;
+
+ /*
+ * If it's a DCR based device, use 'd' for native DCRs
+ * and 'D' for MMIO DCRs.
+ */
+#ifdef CONFIG_PPC_DCR
+ reg = of_get_property(node, "dcr-reg", NULL);
+ if (reg) {
+#ifdef CONFIG_PPC_DCR_NATIVE
+ snprintf(name, BUS_ID_SIZE, "d%x.%s",
+ *reg, node->name);
+#else /* CONFIG_PPC_DCR_NATIVE */
+ addr = of_translate_dcr_address(node, *reg, NULL);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "D%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+#endif /* !CONFIG_PPC_DCR_NATIVE */
+ }
+#endif /* CONFIG_PPC_DCR */
+
+ /*
+ * For MMIO, get the physical address
+ */
+ reg = of_get_property(node, "reg", NULL);
+ if (reg) {
+ addr = of_translate_address(node, reg);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+ }
+
+ /*
+ * No BusID, use the node name and add a globally incremented
+ * counter (and pray...)
+ */
+ magic = atomic_add_return(1, &bus_no_reg_magic);
+ snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+}
+
+struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ struct of_device *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->node = of_node_get(np);
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.parent = parent;
+ dev->dev.release = of_release_dev;
+ dev->dev.archdata.of_node = np;
+ dev->dev.archdata.numa_node = of_node_to_nid(np);
+
+ if (bus_id)
+ strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+ else
+ of_device_make_bus_id(dev);
+
+ return dev;
+}
+EXPORT_SYMBOL(of_device_alloc);
+
ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len)
{
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index f70e787..1d96b82 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -21,7 +21,6 @@
#include <linux/pci.h>
#include <asm/errno.h>
-#include <asm/dcr.h>
#include <asm/of_device.h>
#include <asm/of_platform.h>
#include <asm/topology.h>
@@ -53,8 +52,6 @@ static struct of_device_id of_default_bus_ids[] = {
{},
};
-static atomic_t bus_no_reg_magic;
-
struct bus_type of_platform_bus_type = {
.uevent = of_device_uevent,
};
@@ -84,89 +81,26 @@ void of_unregister_platform_driver(struct of_platform_driver *drv)
}
EXPORT_SYMBOL(of_unregister_platform_driver);
-static void of_platform_make_bus_id(struct of_device *dev)
-{
- struct device_node *node = dev->node;
- char *name = dev->dev.bus_id;
- const u32 *reg;
- u64 addr;
- int magic;
-
- /*
- * If it's a DCR based device, use 'd' for native DCRs
- * and 'D' for MMIO DCRs.
- */
-#ifdef CONFIG_PPC_DCR
- reg = of_get_property(node, "dcr-reg", NULL);
- if (reg) {
-#ifdef CONFIG_PPC_DCR_NATIVE
- snprintf(name, BUS_ID_SIZE, "d%x.%s",
- *reg, node->name);
-#else /* CONFIG_PPC_DCR_NATIVE */
- addr = of_translate_dcr_address(node, *reg, NULL);
- if (addr != OF_BAD_ADDR) {
- snprintf(name, BUS_ID_SIZE,
- "D%llx.%s", (unsigned long long)addr,
- node->name);
- return;
- }
-#endif /* !CONFIG_PPC_DCR_NATIVE */
- }
-#endif /* CONFIG_PPC_DCR */
-
- /*
- * For MMIO, get the physical address
- */
- reg = of_get_property(node, "reg", NULL);
- if (reg) {
- addr = of_translate_address(node, reg);
- if (addr != OF_BAD_ADDR) {
- snprintf(name, BUS_ID_SIZE,
- "%llx.%s", (unsigned long long)addr,
- node->name);
- return;
- }
- }
-
- /*
- * No BusID, use the node name and add a globally incremented
- * counter (and pray...)
- */
- magic = atomic_add_return(1, &bus_no_reg_magic);
- snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
-}
-
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent)
{
struct of_device *dev;
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = of_device_alloc(np, bus_id, parent);
if (!dev)
return NULL;
- dev->node = of_node_get(np);
dev->dma_mask = 0xffffffffUL;
- dev->dev.dma_mask = &dev->dma_mask;
- dev->dev.parent = parent;
dev->dev.bus = &of_platform_bus_type;
- dev->dev.release = of_release_dev;
- dev->dev.archdata.of_node = np;
- dev->dev.archdata.numa_node = of_node_to_nid(np);
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such, possibly using a device notifier
*/
- if (bus_id)
- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
- else
- of_platform_make_bus_id(dev);
-
if (of_device_register(dev) != 0) {
- kfree(dev);
+ of_device_free(dev);
return NULL;
}
--
1.5.2
^ permalink raw reply related
* [PATCH 0/5] [REPOST] PowerPC: ibmebus refactoring and fixes
From: Joachim Fenkes @ 2007-09-26 9:43 UTC (permalink / raw)
To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
Stefan Roscher
This patchset will merge the ibmebus and of_platform bus drivers by basing a
lot of ibmebus functionality on of_platform code and adding the features
specific to ibmebus on top of that.
This is a repost of my previous patchset incorporating Arnd's comments.
I split the actual ibmebus rework into three patches (2/5-4/5) for easier
readability. The kernel will compile during the intermediate states, and
ibmebus will not crash, but not work either.
As a side-effect of patch 3/5, a problem with bus_id collisions in case of
two devices sharing the same location code is resolved -- the bus_id is now
determined differently.
[1/5] moves of_device allocation into of_device.[ch]
[2/5] removes the old bus match/probe/remove functions
[3/5] adds device creation and bus probing based on of_device
[4/5] finally moves to of_device and of_platform_driver by changing
ibmebus.h and matching the eHCA and eHEA drivers
[5/5] just changes a nit in ibmebus_store_probe()
These patches should apply cleanly, in order, against 2.6.23-rc5 and against
Linus' git. Please review and comment them, and queue them up for 2.6.24 if
you think they're okay.
Thanks and regards,
Joachim
arch/powerpc/kernel/ibmebus.c | 267 ++++++++-----------------=
=2D---
arch/powerpc/kernel/of_device.c | 80 +++++++++
arch/powerpc/kernel/of_platform.c | 70 +--------
drivers/infiniband/hw/ehca/ehca_classes.h | 2 +-
drivers/infiniband/hw/ehca/ehca_eq.c | 6 +-
drivers/infiniband/hw/ehca/ehca_main.c | 32 ++--
drivers/net/ehea/ehea.h | 2 +-
drivers/net/ehea/ehea_main.c | 72 ++++----
include/asm-powerpc/ibmebus.h | 38 +----
include/asm-powerpc/of_device.h | 4 +
include/linux/of_device.h | 5 +
11 files changed, 228 insertions(+), 350 deletions(-)
=2D-=20
Joachim Fenkes =A0-- =A0eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH =A0-- =A0Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220 =A0-- =A071032 Boeblingen =A0-- =A0Germany
eMail: fenkes@de.ibm.com
^ permalink raw reply
* Re: [PATCH 1/5] PowerPC: Move of_device allocation into of_device.[ch]
From: Joachim Fenkes @ 2007-09-26 9:07 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Thomas Q Klein, Paul Mackerras, Jan-Bernd Themann, LKML,
linuxppc-dev, Christoph Raisch, Paul Mackerras, Stefan Roscher
In-Reply-To: <200709251627.59040.arnd@arndb.de>
Arnd Bergmann <arnd@arndb.de> wrote on 25.09.2007 16:27:57:
> The patch looks good to me, especially since you did exactly what I
> suggested ;-)
Yes, our discussions were very productive. Thanks and sorry I forgot to
mention your input.
> Maybe the description should have another sentence in it about what
> the change is good for. You have that in the 0/5 mail, but that does
> not go into the changelog, so the information gets lost in the process.
Can do. New patch coming right up!
Joachim
^ permalink raw reply
* Re: [PATCH 2/5] ibmebus: Remove bus match/probe/remove functions
From: Joachim Fenkes @ 2007-09-26 9:04 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Thomas Q Klein, Paul Mackerras, Jan-Bernd Themann, LKML,
linuxppc-dev, Christoph Raisch, Paul Mackerras, Stefan Roscher
In-Reply-To: <200709251629.52376.arnd@arndb.de>
Arnd Bergmann <arnd@arndb.de> wrote on 25.09.2007 16:29:51:
> The description makes it sound like a git-bisect would get broken
> by this patch, which should never happen. If the patch indeed
> ends up with a broken kernel, it would be better to merge it with
> the later patch that fixes the code again.
I took extra care to prevent just that from happening. ibmebus will simply
be disabled during the transition (because of {un,}register_driver being
empty dummies), but the kernel builds and boots without problems. So
unless you're trying to find an ibmebus-based problem, git bisect will be
fine. I'll repost 2/5 with an updated description.
I split the ibmebus rework into three patches because the merged patch was
impossible to read. Makes reviewing easier.
Joachim
^ permalink raw reply
* Re: [PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device
From: Joachim Fenkes @ 2007-09-26 8:58 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Thomas Q Klein, Paul Mackerras, Jan-Bernd Themann, LKML,
linuxppc-dev, Christoph Raisch, Paul Mackerras, Stefan Roscher
In-Reply-To: <200709251639.06414.arnd@arndb.de>
> > +/* These devices will automatically be added to the bus during init
*/
> > +static struct of_device_id builtin_matches[] = {
> > + { .name = "lhca" },
> > + { .compatible = "IBM,lhca" },
> > + { .name = "lhea" },
> > + { .compatible = "IBM,lhea" },
> > + {},
> > +};
> > +
>
> Hmm, do you have devices that only have the matching name property
> but not the compatible property? If not, I'd suggest only looking
> for compatible, so you have less chance of false positives.
If a device that's not an lhca is called "lhca", that's its own fault, i
guess ;) But i concur that looking for the compatible property will
probably suffice.
> > +static int ibmebus_create_device(struct device_node *dn)
> > [...]
>
> nice!
Thanks.
> > - rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
> > + rc = rc ? rc : count;
>
> the last line looks a bit silly. Maybe instead do
>
> rc = ibmebus_create_device(dn);
> of_node_put(dn);
> }
>
> kfree(path);
> if (rc)
> return rc;
> return count;
> }
More code lines? ;) But yes, that looks more like "standard kernel
pattern" - I'll change that.
Joachim
^ permalink raw reply
* Re: [PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers
From: Joachim Fenkes @ 2007-09-26 8:43 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Thomas Q Klein, Paul Mackerras, Jan-Bernd Themann, LKML,
linuxppc-dev, Christoph Raisch, Paul Mackerras, Stefan Roscher
In-Reply-To: <200709251642.41480.arnd@arndb.de>
Arnd Bergmann <arnd@arndb.de> wrote on 25.09.2007 16:42:40:
> This is missing a description,
The description is "ibmebus: Move to of_device and of_platform_driver,
match eHCA and eHEA drivers" -- I thought that should be enough since the
patch is rather straightforward. I can add a more detailed description,
though. Revised patch will follow.
> but the patch looks good.
Thanks =)
Joachim
^ permalink raw reply
* Re: [patch 5/7] Use extended crashkernel command line on ppc64
From: Bernhard Walle @ 2007-09-26 8:15 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-arch, linuxppc-dev, kexec, linux-kernel
In-Reply-To: <20070925124534.b9da41a2.akpm@linux-foundation.org>
Hi,
* Andrew Morton <akpm@linux-foundation.org> [2007-09-25 21:45]:
> On Tue, 25 Sep 2007 20:23:02 +0200 Bernhard Walle <bwalle@suse.de> wrote:
>
> > This patch adapts the ppc64 code to use the generic parse_crashkernel()
> > function introduced in the generic patch of that series.
>
> I really don't like to see patches get a wholesale replacement, especially
> when they've been looked at by a few people and have had some testing, etc.
> It's not possible to see what changed and people need to re-review stuff
> they've already reviewed, etc.
Sorry, I didn't know that this is the preferred way. I just thought
it's more clear if the patches are replaced if the patch set is
finally pushed into Linus' tree.
> diff -puN arch/powerpc/kernel/machine_kexec.c~use-extended-crashkernel-command-line-on-ppc64-update arch/powerpc/kernel/machine_kexec.c
> --- a/arch/powerpc/kernel/machine_kexec.c~use-extended-crashkernel-command-line-on-ppc64-update
> +++ a/arch/powerpc/kernel/machine_kexec.c
> @@ -63,7 +63,7 @@ NORET_TYPE void machine_kexec(struct kim
>
> void __init reserve_crashkernel(void)
> {
> - unsigned long long crash_size = 0, crash_base;
> + unsigned long long crash_size, crash_base;
> int ret;
>
> /* this is necessary because of lmb_phys_mem_size() */
> _
>
>
> which I suspect will now create a compiler warning.
No, it doesn't. I just verified this.
CHK include/linux/compile.h
CC arch/powerpc/kernel/machine_kexec.o
LD arch/powerpc/kernel/built-in.o
Thanks,
Bernhard
--
Bernhard Walle <bwalle@suse.de>, Architecture Maintenance
SUSE LINUX Products GmbH, Nürnberg, Germany
GF: Markus Rex, HRB 16746 (AG Nürnberg)
OpenPGP: F61F 34CC 09CA FB82 C9F6 BA4B 8865 3696 DDAF 6454
^ permalink raw reply
* Re: [PATCH] add Altivec/VMX state to coredumps
From: Geert Uytterhoeven @ 2007-09-26 7:42 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Carlos Eduardo Seo
In-Reply-To: <8FC0C4ED-3268-467C-A3EF-0336082062E1@kernel.crashing.org>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1056 bytes --]
On Wed, 26 Sep 2007, Kumar Gala wrote:
> On Sep 25, 2007, at 11:56 PM, Mark Nelson wrote:
> > What cores have SPE at the moment? Also, perhaps more importantly,
> > are there any plans to have Altivec and SPE in the same core?
>
> The e500 cores's from Freescale.
>
> No, they are pretty much mutually exclusive.
Bummer, only now do I realize this thread is not about the Synergistic
Processing Elements but about the Signal Processing Extension...
With kind regards,
Geert Uytterhoeven
Software Architect
Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/
Sony Network and Software Technology Center Europe
A division of Sony Service Centre (Europe) N.V.
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium
VAT BE 0413.825.160 · RPR Brussels
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619
^ permalink raw reply
* Re: [PATCH 1/15] boot: find initrd location from device-tree
From: Milton Miller @ 2007-09-26 5:49 UTC (permalink / raw)
To: David Gibson; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <20070925032705.GA2525@localhost.localdomain>
On Sep 24, 2007, at 10:27 PM, David Gibson wrote:
> On Mon, Sep 24, 2007 at 03:02:36AM -0500, Milton Miller wrote:
>>
>> On Sep 23, 2007, at 9:58 PM, David Gibson wrote:
>>
>>> On Fri, Sep 21, 2007 at 06:03:24PM -0500, Milton Miller wrote:
>>>> Some platforms have a boot agent that can create or modify
>>>> properties
>>>> in
>>>> the device-tree and load images into memory. Provide a helper to
>>>> set
>>>> loader_info used by prep_initrd().
>>>>
>>>> Signed-off-by: Milton Miller <miltonm@bga.com>
>>>> Acked-by: David Gibson <david@gibson.dropbear.id.au>
>>>
>>> Hrm, despite my earlier ack, I'm going to whinge about a few nits
>>> here.
>>>
>>>> ---
>>>> re 12168
>>>> rediffed types.h, offset in ops.h
>>>>
>>>> Index: kernel/arch/powerpc/boot/ops.h
>>>> ===================================================================
>>>> --- kernel.orig/arch/powerpc/boot/ops.h 2007-09-17
>>>> 22:12:47.000000000
>>>> -0500
>>>> +++ kernel/arch/powerpc/boot/ops.h 2007-09-17 22:12:51.000000000
>>>> -0500
>>>> @@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3
>>>> void __dt_fixup_mac_addresses(u32 startindex, ...);
>>>> #define dt_fixup_mac_addresses(...) \
>>>> __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
>>>> +void dt_find_initrd(void);
>>>>
>>>>
>>>> static inline void *find_node_by_linuxphandle(const u32
>>>> linuxphandle)
>>>> Index: kernel/arch/powerpc/boot/types.h
>>>> ===================================================================
>>>> --- kernel.orig/arch/powerpc/boot/types.h 2007-09-17
>>>> 22:12:47.000000000 -0500
>>>> +++ kernel/arch/powerpc/boot/types.h 2007-09-17 22:12:51.000000000
>>>> -0500
>>>> @@ -12,6 +12,8 @@ typedef short s16;
>>>> typedef int s32;
>>>> typedef long long s64;
>>>>
>>>> +#define UINT_MAX 0xFFFFFFFF
>>>
>>> I actually don't like this constant - at the point you compare you
>>> care, explicitly, about the value not being over 32-bits, rather than
>>> whether it fits a uint, so the named constant is more misleading than
>>> helpful.
>>
>> Arguable, I don't like counting F's or zeros in C code.
>
> So check if (addr >> 32) is non-zero.
>
>> It is used as the max address that the wrapper deals with, both here
>> and memranges, which happens to be 32 bits.
>
> Right and the reasons for that being the value it is are not because
> it also hapeens to be the max uint *or* ulong.
Huh? the code is checking that the value will fit in the ulongs that
are the type that stores this value in the struct. Are you aruging for
max_ptr_type? If the code were compiled LP64 then it would not need
to check that the address was 32 bits. Here you say "check for 32
bits", while below ...
>
>> Actually it cares about overflowing the unsigned long in loader_info,
>> not that the address fits in 32 bits.
>>
>> So it should be ULONG_MAX now (malloc and all the address code was
>> changed to use unsigned long instead of unsigned int since the patch
>> was written).
>>
>> And dt_xlate needs the same information. Its is using a hardcoded 64
>> bit constant to provide the a simiar check.
>>
>>
>>>> +
>>>> #define min(x,y) ({ \
>>>> typeof(x) _x = (x); \
>>>> typeof(y) _y = (y); \
>>>> Index: kernel/arch/powerpc/boot/devtree.c
>>>> ===================================================================
>>>> --- kernel.orig/arch/powerpc/boot/devtree.c 2007-09-17
>>>> 22:12:47.000000000 -0500
>>>> +++ kernel/arch/powerpc/boot/devtree.c 2007-09-17 22:12:51.000000000
>>>> -0500
>>>> @@ -1,6 +1,7 @@
>>>> /*
>>>> * devtree.c - convenience functions for device tree manipulation
>>>> * Copyright 2007 David Gibson, IBM Corporation.
>>>> + * Copyright 2007 Milton Miller, IBM Corporation.
>>>> * Copyright (c) 2007 Freescale Semiconductor, Inc.
>>>> *
>>>> * Authors: David Gibson <david@gibson.dropbear.id.au>
>>>> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const c
>>>>
>>>> return 0;
>>>> }
>>>> +
>>>> +/**
>>>> + * dt_find_initrd - set loader initrd location based on existing
>>>> properties
>>>> + *
>>>> + * finds the linux,initrd-start and linux,initrd-end properties in
>>>> + * the /chosen node and sets the loader initrd fields accordingly.
>>>> + *
>>>> + * Use this if your loader sets the properties to allow other code
>>>> to
>>>> + * relocate the tree and/or cause r3 and r4 to be set on true OF
>>>> + * platforms.
>>>
>>> I am unable to make sense of the paragraph above.
>>
>> The phrase "relocate the tree" should be "relocate the initrd", which
>> the wrapper will do if it located below vmlinux.size. Also, r3 and r4
>> need to be set when booting the kernel from a client interface with an
>> initrd so it can take it into consideration when choosing the location
>> to build the flat tree.
>>
>> How about:
>>
>> Filling in the loader info allows main.c to be aware of the initrd,
>> meaning prep_initrd will move the initrd if it will be overwritten
>> when
>> the kernel is copied to its runtime location. In addition, if you are
>> booting the kernel from a client interface instead of a flat device
>> tree, this also causes r3 and r4 to be set so the kernel can avoid
>> overwriting the initrd when creating the flat tree.
>
> Clearer, but I still don't see that it says anything useful - "finds
> the initrd from the devtree and does all the things that are supposed
> to be done with an initrd" - which is implied in the previous
> paragraph.
I was tring to point out there is additional processing that is done
when the bootwrapper is aware of the initrd, as opposed to the kernel
finding it after it processes the flattened the tree. suggestions?
>>>> + */
>>>> +void dt_find_initrd(void)
>>>> +{
>>>> + int rc;
>>>> + unsigned long long initrd_start, initrd_end;
>>>> + void *devp;
>>>> + static const char start_prop[] = "linux,initrd-start";
>>>> + static const char end_prop[] = "linux,initrd-end";
>>>
>>> I think these constants are more obscuring than useful.
>>
>> They are useful to the extent they reduce the number of source
>> characters causing about 8 less line wraps. Since they are used
>> multiple places, the compiler only needs to emit one copy of this byte
>> sequence. Admitedly you made this point in a prior review.
>
> The compiler is perfectly capable of folding identical string
> constants.
Yes it is, but are you going to leave the constant strings as %s in the
printf strings?
Maybe i shold create a function that takes the property and returns the
int if its either 32 or 64 bits, calling it twice?
>>>> +
>>>> + devp = finddevice("/chosen");
>>>> + if (! devp) {
>>>> + return;
>>>> + }
>>>
>>> CodingStyle would not put { } here.
>>
>> Yea, nit. not sure why I have the braces there, I usually follow that
>> one. And what's that space doing after !?
>>
>>>
>>>> +
>>>> + rc = getprop(devp, start_prop, &initrd_start,
>>>> sizeof(initrd_start));
>>>> + if (rc < 0)
>>>> + return; /* not found */
>>>> + /* The properties had to be 8 bytes until 2.6.22 */
>>>> + if (rc == sizeof(unsigned long)) {
>>>> + unsigned long tmp;
>>>> + memcpy(&tmp, &initrd_start, rc);
>>>> + initrd_start = tmp;
>>>> + } else if (rc != sizeof(initrd_start)) { /* now they
>>>> can be 4 */
>>>
>>> Right. 8 bytes and 4 bytes, so you should be using explicit length
>>> types instead of long and long long.
>>
>> Ok, I guess we ahve u32 and u64 in types.h now. But there is other
>> code in the wrapper that assumes its compiled 32 bit ILP.
>
> Yes, but that's no reason to propagate the sin.
HAH! so abvoe you are tring to get me to hard code in 32 bits, and now
you argue that long == 32 bits is "sinful"?
>
>>>> + printf("unexpected length of %s in /chosen!\n\r", start_prop);
>>>> + return;
>>>
>>> All these printf() / return stanzas add a lot of verbosity to this
>>> function. Any way they can be consolidated a bit, maybe a single
>>> error path that just prints the property values, so the user can
>>> figure out what was wrong with them.
>>
>> On a prior review I got asked to split the reasons for ingoring the
>> values below (the > 32 bit address from end < start cases). Admitedly
>> without all the detailed errors the justification for the string
>> varables is reduced.
>
> Hrm. Well, I can't say I'm entirely convinced either way on this
> one. I guess I'll think about it again once the rest is cleaned up.
I'll make some of these changes when I get back to work (been at the
power.org conference), but I still think ulong_max is the correct
check.
milton
^ permalink raw reply
* Re: [PATCH] add Altivec/VMX state to coredumps
From: Kumar Gala @ 2007-09-26 5:37 UTC (permalink / raw)
To: Mark Nelson; +Cc: linuxppc-dev, Carlos Eduardo Seo
In-Reply-To: <46F9E67C.4070209@au1.ibm.com>
On Sep 25, 2007, at 11:56 PM, Mark Nelson wrote:
> Kumar Gala wrote:
>>
>> On Sep 25, 2007, at 8:22 PM, Mark Nelson wrote:
>>
>>> Kumar Gala wrote:
>>>>
>>>> On Sep 24, 2007, at 11:03 PM, Mark Nelson wrote:
>>>>
>>>>> Update dump_task_altivec() (that has so far never been put to use)
>>>>> so that it dumps the Altivec/VMX registers (VR[0] - VR[31], VSCR
>>>>> and VRSAVE) in the same format as the ptrace get_vrregs() and add
>>>>> the appropriate glue typedefs and #defines to
>>>>> include/asm-powerpc/elf.h for it to work.
>>>>
>>>> Is there some way to tell if the core dump has altivec registers
>>>> state
>>>> in it?
>>>>
>>>> I'm wondering how we distinguish a core dump w/altivec state vs
>>>> one with
>>>> SPE state.
>>>>
>>>> - k
>>>>
>>>>
>>>
>>> If the core dump has the Altivec registers saved in there it will
>>> have a
>>> note called LINUX as shown below:
>>>
>>> $ readelf -n core
>>>
>>> Notes at offset 0x000002b4 with length 0x000005c8:
>>> Owner Data size Description
>>> CORE 0x0000010c NT_PRSTATUS (prstatus structure)
>>> CORE 0x00000080 NT_PRPSINFO (prpsinfo structure)
>>> CORE 0x000000b0 NT_AUXV (auxiliary vector)
>>> CORE 0x00000108 NT_FPREGSET (floating point
>>> registers)
>>> LINUX 0x00000220 NT_PRXFPREG (user_xfpregs structure)
>>>
>>> This mirrors what occurs with the SSE registers on i386 core
>>> dumps in
>>> order to keep things as similar as possible.
>>>
>>> I can't find any place where dump_spe() is called at the moment,
>>> but I
>>> suppose if it were to be hooked up in the future it could cause
>>> confusion.
>>> The Altivec register state in the core file is much larger than what
>>> would be dumped by the current dump_spe(), but I'm not sure if that
>>> matters...
>>>
>>> There's a patch for GDB that currently reads the contents of
>>> these vector
>>> registers from the core file, but it's being held until this
>>> patch has
>>> been commented on and/or approved of, so if it comes to it the
>>> note name
>>> could be changed to ALTIVEC (or something similar).
>>
>> I think we should NOT overload NT_PRXFPREG and add proper note types
>> NT_ALTIVEC & NT_SPE for those register sets.
>>
>> Who on the GDB side would we need to coordinate such a change with?
>>
>> - k
>>
>
> You're probably right :)
>
> What cores have SPE at the moment? Also, perhaps more importantly,
> are there any plans to have Altivec and SPE in the same core?
The e500 cores's from Freescale.
No, they are pretty much mutually exclusive.
> I've been working with Carlos Eduardo Seo (Cc'ed on this mail) on
> the GDB side of this.
From comments it looks like the expectation is that the combination
of note type and name which is expected to be unique.
I'm wondering if we should handle this via
elf_coredump_extra_notes_size() & elf_coredump_extra_notes_write().
Does GDB care about the order it sees the various sections in?
- k
^ permalink raw reply
* Re: dtc: Use a custom name for lexer output
From: David Gibson @ 2007-09-26 5:25 UTC (permalink / raw)
To: Jon Loeliger, linuxppc-dev
In-Reply-To: <20070926040554.GA32097@localhost.localdomain>
On Wed, Sep 26, 2007 at 02:05:54PM +1000, David Gibson wrote:
> This patch makes dtc use the name dtc-lexer.lex.c for the flex output,
> instead of the default lex.yy.c. If nothing else that makes the
> filename more obvious when/if dtc is embedded into other projects.
>
> It also explicitly requests flex as the lexer generator, rather than
> using make's default $(LEX).
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Jon, sorry, please ignore this. Better version coming.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] add Altivec/VMX state to coredumps
From: Mark Nelson @ 2007-09-26 4:56 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Carlos Eduardo Seo
In-Reply-To: <1B211071-5D55-4DBC-A109-7A66EC17A810@kernel.crashing.org>
Kumar Gala wrote:
>
> On Sep 25, 2007, at 8:22 PM, Mark Nelson wrote:
>
>> Kumar Gala wrote:
>>>
>>> On Sep 24, 2007, at 11:03 PM, Mark Nelson wrote:
>>>
>>>> Update dump_task_altivec() (that has so far never been put to use)
>>>> so that it dumps the Altivec/VMX registers (VR[0] - VR[31], VSCR
>>>> and VRSAVE) in the same format as the ptrace get_vrregs() and add
>>>> the appropriate glue typedefs and #defines to
>>>> include/asm-powerpc/elf.h for it to work.
>>>
>>> Is there some way to tell if the core dump has altivec registers state
>>> in it?
>>>
>>> I'm wondering how we distinguish a core dump w/altivec state vs one with
>>> SPE state.
>>>
>>> - k
>>>
>>>
>>
>> If the core dump has the Altivec registers saved in there it will have a
>> note called LINUX as shown below:
>>
>> $ readelf -n core
>>
>> Notes at offset 0x000002b4 with length 0x000005c8:
>> Owner Data size Description
>> CORE 0x0000010c NT_PRSTATUS (prstatus structure)
>> CORE 0x00000080 NT_PRPSINFO (prpsinfo structure)
>> CORE 0x000000b0 NT_AUXV (auxiliary vector)
>> CORE 0x00000108 NT_FPREGSET (floating point registers)
>> LINUX 0x00000220 NT_PRXFPREG (user_xfpregs structure)
>>
>> This mirrors what occurs with the SSE registers on i386 core dumps in
>> order to keep things as similar as possible.
>>
>> I can't find any place where dump_spe() is called at the moment, but I
>> suppose if it were to be hooked up in the future it could cause
>> confusion.
>> The Altivec register state in the core file is much larger than what
>> would be dumped by the current dump_spe(), but I'm not sure if that
>> matters...
>>
>> There's a patch for GDB that currently reads the contents of these vector
>> registers from the core file, but it's being held until this patch has
>> been commented on and/or approved of, so if it comes to it the note name
>> could be changed to ALTIVEC (or something similar).
>
> I think we should NOT overload NT_PRXFPREG and add proper note types
> NT_ALTIVEC & NT_SPE for those register sets.
>
> Who on the GDB side would we need to coordinate such a change with?
>
> - k
>
You're probably right :)
What cores have SPE at the moment? Also, perhaps more importantly, are there any plans to have Altivec and SPE in the same core?
I've been working with Carlos Eduardo Seo (Cc'ed on this mail) on the GDB side of this.
Thanks!
Mark.
^ permalink raw reply
* [PATCH 7/7] Celleb: update for PCI
From: Ishizaki Kou @ 2007-09-26 4:40 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
This is a patch kit to support PCI bus on Celleb with new "I/O routines
for PowerPC." External PCI on Celleb must do explicit synchronization
with devices (Bus has no automatic synchronization feature).
Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>
---
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/pci.h
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/pci.h
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/pci.h
@@ -25,11 +25,18 @@
#include <asm/pci-bridge.h>
#include <asm/prom.h>
+#include <asm/ppc-pci.h>
extern int celleb_setup_phb(struct pci_controller *);
extern int celleb_pci_probe_mode(struct pci_bus *);
-extern struct pci_ops celleb_epci_ops;
extern int celleb_setup_epci(struct device_node *, struct pci_controller *);
+extern void *celleb_dummy_page_va;
+extern int __init celleb_pci_workaround_init(void);
+extern void __init celleb_pci_add_one(struct pci_controller *,
+ void (*)(struct pci_controller *));
+extern void fake_pci_workaround_init(struct pci_controller *);
+extern void epci_workaround_init(struct pci_controller *);
+
#endif /* _CELLEB_PCI_H */
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/scc.h
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/scc.h
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/scc.h
@@ -53,7 +53,7 @@
#define SCC_EPCI_STATUS 0x808
#define SCC_EPCI_ABTSET 0x80c
#define SCC_EPCI_WATRP 0x810
-#define SCC_EPCI_DUMMYRADR 0x814
+#define SCC_EPCI_DUMYRADR 0x814
#define SCC_EPCI_SWRESP 0x818
#define SCC_EPCI_CNTOPT 0x81c
#define SCC_EPCI_ECMODE 0xf00
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/Makefile
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/Makefile
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/Makefile
@@ -1,6 +1,7 @@
obj-y += interrupt.o iommu.o setup.o \
- htab.o beat.o pci.o \
- scc_epci.o scc_uhc.o hvCall.o
+ htab.o beat.o hvCall.o pci.o \
+ scc_epci.o scc_uhc.o \
+ io-workarounds.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/setup.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/setup.c
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/setup.c
@@ -137,6 +137,8 @@ static int __init celleb_publish_devices
/* Publish OF platform devices for southbridge IOs */
of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
+ celleb_pci_workaround_init();
+
return 0;
}
device_initcall(celleb_publish_devices);
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/pci.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/pci.c
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/pci.c
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/pci_regs.h>
+#include <linux/of_device.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -435,36 +436,58 @@ static void __init celleb_alloc_private_
GFP_KERNEL);
}
+static int __init celleb_setup_fake_pci(struct device_node *dev,
+ struct pci_controller *phb)
+{
+ struct device_node *node;
+
+ phb->ops = &celleb_fake_pci_ops;
+ celleb_alloc_private_mem(phb);
+
+ for (node = of_get_next_child(dev, NULL);
+ node != NULL; node = of_get_next_child(dev, node))
+ celleb_setup_fake_pci_device(node, phb);
+
+ return 0;
+}
+
+void __init fake_pci_workaround_init(struct pci_controller *phb)
+{
+ /**
+ * We will add fake pci bus to scc_pci_bus for the purpose to improve
+ * I/O Macro performance. But device-tree and device drivers
+ * are not ready to use address with a token.
+ */
+
+ /* celleb_pci_add_one(phb, NULL); */
+}
+
+static struct of_device_id celleb_phb_match[] __initdata = {
+ {
+ .name = "pci-pseudo",
+ .data = celleb_setup_fake_pci,
+ }, {
+ .name = "epci",
+ .data = celleb_setup_epci,
+ }, {
+ },
+};
+
int __init celleb_setup_phb(struct pci_controller *phb)
{
- const char *name;
struct device_node *dev = phb->arch_data;
- struct device_node *node;
- unsigned int rlen;
+ const struct of_device_id *match;
+ int (*setup_func)(struct device_node *, struct pci_controller *);
- name = of_get_property(dev, "name", &rlen);
- if (!name)
+ match = of_match_node(celleb_phb_match, dev);
+ if (!match)
return 1;
- pr_debug("PCI: celleb_setup_phb() %s\n", name);
phb_set_bus_ranges(dev, phb);
phb->buid = 1;
- if (strcmp(name, "epci") == 0) {
- phb->ops = &celleb_epci_ops;
- return celleb_setup_epci(dev, phb);
-
- } else if (strcmp(name, "pci-pseudo") == 0) {
- phb->ops = &celleb_fake_pci_ops;
- celleb_alloc_private_mem(phb);
- for (node = of_get_next_child(dev, NULL);
- node != NULL; node = of_get_next_child(dev, node))
- celleb_setup_fake_pci_device(node, phb);
-
- } else
- return 1;
-
- return 0;
+ setup_func = match->data;
+ return (*setup_func)(dev, phb);
}
int celleb_pci_probe_mode(struct pci_bus *bus)
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/scc_epci.c
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/scc_epci.c
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/scc_epci.c
@@ -43,7 +43,11 @@
#define iob() __asm__ __volatile__("eieio; sync":::"memory")
-static inline volatile void __iomem *celleb_epci_get_epci_base(
+struct epci_private {
+ dma_addr_t dummy_page_da;
+};
+
+static inline PCI_IO_ADDR celleb_epci_get_epci_base(
struct pci_controller *hose)
{
/*
@@ -55,7 +59,7 @@ static inline volatile void __iomem *cel
return hose->cfg_addr;
}
-static inline volatile void __iomem *celleb_epci_get_epci_cfg(
+static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
struct pci_controller *hose)
{
/*
@@ -67,20 +71,11 @@ static inline volatile void __iomem *cel
return hose->cfg_data;
}
-#if 0 /* test code for epci dummy read */
-static void celleb_epci_dummy_read(struct pci_dev *dev)
+static void scc_epci_dummy_read(struct pci_controller *hose)
{
- volatile void __iomem *epci_base;
- struct device_node *node;
- struct pci_controller *hose;
+ PCI_IO_ADDR epci_base;
u32 val;
- node = (struct device_node *)dev->bus->sysdata;
- hose = pci_find_hose_for_OF_device(node);
-
- if (!hose)
- return;
-
epci_base = celleb_epci_get_epci_base(hose);
val = in_be32(epci_base + SCC_EPCI_WATRP);
@@ -88,21 +83,45 @@ static void celleb_epci_dummy_read(struc
return;
}
-#endif
+
+void __init epci_workaround_init(struct pci_controller *hose)
+{
+ PCI_IO_ADDR epci_base;
+ PCI_IO_ADDR reg;
+ struct epci_private *private = hose->private_data;
+
+ BUG_ON(!private);
+
+ private->dummy_page_da = dma_map_single(hose->parent,
+ celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
+ if (private->dummy_page_da == DMA_ERROR_CODE) {
+ printk(KERN_ERR "EPCI: dummy read disabled."
+ "Map dummy page failed.\n");
+ return;
+ }
+
+ celleb_pci_add_one(hose, scc_epci_dummy_read);
+ epci_base = celleb_epci_get_epci_base(hose);
+
+ reg = epci_base + SCC_EPCI_DUMYRADR;
+ out_be32(reg, private->dummy_page_da);
+}
static inline void clear_and_disable_master_abort_interrupt(
struct pci_controller *hose)
{
- volatile void __iomem *epci_base, *reg;
+ PCI_IO_ADDR epci_base;
+ PCI_IO_ADDR reg;
epci_base = celleb_epci_get_epci_base(hose);
reg = epci_base + PCI_COMMAND;
out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
}
static int celleb_epci_check_abort(struct pci_controller *hose,
- volatile void __iomem *addr)
+ PCI_IO_ADDR addr)
{
- volatile void __iomem *reg, *epci_base;
+ PCI_IO_ADDR reg;
+ PCI_IO_ADDR epci_base;
u32 val;
iob();
@@ -132,12 +151,12 @@ static int celleb_epci_check_abort(struc
return PCIBIOS_SUCCESSFUL;
}
-static volatile void __iomem *celleb_epci_make_config_addr(
+static PCI_IO_ADDR celleb_epci_make_config_addr(
struct pci_bus *bus,
struct pci_controller *hose,
unsigned int devfn, int where)
{
- volatile void __iomem *addr;
+ PCI_IO_ADDR addr;
if (bus != hose->bus)
addr = celleb_epci_get_epci_cfg(hose) +
@@ -157,7 +176,8 @@ static volatile void __iomem *celleb_epc
static int celleb_epci_read_config(struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 * val)
{
- volatile void __iomem *epci_base, *addr;
+ PCI_IO_ADDR epci_base;
+ PCI_IO_ADDR addr;
struct device_node *node;
struct pci_controller *hose;
@@ -220,7 +240,8 @@ static int celleb_epci_read_config(struc
static int celleb_epci_write_config(struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val)
{
- volatile void __iomem *epci_base, *addr;
+ PCI_IO_ADDR epci_base;
+ PCI_IO_ADDR addr;
struct device_node *node;
struct pci_controller *hose;
@@ -286,7 +307,8 @@ struct pci_ops celleb_epci_ops = {
static int __init celleb_epci_init(struct pci_controller *hose)
{
u32 val;
- volatile void __iomem *reg, *epci_base;
+ PCI_IO_ADDR reg;
+ PCI_IO_ADDR epci_base;
int hwres = 0;
epci_base = celleb_epci_get_epci_base(hose);
@@ -440,10 +462,24 @@ int __init celleb_setup_epci(struct devi
r.start, (unsigned long)hose->cfg_data,
(r.end - r.start + 1));
+ hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL);
+ if (hose->private_data == NULL) {
+ printk(KERN_ERR "EPCI: no memory for private data.\n");
+ goto error;
+ }
+
+ hose->ops = &celleb_epci_ops;
celleb_epci_init(hose);
return 0;
error:
+ kfree(hose->private_data);
+
+ if (hose->cfg_addr)
+ iounmap(hose->cfg_addr);
+
+ if (hose->cfg_data)
+ iounmap(hose->cfg_data);
return 1;
}
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/io-workarounds.c
===================================================================
--- /dev/null
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/io-workarounds.c
@@ -0,0 +1,279 @@
+/*
+ * Support for Celleb io workarounds
+ *
+ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+ *
+ * This file is based to arch/powerpc/platform/cell/io-workarounds.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#undef DEBUG
+
+#include <linux/of_device.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+
+#include "pci.h"
+
+#define MAX_CELLEB_PCI_BUS 4
+
+void *celleb_dummy_page_va;
+
+static struct celleb_pci_bus {
+ struct pci_controller *phb;
+ void (*dummy_read)(struct pci_controller *);
+} celleb_pci_busses[MAX_CELLEB_PCI_BUS];
+
+static int celleb_pci_count = 0;
+
+static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
+ unsigned long paddr)
+{
+ int i, j;
+ struct resource *res;
+
+ for (i = 0; i < celleb_pci_count; i++) {
+ struct celleb_pci_bus *bus = &celleb_pci_busses[i];
+ struct pci_controller *phb = bus->phb;
+ if (paddr)
+ for (j = 0; j < 3; j++) {
+ res = &phb->mem_resources[j];
+ if (paddr >= res->start && paddr <= res->end)
+ return bus;
+ }
+ res = &phb->io_resource;
+ if (vaddr && vaddr >= res->start && vaddr <= res->end)
+ return bus;
+ }
+ return NULL;
+}
+
+static void celleb_io_flush(const PCI_IO_ADDR addr)
+{
+ struct celleb_pci_bus *bus;
+ int token;
+
+ token = PCI_GET_ADDR_TOKEN(addr);
+
+ if (token && token <= celleb_pci_count)
+ bus = &celleb_pci_busses[token - 1];
+ else {
+ unsigned long vaddr, paddr;
+ pte_t *ptep;
+
+ vaddr = (unsigned long)PCI_FIX_ADDR(addr);
+ if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
+ return;
+
+ ptep = find_linux_pte(init_mm.pgd, vaddr);
+ if (ptep == NULL)
+ paddr = 0;
+ else
+ paddr = pte_pfn(*ptep) << PAGE_SHIFT;
+ bus = celleb_pci_find(vaddr, paddr);
+
+ if (bus == NULL)
+ return;
+ }
+
+ if (bus->dummy_read)
+ bus->dummy_read(bus->phb);
+}
+
+static u8 celleb_readb(const PCI_IO_ADDR addr)
+{
+ u8 val;
+ val = __do_readb(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static u16 celleb_readw(const PCI_IO_ADDR addr)
+{
+ u16 val;
+ val = __do_readw(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static u32 celleb_readl(const PCI_IO_ADDR addr)
+{
+ u32 val;
+ val = __do_readl(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static u64 celleb_readq(const PCI_IO_ADDR addr)
+{
+ u64 val;
+ val = __do_readq(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static u16 celleb_readw_be(const PCI_IO_ADDR addr)
+{
+ u16 val;
+ val = __do_readw_be(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static u32 celleb_readl_be(const PCI_IO_ADDR addr)
+{
+ u32 val;
+ val = __do_readl_be(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static u64 celleb_readq_be(const PCI_IO_ADDR addr)
+{
+ u64 val;
+ val = __do_readq_be(addr);
+ celleb_io_flush(addr);
+ return val;
+}
+
+static void celleb_readsb(const PCI_IO_ADDR addr,
+ void *buf, unsigned long count)
+{
+ __do_readsb(addr, buf, count);
+ celleb_io_flush(addr);
+}
+
+static void celleb_readsw(const PCI_IO_ADDR addr,
+ void *buf, unsigned long count)
+{
+ __do_readsw(addr, buf, count);
+ celleb_io_flush(addr);
+}
+
+static void celleb_readsl(const PCI_IO_ADDR addr,
+ void *buf, unsigned long count)
+{
+ __do_readsl(addr, buf, count);
+ celleb_io_flush(addr);
+}
+
+static void celleb_memcpy_fromio(void *dest,
+ const PCI_IO_ADDR src,
+ unsigned long n)
+{
+ __do_memcpy_fromio(dest, src, n);
+ celleb_io_flush(src);
+}
+
+static void __iomem *celleb_ioremap(unsigned long addr,
+ unsigned long size,
+ unsigned long flags)
+{
+ struct celleb_pci_bus *bus;
+ void __iomem *res = __ioremap(addr, size, flags);
+ int busno;
+
+ bus = celleb_pci_find(0, addr);
+ if (bus != NULL) {
+ busno = bus - celleb_pci_busses;
+ PCI_SET_ADDR_TOKEN(res, busno + 1);
+ }
+ return res;
+}
+
+static void celleb_iounmap(volatile void __iomem *addr)
+{
+ return __iounmap(PCI_FIX_ADDR(addr));
+}
+
+static struct ppc_pci_io celleb_pci_io __initdata = {
+ .readb = celleb_readb,
+ .readw = celleb_readw,
+ .readl = celleb_readl,
+ .readq = celleb_readq,
+ .readw_be = celleb_readw_be,
+ .readl_be = celleb_readl_be,
+ .readq_be = celleb_readq_be,
+ .readsb = celleb_readsb,
+ .readsw = celleb_readsw,
+ .readsl = celleb_readsl,
+ .memcpy_fromio = celleb_memcpy_fromio,
+};
+
+void __init celleb_pci_add_one(struct pci_controller *phb,
+ void (*dummy_read)(struct pci_controller *))
+{
+ struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
+ struct device_node *np = phb->arch_data;
+
+ if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
+ printk(KERN_ERR "Too many pci bridges, workarounds"
+ " disabled for %s\n", np->full_name);
+ return;
+ }
+
+ celleb_pci_count++;
+
+ bus->phb = phb;
+ bus->dummy_read = dummy_read;
+}
+
+static struct of_device_id celleb_pci_workaround_match[] __initdata = {
+ {
+ .name = "pci-pseudo",
+ .data = fake_pci_workaround_init,
+ }, {
+ .name = "epci",
+ .data = epci_workaround_init,
+ }, {
+ },
+};
+
+int __init celleb_pci_workaround_init(void)
+{
+ struct pci_controller *phb;
+ struct device_node *node;
+ const struct of_device_id *match;
+ void (*init_func)(struct pci_controller *);
+
+ celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!celleb_dummy_page_va) {
+ printk(KERN_ERR "Celleb: dummy read disabled."
+ "Alloc celleb_dummy_page_va failed\n");
+ return 1;
+ }
+
+ list_for_each_entry(phb, &hose_list, list_node) {
+ node = phb->arch_data;
+ match = of_match_node(celleb_pci_workaround_match, node);
+
+ if (match) {
+ init_func = match->data;
+ (*init_func)(phb);
+ }
+ }
+
+ ppc_pci_io = celleb_pci_io;
+ ppc_md.ioremap = celleb_ioremap;
+ ppc_md.iounmap = celleb_iounmap;
+
+ return 0;
+}
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/Kconfig
===================================================================
--- linux-powerpc-git.orig/arch/powerpc/platforms/celleb/Kconfig
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/Kconfig
@@ -2,6 +2,7 @@ config PPC_CELLEB
bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL
+ select PPC_INDIRECT_IO
select PPC_OF_PLATFORM_PCI
select HAS_TXX9_SERIAL
select PPC_UDBG_BEAT
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox