diff options
Diffstat (limited to 'arch/powerpc/platforms/ps3')
| -rw-r--r-- | arch/powerpc/platforms/ps3/Kconfig | 36 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/Makefile | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/device-init.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/exports.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/gelic_udbg.c | 273 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/htab.c | 31 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/interrupt.c | 196 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/mm.c | 81 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/os-area.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/platform.h | 17 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/repository.c | 369 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/setup.c | 15 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/smp.c | 80 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/spu.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/system-bus.c | 22 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/time.c | 4 |
16 files changed, 838 insertions, 307 deletions
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index dfe316b161a..56f274064d6 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -2,12 +2,9 @@ config PPC_PS3 bool "Sony PS3" depends on PPC64 && PPC_BOOK3S select PPC_CELL - select USB_ARCH_HAS_OHCI select USB_OHCI_LITTLE_ENDIAN select USB_OHCI_BIG_ENDIAN_MMIO - select USB_ARCH_HAS_EHCI select USB_EHCI_BIG_ENDIAN_MMIO - select MEMORY_HOTPLUG select PPC_PCI_CHOICE help This option enables support for the Sony PS3 game console @@ -49,7 +46,7 @@ config PS3_HTAB_SIZE system will have optimal runtime performance. config PS3_DYNAMIC_DMA - depends on PPC_PS3 && EXPERIMENTAL + depends on PPC_PS3 bool "PS3 Platform dynamic DMA page table management" default n help @@ -74,7 +71,7 @@ config PS3_PS3AV help Include support for the PS3 AV Settings driver. - This support is required for graphics and sound. In + This support is required for PS3 graphics and sound. In general, all users will say Y or M. config PS3_SYS_MANAGER @@ -85,9 +82,22 @@ config PS3_SYS_MANAGER help Include support for the PS3 System Manager. - This support is required for system control. In + This support is required for PS3 system control. In general, all users will say Y or M. +config PS3_REPOSITORY_WRITE + bool "PS3 Repository write support" if PS3_ADVANCED + depends on PPC_PS3 + default n + help + Enables support for writing to the PS3 System Repository. + + This support is intended for bootloaders that need to store data + in the repository for later boot stages. + + If in doubt, say N here and reduce the size of the kernel by a + small amount. + config PS3_STORAGE depends on PPC_PS3 tristate @@ -122,7 +132,7 @@ config PS3_FLASH This support is required to access the PS3 FLASH ROM, which contains the boot loader and some boot options. - In general, all users will say Y or M. + In general, PS3 OtherOS users will say Y or M. As this driver needs a fixed buffer of 256 KiB of memory, it can be disabled on the kernel command line using "ps3flash=off", to @@ -148,4 +158,16 @@ config PS3_LPM profiling support of the Cell processor with programs like oprofile and perfmon2, then say Y or M, otherwise say N. +config PS3GELIC_UDBG + bool "PS3 udbg output via UDP broadcasts on Ethernet" + depends on PPC_PS3 + help + Enables udbg early debugging output by sending broadcast UDP + via the Ethernet port (UDP port number 18194). + + This driver uses a trivial implementation and is independent + from the main PS3 gelic network driver. + + If in doubt, say N here. + endmenu diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile index ac1bdf844ec..02b9e636dab 100644 --- a/arch/powerpc/platforms/ps3/Makefile +++ b/arch/powerpc/platforms/ps3/Makefile @@ -2,6 +2,7 @@ obj-y += setup.o mm.o time.o hvcall.o htab.o repository.o obj-y += interrupt.o exports.o os-area.o obj-y += system-bus.o +obj-$(CONFIG_PS3GELIC_UDBG) += gelic_udbg.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SPU_BASE) += spu.o obj-y += device-init.o diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c index 6c4b5837fc8..3f175e8aedb 100644 --- a/arch/powerpc/platforms/ps3/device-init.c +++ b/arch/powerpc/platforms/ps3/device-init.c @@ -825,7 +825,7 @@ static int ps3_probe_thread(void *data) spin_lock_init(&dev.lock); - res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED, + res = request_irq(irq, ps3_notification_interrupt, 0, "ps3_notification", &dev); if (res) { pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__, diff --git a/arch/powerpc/platforms/ps3/exports.c b/arch/powerpc/platforms/ps3/exports.c index a7e8ffd24a6..7df5b7d8fc6 100644 --- a/arch/powerpc/platforms/ps3/exports.c +++ b/arch/powerpc/platforms/ps3/exports.c @@ -18,8 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/module.h> - #define LV1_CALL(name, in, out, num) \ extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \ EXPORT_SYMBOL(_lv1_##name); diff --git a/arch/powerpc/platforms/ps3/gelic_udbg.c b/arch/powerpc/platforms/ps3/gelic_udbg.c new file mode 100644 index 00000000000..20b46a19a48 --- /dev/null +++ b/arch/powerpc/platforms/ps3/gelic_udbg.c @@ -0,0 +1,273 @@ +/* + * udbg debug output routine via GELIC UDP broadcasts + * + * Copyright (C) 2007 Sony Computer Entertainment Inc. + * Copyright 2006, 2007 Sony Corporation + * Copyright (C) 2010 Hector Martin <hector@marcansoft.com> + * Copyright (C) 2011 Andre Heider <a.heider@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + */ + +#include <asm/io.h> +#include <asm/udbg.h> +#include <asm/lv1call.h> + +#define GELIC_BUS_ID 1 +#define GELIC_DEVICE_ID 0 +#define GELIC_DEBUG_PORT 18194 +#define GELIC_MAX_MESSAGE_SIZE 1000 + +#define GELIC_LV1_GET_MAC_ADDRESS 1 +#define GELIC_LV1_GET_VLAN_ID 4 +#define GELIC_LV1_VLAN_TX_ETHERNET_0 2 + +#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000 +#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000 + +#define GELIC_DESCR_TX_DMA_IKE 0x00080000 +#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000 +#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000 + +#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \ + GELIC_DESCR_TX_DMA_IKE | \ + GELIC_DESCR_TX_DMA_NO_CHKSUM) + +static u64 bus_addr; + +struct gelic_descr { + /* as defined by the hardware */ + __be32 buf_addr; + __be32 buf_size; + __be32 next_descr_addr; + __be32 dmac_cmd_status; + __be32 result_size; + __be32 valid_size; /* all zeroes for tx */ + __be32 data_status; + __be32 data_error; /* all zeroes for tx */ +} __attribute__((aligned(32))); + +struct debug_block { + struct gelic_descr descr; + u8 pkt[1520]; +} __packed; + +struct ethhdr { + u8 dest[6]; + u8 src[6]; + u16 type; +} __packed; + +struct vlantag { + u16 vlan; + u16 subtype; +} __packed; + +struct iphdr { + u8 ver_len; + u8 dscp_ecn; + u16 total_length; + u16 ident; + u16 frag_off_flags; + u8 ttl; + u8 proto; + u16 checksum; + u32 src; + u32 dest; +} __packed; + +struct udphdr { + u16 src; + u16 dest; + u16 len; + u16 checksum; +} __packed; + +static __iomem struct ethhdr *h_eth; +static __iomem struct vlantag *h_vlan; +static __iomem struct iphdr *h_ip; +static __iomem struct udphdr *h_udp; + +static __iomem char *pmsg; +static __iomem char *pmsgc; + +static __iomem struct debug_block dbg __attribute__((aligned(32))); + +static int header_size; + +static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len, + u64 *real_bus_addr) +{ + s64 result; + u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL; + u64 real_end = real_addr + len; + u64 map_start = real_addr & ~0xfff; + u64 map_end = (real_end + 0xfff) & ~0xfff; + u64 bus_addr = 0; + + u64 flags = 0xf800000000000000UL; + + result = lv1_allocate_device_dma_region(bus_id, dev_id, + map_end - map_start, 12, 0, + &bus_addr); + if (result) + lv1_panic(0); + + result = lv1_map_device_dma_region(bus_id, dev_id, map_start, + bus_addr, map_end - map_start, + flags); + if (result) + lv1_panic(0); + + *real_bus_addr = bus_addr + real_addr - map_start; +} + +static int unmap_dma_mem(int bus_id, int dev_id, u64 bus_addr, size_t len) +{ + s64 result; + u64 real_bus_addr; + + real_bus_addr = bus_addr & ~0xfff; + len += bus_addr - real_bus_addr; + len = (len + 0xfff) & ~0xfff; + + result = lv1_unmap_device_dma_region(bus_id, dev_id, real_bus_addr, + len); + if (result) + return result; + + return lv1_free_device_dma_region(bus_id, dev_id, real_bus_addr); +} + +static void gelic_debug_init(void) +{ + s64 result; + u64 v2; + u64 mac; + u64 vlan_id; + + result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0); + if (result) + lv1_panic(0); + + map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg), + &bus_addr); + + memset(&dbg, 0, sizeof(dbg)); + + dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt); + + wmb(); + + result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID, + GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0, + &mac, &v2); + if (result) + lv1_panic(0); + + mac <<= 16; + + h_eth = (struct ethhdr *)dbg.pkt; + + memset(&h_eth->dest, 0xff, 6); + memcpy(&h_eth->src, &mac, 6); + + header_size = sizeof(struct ethhdr); + + result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID, + GELIC_LV1_GET_VLAN_ID, + GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0, + &vlan_id, &v2); + if (!result) { + h_eth->type = 0x8100; + + header_size += sizeof(struct vlantag); + h_vlan = (struct vlantag *)(h_eth + 1); + h_vlan->vlan = vlan_id; + h_vlan->subtype = 0x0800; + h_ip = (struct iphdr *)(h_vlan + 1); + } else { + h_eth->type = 0x0800; + h_ip = (struct iphdr *)(h_eth + 1); + } + + header_size += sizeof(struct iphdr); + h_ip->ver_len = 0x45; + h_ip->ttl = 10; + h_ip->proto = 0x11; + h_ip->src = 0x00000000; + h_ip->dest = 0xffffffff; + + header_size += sizeof(struct udphdr); + h_udp = (struct udphdr *)(h_ip + 1); + h_udp->src = GELIC_DEBUG_PORT; + h_udp->dest = GELIC_DEBUG_PORT; + + pmsgc = pmsg = (char *)(h_udp + 1); +} + +static void gelic_debug_shutdown(void) +{ + if (bus_addr) + unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, + bus_addr, sizeof(dbg)); + lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID); +} + +static void gelic_sendbuf(int msgsize) +{ + u16 *p; + u32 sum; + int i; + + dbg.descr.buf_size = header_size + msgsize; + h_ip->total_length = msgsize + sizeof(struct udphdr) + + sizeof(struct iphdr); + h_udp->len = msgsize + sizeof(struct udphdr); + + h_ip->checksum = 0; + sum = 0; + p = (u16 *)h_ip; + for (i = 0; i < 5; i++) + sum += *p++; + h_ip->checksum = ~(sum + (sum >> 16)); + + dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM | + GELIC_DESCR_TX_DMA_FRAME_TAIL; + dbg.descr.result_size = 0; + dbg.descr.data_status = 0; + + wmb(); + + lv1_net_start_tx_dma(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, 0); + + while ((dbg.descr.dmac_cmd_status & GELIC_DESCR_DMA_STAT_MASK) == + GELIC_DESCR_DMA_CARDOWNED) + cpu_relax(); +} + +static void ps3gelic_udbg_putc(char ch) +{ + *pmsgc++ = ch; + if (ch == '\n' || (pmsgc-pmsg) >= GELIC_MAX_MESSAGE_SIZE) { + gelic_sendbuf(pmsgc-pmsg); + pmsgc = pmsg; + } +} + +void __init udbg_init_ps3gelic(void) +{ + gelic_debug_init(); + udbg_putc = ps3gelic_udbg_putc; +} + +void udbg_shutdown_ps3gelic(void) +{ + udbg_putc = NULL; + gelic_debug_shutdown(); +} +EXPORT_SYMBOL(udbg_shutdown_ps3gelic); diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index 3124cf791eb..3e270e3412a 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c @@ -27,6 +27,7 @@ #include <asm/lv1call.h> #include <asm/ps3fb.h> +#define PS3_VERBOSE_RESULT #include "platform.h" /** @@ -43,9 +44,9 @@ enum ps3_lpar_vas_id { static DEFINE_SPINLOCK(ps3_htab_lock); -static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, +static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn, unsigned long pa, unsigned long rflags, unsigned long vflags, - int psize, int ssize) + int psize, int apsize, int ssize) { int result; u64 hpte_v, hpte_r; @@ -61,8 +62,8 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, */ vflags &= ~HPTE_V_SECONDARY; - hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID; - hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; + hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID; + hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize) | rflags; spin_lock_irqsave(&ps3_htab_lock, flags); @@ -75,8 +76,9 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, if (result) { /* all entries bolted !*/ - pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%llx r=%llx\n", - __func__, result, va, pa, hpte_group, hpte_v, hpte_r); + pr_info("%s:result=%s vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n", + __func__, ps3_result(result), vpn, pa, hpte_group, + hpte_v, hpte_r); BUG(); } @@ -107,7 +109,8 @@ static long ps3_hpte_remove(unsigned long hpte_group) } static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int psize, int ssize, int local) + unsigned long vpn, int psize, int apsize, + int ssize, int local) { int result; u64 hpte_v, want_v, hpte_rs; @@ -115,7 +118,7 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, unsigned long flags; long ret; - want_v = hpte_encode_v(va, psize, ssize); + want_v = hpte_encode_avpn(vpn, psize, ssize); spin_lock_irqsave(&ps3_htab_lock, flags); @@ -125,8 +128,8 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, &hpte_rs); if (result) { - pr_info("%s: res=%d read va=%lx slot=%lx psize=%d\n", - __func__, result, va, slot, psize); + pr_info("%s: result=%s read vpn=%lx slot=%lx psize=%d\n", + __func__, ps3_result(result), vpn, slot, psize); BUG(); } @@ -159,8 +162,8 @@ static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, panic("ps3_hpte_updateboltedpp() not implemented"); } -static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, - int psize, int ssize, int local) +static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn, + int psize, int apsize, int ssize, int local) { unsigned long flags; int result; @@ -170,8 +173,8 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0); if (result) { - pr_info("%s: res=%d va=%lx slot=%lx psize=%d\n", - __func__, result, va, slot, psize); + pr_info("%s: result=%s vpn=%lx slot=%lx psize=%d\n", + __func__, ps3_result(result), vpn, slot, psize); BUG(); } diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 92290ff4761..5f3b23220b8 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -19,7 +19,7 @@ */ #include <linux/kernel.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/irq.h> #include <asm/machdep.h> @@ -31,18 +31,18 @@ #if defined(DEBUG) #define DBG udbg_printf +#define FAIL udbg_printf #else -#define DBG pr_debug +#define DBG pr_devel +#define FAIL pr_debug #endif /** * struct ps3_bmp - a per cpu irq status and mask bitmap structure * @status: 256 bit status bitmap indexed by plug - * @unused_1: + * @unused_1: Alignment * @mask: 256 bit mask bitmap indexed by plug - * @unused_2: - * @lock: - * @ipi_debug_brk_mask: + * @unused_2: Alignment * * The HV maintains per SMT thread mappings of HV outlet to HV plug on * behalf of the guest. These mappings are implemented as 256 bit guest @@ -73,21 +73,25 @@ struct ps3_bmp { unsigned long mask; u64 unused_2[3]; }; - u64 ipi_debug_brk_mask; - spinlock_t lock; }; /** * struct ps3_private - a per cpu data structure * @bmp: ps3_bmp structure + * @bmp_lock: Syncronize access to bmp. + * @ipi_debug_brk_mask: Mask for debug break IPIs * @ppe_id: HV logical_ppe_id * @thread_id: HV thread_id + * @ipi_mask: Mask of IPI virqs */ struct ps3_private { struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); + spinlock_t bmp_lock; u64 ppe_id; u64 thread_id; + unsigned long ipi_debug_brk_mask; + unsigned long ipi_mask; }; static DEFINE_PER_CPU(struct ps3_private, ps3_private); @@ -99,16 +103,16 @@ static DEFINE_PER_CPU(struct ps3_private, ps3_private); * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). */ -static void ps3_chip_mask(unsigned int virq) +static void ps3_chip_mask(struct irq_data *d) { - struct ps3_private *pd = get_irq_chip_data(virq); + struct ps3_private *pd = irq_data_get_irq_chip_data(d); unsigned long flags; - pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__, - pd->thread_id, virq); + DBG("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__, + pd->thread_id, d->irq); local_irq_save(flags); - clear_bit(63 - virq, &pd->bmp.mask); + clear_bit(63 - d->irq, &pd->bmp.mask); lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); local_irq_restore(flags); } @@ -120,16 +124,16 @@ static void ps3_chip_mask(unsigned int virq) * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). */ -static void ps3_chip_unmask(unsigned int virq) +static void ps3_chip_unmask(struct irq_data *d) { - struct ps3_private *pd = get_irq_chip_data(virq); + struct ps3_private *pd = irq_data_get_irq_chip_data(d); unsigned long flags; - pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__, - pd->thread_id, virq); + DBG("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__, + pd->thread_id, d->irq); local_irq_save(flags); - set_bit(63 - virq, &pd->bmp.mask); + set_bit(63 - d->irq, &pd->bmp.mask); lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); local_irq_restore(flags); } @@ -141,10 +145,14 @@ static void ps3_chip_unmask(unsigned int virq) * Calls lv1_end_of_interrupt_ext(). */ -static void ps3_chip_eoi(unsigned int virq) +static void ps3_chip_eoi(struct irq_data *d) { - const struct ps3_private *pd = get_irq_chip_data(virq); - lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq); + const struct ps3_private *pd = irq_data_get_irq_chip_data(d); + + /* non-IPIs are EOIed here. */ + + if (!test_bit(63 - d->irq, &pd->ipi_mask)) + lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq); } /** @@ -153,9 +161,9 @@ static void ps3_chip_eoi(unsigned int virq) static struct irq_chip ps3_irq_chip = { .name = "ps3", - .mask = ps3_chip_mask, - .unmask = ps3_chip_unmask, - .eoi = ps3_chip_eoi, + .irq_mask = ps3_chip_mask, + .irq_unmask = ps3_chip_unmask, + .irq_eoi = ps3_chip_eoi, }; /** @@ -185,24 +193,24 @@ static int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, *virq = irq_create_mapping(NULL, outlet); if (*virq == NO_IRQ) { - pr_debug("%s:%d: irq_create_mapping failed: outlet %lu\n", + FAIL("%s:%d: irq_create_mapping failed: outlet %lu\n", __func__, __LINE__, outlet); result = -ENOMEM; goto fail_create; } - pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, + DBG("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, outlet, cpu, *virq); - result = set_irq_chip_data(*virq, pd); + result = irq_set_chip_data(*virq, pd); if (result) { - pr_debug("%s:%d: set_irq_chip_data failed\n", + FAIL("%s:%d: irq_set_chip_data failed\n", __func__, __LINE__); goto fail_set; } - ps3_chip_mask(*virq); + ps3_chip_mask(irq_get_irq_data(*virq)); return result; @@ -221,15 +229,15 @@ fail_create: static int ps3_virq_destroy(unsigned int virq) { - const struct ps3_private *pd = get_irq_chip_data(virq); + const struct ps3_private *pd = irq_get_chip_data(virq); - pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__, + DBG("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__, __LINE__, pd->ppe_id, pd->thread_id, virq); - set_irq_chip_data(virq, NULL); + irq_set_chip_data(virq, NULL); irq_dispose_mapping(virq); - pr_debug("%s:%d <-\n", __func__, __LINE__); + DBG("%s:%d <-\n", __func__, __LINE__); return 0; } @@ -252,11 +260,11 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, result = ps3_virq_setup(cpu, outlet, virq); if (result) { - pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__); + FAIL("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__); goto fail_setup; } - pd = get_irq_chip_data(*virq); + pd = irq_get_chip_data(*virq); /* Binds outlet to cpu + virq. */ @@ -264,7 +272,7 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, outlet, 0); if (result) { - pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", + FAIL("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); result = -EPERM; goto fail_connect; @@ -291,17 +299,17 @@ EXPORT_SYMBOL_GPL(ps3_irq_plug_setup); int ps3_irq_plug_destroy(unsigned int virq) { int result; - const struct ps3_private *pd = get_irq_chip_data(virq); + const struct ps3_private *pd = irq_get_chip_data(virq); - pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__, + DBG("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__, __LINE__, pd->ppe_id, pd->thread_id, virq); - ps3_chip_mask(virq); + ps3_chip_mask(irq_get_irq_data(virq)); result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq); if (result) - pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", + FAIL("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_virq_destroy(virq); @@ -329,7 +337,7 @@ int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq) result = lv1_construct_event_receive_port(&outlet); if (result) { - pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n", + FAIL("%s:%d: lv1_construct_event_receive_port failed: %s\n", __func__, __LINE__, ps3_result(result)); *virq = NO_IRQ; return result; @@ -355,14 +363,14 @@ int ps3_event_receive_port_destroy(unsigned int virq) { int result; - pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq); + DBG(" -> %s:%d virq %u\n", __func__, __LINE__, virq); - ps3_chip_mask(virq); + ps3_chip_mask(irq_get_irq_data(virq)); result = lv1_destruct_event_receive_port(virq_to_hw(virq)); if (result) - pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", + FAIL("%s:%d: lv1_destruct_event_receive_port failed: %s\n", __func__, __LINE__, ps3_result(result)); /* @@ -370,7 +378,7 @@ int ps3_event_receive_port_destroy(unsigned int virq) * calls from interrupt context (smp_call_function) when kexecing. */ - pr_debug(" <- %s:%d\n", __func__, __LINE__); + DBG(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -406,7 +414,7 @@ int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, dev->dev_id, virq_to_hw(*virq), dev->interrupt_id); if (result) { - pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" + FAIL("%s:%d: lv1_connect_interrupt_event_receive_port" " failed: %s\n", __func__, __LINE__, ps3_result(result)); ps3_event_receive_port_destroy(*virq); @@ -414,7 +422,7 @@ int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, return result; } - pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, + DBG("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, dev->interrupt_id, *virq); return 0; @@ -428,14 +436,14 @@ int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, int result; - pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, + DBG(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, dev->interrupt_id, virq); result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id, dev->dev_id, virq_to_hw(virq), dev->interrupt_id); if (result) - pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" + FAIL("%s:%d: lv1_disconnect_interrupt_event_receive_port" " failed: %s\n", __func__, __LINE__, ps3_result(result)); @@ -450,7 +458,7 @@ int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, result = ps3_virq_destroy(virq); BUG_ON(result); - pr_debug(" <- %s:%d\n", __func__, __LINE__); + DBG(" <- %s:%d\n", __func__, __LINE__); return result; } EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy); @@ -475,7 +483,7 @@ int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id, result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); if (result) { - pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", + FAIL("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; } @@ -492,7 +500,7 @@ int ps3_io_irq_destroy(unsigned int virq) int result; unsigned long outlet = virq_to_hw(virq); - ps3_chip_mask(virq); + ps3_chip_mask(irq_get_irq_data(virq)); /* * lv1_destruct_io_irq_outlet() will destroy the IRQ plug, @@ -505,7 +513,7 @@ int ps3_io_irq_destroy(unsigned int virq) result = lv1_destruct_io_irq_outlet(outlet); if (result) - pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", + FAIL("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; @@ -537,7 +545,7 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet); if (result) { - pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", + FAIL("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; } @@ -553,11 +561,11 @@ int ps3_vuart_irq_destroy(unsigned int virq) { int result; - ps3_chip_mask(virq); + ps3_chip_mask(irq_get_irq_data(virq)); result = lv1_deconfigure_virtual_uart_irq(); if (result) { - pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", + FAIL("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; } @@ -590,7 +598,7 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, result = lv1_get_spe_irq_outlet(spe_id, class, &outlet); if (result) { - pr_debug("%s:%d: lv1_get_spe_irq_outlet failed: %s\n", + FAIL("%s:%d: lv1_get_spe_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); return result; } @@ -605,7 +613,7 @@ int ps3_spe_irq_destroy(unsigned int virq) { int result; - ps3_chip_mask(virq); + ps3_chip_mask(irq_get_irq_data(virq)); result = ps3_irq_plug_destroy(virq); BUG_ON(result); @@ -621,7 +629,7 @@ int ps3_spe_irq_destroy(unsigned int virq) static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu, const char* func, int line) { - pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n", + pr_debug("%s:%d: %s %u {%04llx_%04llx_%04llx_%04llx}\n", func, line, header, cpu, *p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff, *p & 0xffff); @@ -630,7 +638,7 @@ static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu, static void __maybe_unused _dump_256_bmp(const char *header, const u64 *p, unsigned cpu, const char* func, int line) { - pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", + pr_debug("%s:%d: %s %u {%016llx:%016llx:%016llx:%016llx}\n", func, line, header, cpu, p[0], p[1], p[2], p[3]); } @@ -639,10 +647,10 @@ static void _dump_bmp(struct ps3_private* pd, const char* func, int line) { unsigned long flags; - spin_lock_irqsave(&pd->bmp.lock, flags); + spin_lock_irqsave(&pd->bmp_lock, flags); _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line); - _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); - spin_unlock_irqrestore(&pd->bmp.lock, flags); + _dump_64_bmp("mask", (u64*)&pd->bmp.mask, pd->thread_id, func, line); + spin_unlock_irqrestore(&pd->bmp_lock, flags); } #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) @@ -651,39 +659,33 @@ static void __maybe_unused _dump_mask(struct ps3_private *pd, { unsigned long flags; - spin_lock_irqsave(&pd->bmp.lock, flags); - _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); - spin_unlock_irqrestore(&pd->bmp.lock, flags); + spin_lock_irqsave(&pd->bmp_lock, flags); + _dump_64_bmp("mask", (u64*)&pd->bmp.mask, pd->thread_id, func, line); + spin_unlock_irqrestore(&pd->bmp_lock, flags); } #else static void dump_bmp(struct ps3_private* pd) {}; #endif /* defined(DEBUG) */ -static void ps3_host_unmap(struct irq_host *h, unsigned int virq) -{ - set_irq_chip_data(virq, NULL); -} - -static int ps3_host_map(struct irq_host *h, unsigned int virq, +static int ps3_host_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hwirq) { - pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, + DBG("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, virq); - set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq); + irq_set_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq); return 0; } -static int ps3_host_match(struct irq_host *h, struct device_node *np) +static int ps3_host_match(struct irq_domain *h, struct device_node *np) { /* Match all */ return 1; } -static struct irq_host_ops ps3_host_ops = { +static const struct irq_domain_ops ps3_host_ops = { .map = ps3_host_map, - .unmap = ps3_host_unmap, .match = ps3_host_match, }; @@ -691,10 +693,20 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) { struct ps3_private *pd = &per_cpu(ps3_private, cpu); - pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq; + set_bit(63 - virq, &pd->ipi_debug_brk_mask); + + DBG("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__, + cpu, virq, pd->ipi_debug_brk_mask); +} + +void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq) +{ + struct ps3_private *pd = &per_cpu(ps3_private, cpu); + + set_bit(63 - virq, &pd->ipi_mask); - pr_debug("%s:%d: cpu %u, virq %u, mask %llxh\n", __func__, __LINE__, - cpu, virq, pd->bmp.ipi_debug_brk_mask); + DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__, + cpu, virq, pd->ipi_mask); } static unsigned int ps3_get_irq(void) @@ -705,14 +717,14 @@ static unsigned int ps3_get_irq(void) /* check for ipi break first to stop this cpu ASAP */ - if (x & pd->bmp.ipi_debug_brk_mask) - x &= pd->bmp.ipi_debug_brk_mask; + if (x & pd->ipi_debug_brk_mask) + x &= pd->ipi_debug_brk_mask; asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x)); plug &= 0x3f; if (unlikely(plug == NO_IRQ)) { - pr_debug("%s:%d: no plug found: thread_id %llu\n", __func__, + DBG("%s:%d: no plug found: thread_id %llu\n", __func__, __LINE__, pd->thread_id); dump_bmp(&per_cpu(ps3_private, 0)); dump_bmp(&per_cpu(ps3_private, 1)); @@ -726,6 +738,12 @@ static unsigned int ps3_get_irq(void) BUG(); } #endif + + /* IPIs are EOIed here. */ + + if (test_bit(63 - plug, &pd->ipi_mask)) + lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug); + return plug; } @@ -733,21 +751,19 @@ void __init ps3_init_IRQ(void) { int result; unsigned cpu; - struct irq_host *host; + struct irq_domain *host; - host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, - PS3_INVALID_OUTLET); + host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL); irq_set_default_host(host); - irq_set_virq_count(PS3_PLUG_MAX + 1); for_each_possible_cpu(cpu) { struct ps3_private *pd = &per_cpu(ps3_private, cpu); lv1_get_logical_ppe_id(&pd->ppe_id); pd->thread_id = get_hard_smp_processor_id(cpu); - spin_lock_init(&pd->bmp.lock); + spin_lock_init(&pd->bmp_lock); - pr_debug("%s:%d: ppe_id %llu, thread_id %llu, bmp %lxh\n", + DBG("%s:%d: ppe_id %llu, thread_id %llu, bmp %lxh\n", __func__, __LINE__, pd->ppe_id, pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp))); @@ -755,7 +771,7 @@ void __init ps3_init_IRQ(void) pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp))); if (result) - pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" + FAIL("%s:%d: lv1_configure_irq_state_bitmap failed:" " %s\n", __func__, __LINE__, ps3_result(result)); } diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index c2045880e67..0c9f643d9e2 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -19,8 +19,7 @@ */ #include <linux/kernel.h> -#include <linux/module.h> -#include <linux/memory_hotplug.h> +#include <linux/export.h> #include <linux/memblock.h> #include <linux/slab.h> @@ -29,6 +28,7 @@ #include <asm/prom.h> #include <asm/udbg.h> #include <asm/lv1call.h> +#include <asm/setup.h> #include "platform.h" @@ -78,12 +78,14 @@ enum { * @base: base address * @size: size in bytes * @offset: difference between base and rm.size + * @destroy: flag if region should be destroyed upon shutdown */ struct mem_region { u64 base; u64 size; unsigned long offset; + int destroy; }; /** @@ -95,7 +97,7 @@ struct mem_region { * The HV virtual address space (vas) allows for hotplug memory regions. * Memory regions can be created and destroyed in the vas at runtime. * @rm: real mode (bootmem) region - * @r1: hotplug memory region(s) + * @r1: highmem region(s) * * ps3 addresses * virt_addr: a cpu 'translated' effective address @@ -221,10 +223,6 @@ void ps3_mm_vas_destroy(void) } } -/*============================================================================*/ -/* memory hotplug routines */ -/*============================================================================*/ - /** * ps3_mm_region_create - create a memory region in the vas * @r: pointer to a struct mem_region to accept initialized values @@ -261,6 +259,7 @@ static int ps3_mm_region_create(struct mem_region *r, unsigned long size) goto zero_region; } + r->destroy = 1; r->offset = r->base - map.rm.size; return result; @@ -278,7 +277,14 @@ static void ps3_mm_region_destroy(struct mem_region *r) { int result; + if (!r->destroy) { + pr_info("%s:%d: Not destroying high region: %llxh %llxh\n", + __func__, __LINE__, r->base, r->size); + return; + } + DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base); + if (r->base) { result = lv1_release_memory(r->base); BUG_ON(result); @@ -287,51 +293,36 @@ static void ps3_mm_region_destroy(struct mem_region *r) } } -/** - * ps3_mm_add_memory - hot add memory - */ - -static int __init ps3_mm_add_memory(void) +static int ps3_mm_get_repository_highmem(struct mem_region *r) { int result; - unsigned long start_addr; - unsigned long start_pfn; - unsigned long nr_pages; - - if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) - return -ENODEV; - BUG_ON(!mem_init_done); + /* Assume a single highmem region. */ - start_addr = map.rm.size; - start_pfn = start_addr >> PAGE_SHIFT; - nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; + result = ps3_repository_read_highmem_info(0, &r->base, &r->size); - DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n", - __func__, __LINE__, start_addr, start_pfn, nr_pages); - - result = add_memory(0, start_addr, map.r1.size); + if (result) + goto zero_region; - if (result) { - pr_err("%s:%d: add_memory failed: (%d)\n", - __func__, __LINE__, result); - return result; + if (!r->base || !r->size) { + result = -1; + goto zero_region; } - memblock_add(start_addr, map.r1.size); - memblock_analyze(); + r->offset = r->base - map.rm.size; - result = online_pages(start_pfn, nr_pages); + DBG("%s:%d: Found high region in repository: %llxh %llxh\n", + __func__, __LINE__, r->base, r->size); - if (result) - pr_err("%s:%d: online_pages failed: (%d)\n", - __func__, __LINE__, result); + return 0; +zero_region: + DBG("%s:%d: No high region in repository.\n", __func__, __LINE__); + + r->size = r->base = r->offset = 0; return result; } -device_initcall(ps3_mm_add_memory); - /*============================================================================*/ /* dma routines */ /*============================================================================*/ @@ -1217,13 +1208,23 @@ void __init ps3_mm_init(void) BUG_ON(map.rm.base); BUG_ON(!map.rm.size); + /* Check if we got the highmem region from an earlier boot step */ - /* arrange to do this in ps3_mm_add_memory */ - ps3_mm_region_create(&map.r1, map.total - map.rm.size); + if (ps3_mm_get_repository_highmem(&map.r1)) + ps3_mm_region_create(&map.r1, map.total - map.rm.size); /* correct map.total for the real total amount of memory we use */ map.total = map.rm.size + map.r1.size; + if (!map.r1.size) { + DBG("%s:%d: No highmem region found\n", __func__, __LINE__); + } else { + DBG("%s:%d: Adding highmem region: %llxh %llxh\n", + __func__, __LINE__, map.rm.size, + map.total - map.rm.size); + memblock_add(map.rm.size, map.total - map.rm.size); + } + DBG(" <- %s:%d\n", __func__, __LINE__); } diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index 5b759b66959..09787139834 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c @@ -23,6 +23,7 @@ #include <linux/workqueue.h> #include <linux/fs.h> #include <linux/syscalls.h> +#include <linux/export.h> #include <linux/ctype.h> #include <linux/memblock.h> #include <linux/of.h> @@ -279,13 +280,13 @@ static void os_area_set_property(struct device_node *node, if (tmp) { pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name); - prom_remove_property(node, tmp); + of_remove_property(node, tmp); } - result = prom_add_property(node, prop); + result = of_add_property(node, prop); if (result) - pr_debug("%s:%d prom_set_property failed\n", __func__, + pr_debug("%s:%d of_set_property failed\n", __func__, __LINE__); } diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 9a196a88eda..d71329a8e32 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h @@ -43,6 +43,7 @@ void ps3_mm_shutdown(void); void ps3_init_IRQ(void); void ps3_shutdown_IRQ(int cpu); void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); +void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq); /* smp */ @@ -187,6 +188,22 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size); int ps3_repository_read_region_total(u64 *region_total); int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total); +int ps3_repository_read_highmem_region_count(unsigned int *region_count); +int ps3_repository_read_highmem_base(unsigned int region_index, + u64 *highmem_base); +int ps3_repository_read_highmem_size(unsigned int region_index, + u64 *highmem_size); +int ps3_repository_read_highmem_info(unsigned int region_index, + u64 *highmem_base, u64 *highmem_size); + +int ps3_repository_write_highmem_region_count(unsigned int region_count); +int ps3_repository_write_highmem_base(unsigned int region_index, + u64 highmem_base); +int ps3_repository_write_highmem_size(unsigned int region_index, + u64 highmem_size); +int ps3_repository_write_highmem_info(unsigned int region_index, + u64 highmem_base, u64 highmem_size); +int ps3_repository_delete_highmem_info(unsigned int region_index); /* repository pme info */ diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index 5e304c292f6..bfccdc7cb85 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c @@ -44,7 +44,7 @@ static void _dump_field(const char *hdr, u64 n, const char *func, int line) s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.'; s[i] = 0; - pr_debug("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s); + pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s); #endif } @@ -53,7 +53,7 @@ static void _dump_field(const char *hdr, u64 n, const char *func, int line) static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, const char *func, int line) { - pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); + pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id); _dump_field("n1: ", n1, func, line); _dump_field("n2: ", n2, func, line); _dump_field("n3: ", n3, func, line); @@ -65,13 +65,13 @@ static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2, const char *func, int line) { - pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); + pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id); _dump_field("n1: ", n1, func, line); _dump_field("n2: ", n2, func, line); _dump_field("n3: ", n3, func, line); _dump_field("n4: ", n4, func, line); - pr_debug("%s:%d: v1: %016llx\n", func, line, v1); - pr_debug("%s:%d: v2: %016llx\n", func, line, v2); + pr_devel("%s:%d: v1: %016llx\n", func, line, v1); + pr_devel("%s:%d: v2: %016llx\n", func, line, v2); } /** @@ -131,11 +131,11 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, lpar_id = id; } - result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1, + result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1, &v2); if (result) { - pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", + pr_warn("%s:%d: lv1_read_repository_node failed: %s\n", __func__, __LINE__, ps3_result(result)); dump_node_name(lpar_id, n1, n2, n3, n4); return -ENOENT; @@ -149,10 +149,10 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, *_v2 = v2; if (v1 && !_v1) - pr_debug("%s:%d: warning: discarding non-zero v1: %016llx\n", + pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n", __func__, __LINE__, v1); if (v2 && !_v2) - pr_debug("%s:%d: warning: discarding non-zero v2: %016llx\n", + pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n", __func__, __LINE__, v2); return 0; @@ -184,7 +184,7 @@ int ps3_repository_read_bus_type(unsigned int bus_index, enum ps3_bus_type *bus_type) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -199,7 +199,7 @@ int ps3_repository_read_bus_num_dev(unsigned int bus_index, unsigned int *num_dev) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -239,7 +239,7 @@ int ps3_repository_read_dev_type(unsigned int bus_index, unsigned int dev_index, enum ps3_dev_type *dev_type) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -256,8 +256,8 @@ int ps3_repository_read_dev_intr(unsigned int bus_index, enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id) { int result; - u64 v1; - u64 v2; + u64 v1 = 0; + u64 v2 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -275,7 +275,7 @@ int ps3_repository_read_dev_reg_type(unsigned int bus_index, enum ps3_reg_type *reg_type) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -323,16 +323,16 @@ int ps3_repository_find_device(struct ps3_repository_device *repo) result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); if (result) { - pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); + pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); return result; } - pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n", + pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n", __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, num_dev); if (tmp.dev_index >= num_dev) { - pr_debug("%s:%d: no device found\n", __func__, __LINE__); + pr_devel("%s:%d: no device found\n", __func__, __LINE__); return -ENODEV; } @@ -340,7 +340,7 @@ int ps3_repository_find_device(struct ps3_repository_device *repo) &tmp.dev_type); if (result) { - pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__); + pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__); return result; } @@ -348,12 +348,12 @@ int ps3_repository_find_device(struct ps3_repository_device *repo) &tmp.dev_id); if (result) { - pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, + pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__, __LINE__); return result; } - pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n", + pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n", __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); *repo = tmp; @@ -367,14 +367,14 @@ int ps3_repository_find_device_by_id(struct ps3_repository_device *repo, struct ps3_repository_device tmp; unsigned int num_dev; - pr_debug(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__, + pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__, bus_id, dev_id); for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) { result = ps3_repository_read_bus_id(tmp.bus_index, &tmp.bus_id); if (result) { - pr_debug("%s:%u read_bus_id(%u) failed\n", __func__, + pr_devel("%s:%u read_bus_id(%u) failed\n", __func__, __LINE__, tmp.bus_index); return result; } @@ -382,23 +382,23 @@ int ps3_repository_find_device_by_id(struct ps3_repository_device *repo, if (tmp.bus_id == bus_id) goto found_bus; - pr_debug("%s:%u: skip, bus_id %llu\n", __func__, __LINE__, + pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__, tmp.bus_id); } - pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__); + pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__); return result; found_bus: result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type); if (result) { - pr_debug("%s:%u read_bus_type(%u) failed\n", __func__, + pr_devel("%s:%u read_bus_type(%u) failed\n", __func__, __LINE__, tmp.bus_index); return result; } result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); if (result) { - pr_debug("%s:%u read_bus_num_dev failed\n", __func__, + pr_devel("%s:%u read_bus_num_dev failed\n", __func__, __LINE__); return result; } @@ -408,7 +408,7 @@ found_bus: tmp.dev_index, &tmp.dev_id); if (result) { - pr_debug("%s:%u read_dev_id(%u:%u) failed\n", __func__, + pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__, __LINE__, tmp.bus_index, tmp.dev_index); return result; } @@ -416,45 +416,45 @@ found_bus: if (tmp.dev_id == dev_id) goto found_dev; - pr_debug("%s:%u: skip, dev_id %llu\n", __func__, __LINE__, + pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__, tmp.dev_id); } - pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__); + pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__); return result; found_dev: result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, &tmp.dev_type); if (result) { - pr_debug("%s:%u read_dev_type failed\n", __func__, __LINE__); + pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__); return result; } - pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n", + pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n", __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index, tmp.dev_index, tmp.bus_id, tmp.dev_id); *repo = tmp; return 0; } -int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, +int ps3_repository_find_devices(enum ps3_bus_type bus_type, int (*callback)(const struct ps3_repository_device *repo)) { int result = 0; struct ps3_repository_device repo; - pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); + pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); repo.bus_type = bus_type; result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); if (result) { - pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__); + pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__); return result; } result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); if (result) { - pr_debug("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__, + pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__, repo.bus_index); return result; } @@ -469,13 +469,13 @@ int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, result = callback(&repo); if (result) { - pr_debug("%s:%d: abort at callback\n", __func__, + pr_devel("%s:%d: abort at callback\n", __func__, __LINE__); break; } } - pr_debug(" <- %s:%d\n", __func__, __LINE__); + pr_devel(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -489,7 +489,7 @@ int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, for (i = from; i < 10; i++) { error = ps3_repository_read_bus_type(i, &type); if (error) { - pr_debug("%s:%d read_bus_type failed\n", + pr_devel("%s:%d read_bus_type failed\n", __func__, __LINE__); *bus_index = UINT_MAX; return error; @@ -509,7 +509,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, int result = 0; unsigned int res_index; - pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); + pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); *interrupt_id = UINT_MAX; @@ -521,7 +521,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, repo->dev_index, res_index, &t, &id); if (result) { - pr_debug("%s:%d read_dev_intr failed\n", + pr_devel("%s:%d read_dev_intr failed\n", __func__, __LINE__); return result; } @@ -535,7 +535,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, if (res_index == 10) return -ENODEV; - pr_debug("%s:%d: found intr_type %u at res_index %u\n", + pr_devel("%s:%d: found intr_type %u at res_index %u\n", __func__, __LINE__, intr_type, res_index); return result; @@ -547,7 +547,7 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo, int result = 0; unsigned int res_index; - pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); + pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); *bus_addr = *len = 0; @@ -560,7 +560,7 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo, repo->dev_index, res_index, &t, &a, &l); if (result) { - pr_debug("%s:%d read_dev_reg failed\n", + pr_devel("%s:%d read_dev_reg failed\n", __func__, __LINE__); return result; } @@ -575,7 +575,7 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo, if (res_index == 10) return -ENODEV; - pr_debug("%s:%d: found reg_type %u at res_index %u\n", + pr_devel("%s:%d: found reg_type %u at res_index %u\n", __func__, __LINE__, reg_type, res_index); return result; @@ -615,7 +615,7 @@ int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, unsigned int dev_index, unsigned int *num_regions) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -631,7 +631,7 @@ int ps3_repository_read_stor_dev_region_id(unsigned int bus_index, unsigned int *region_id) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), @@ -779,6 +779,72 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) } /** + * ps3_repository_read_highmem_region_count - Read the number of highmem regions + * + * Bootloaders must arrange the repository nodes such that regions are indexed + * with a region_index from 0 to region_count-1. + */ + +int ps3_repository_read_highmem_region_count(unsigned int *region_count) +{ + int result; + u64 v1 = 0; + + result = read_node(PS3_LPAR_ID_CURRENT, + make_first_field("highmem", 0), + make_field("region", 0), + make_field("count", 0), + 0, + &v1, NULL); + *region_count = v1; + return result; +} + + +int ps3_repository_read_highmem_base(unsigned int region_index, + u64 *highmem_base) +{ + return read_node(PS3_LPAR_ID_CURRENT, + make_first_field("highmem", 0), + make_field("region", region_index), + make_field("base", 0), + 0, + highmem_base, NULL); +} + +int ps3_repository_read_highmem_size(unsigned int region_index, + u64 *highmem_size) +{ + return read_node(PS3_LPAR_ID_CURRENT, + make_first_field("highmem", 0), + make_field("region", region_index), + make_field("size", 0), + 0, + highmem_size, NULL); +} + +/** + * ps3_repository_read_highmem_info - Read high memory region info + * @region_index: Region index, {0,..,region_count-1}. + * @highmem_base: High memory base address. + * @highmem_size: High memory size. + * + * Bootloaders that preallocate highmem regions must place the + * region info into the repository at these well known nodes. + */ + +int ps3_repository_read_highmem_info(unsigned int region_index, + u64 *highmem_base, u64 *highmem_size) +{ + int result; + + *highmem_base = 0; + result = ps3_repository_read_highmem_base(region_index, highmem_base); + return result ? result + : ps3_repository_read_highmem_size(region_index, highmem_size); +} + +/** * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. * @num_spu: Number of physical spus. */ @@ -786,7 +852,7 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -805,7 +871,7 @@ int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -827,8 +893,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index, enum ps3_spu_resource_type *resource_type, unsigned int *resource_id) { int result; - u64 v1; - u64 v2; + u64 v1 = 0; + u64 v2 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -854,7 +920,7 @@ static int ps3_repository_read_boot_dat_address(u64 *address) int ps3_repository_read_boot_dat_size(unsigned int *size) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -869,7 +935,7 @@ int ps3_repository_read_boot_dat_size(unsigned int *size) int ps3_repository_read_vuart_av_port(unsigned int *port) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -884,7 +950,7 @@ int ps3_repository_read_vuart_av_port(unsigned int *port) int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_CURRENT, make_first_field("bi", 0), @@ -919,7 +985,7 @@ int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) int ps3_repository_read_num_be(unsigned int *num_be) { int result; - u64 v1; + u64 v1 = 0; result = read_node(PS3_LPAR_ID_PME, make_first_field("ben", 0), @@ -1002,6 +1068,138 @@ int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar, lpar, rights); } +#if defined(CONFIG_PS3_REPOSITORY_WRITE) + +static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2) +{ + int result; + + dump_node(0, n1, n2, n3, n4, v1, v2); + + result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2); + + if (result) { + pr_devel("%s:%d: lv1_create_repository_node failed: %s\n", + __func__, __LINE__, ps3_result(result)); + return -ENOENT; + } + + return 0; +} + +static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4) +{ + int result; + + dump_node(0, n1, n2, n3, n4, 0, 0); + + result = lv1_delete_repository_node(n1, n2, n3, n4); + + if (result) { + pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n", + __func__, __LINE__, ps3_result(result)); + return -ENOENT; + } + + return 0; +} + +static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2) +{ + int result; + + result = create_node(n1, n2, n3, n4, v1, v2); + + if (!result) + return 0; + + result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2); + + if (result) { + pr_devel("%s:%d: lv1_write_repository_node failed: %s\n", + __func__, __LINE__, ps3_result(result)); + return -ENOENT; + } + + return 0; +} + +int ps3_repository_write_highmem_region_count(unsigned int region_count) +{ + int result; + u64 v1 = (u64)region_count; + + result = write_node( + make_first_field("highmem", 0), + make_field("region", 0), + make_field("count", 0), + 0, + v1, 0); + return result; +} + +int ps3_repository_write_highmem_base(unsigned int region_index, + u64 highmem_base) +{ + return write_node( + make_first_field("highmem", 0), + make_field("region", region_index), + make_field("base", 0), + 0, + highmem_base, 0); +} + +int ps3_repository_write_highmem_size(unsigned int region_index, + u64 highmem_size) +{ + return write_node( + make_first_field("highmem", 0), + make_field("region", region_index), + make_field("size", 0), + 0, + highmem_size, 0); +} + +int ps3_repository_write_highmem_info(unsigned int region_index, + u64 highmem_base, u64 highmem_size) +{ + int result; + + result = ps3_repository_write_highmem_base(region_index, highmem_base); + return result ? result + : ps3_repository_write_highmem_size(region_index, highmem_size); +} + +static int ps3_repository_delete_highmem_base(unsigned int region_index) +{ + return delete_node( + make_first_field("highmem", 0), + make_field("region", region_index), + make_field("base", 0), + 0); +} + +static int ps3_repository_delete_highmem_size(unsigned int region_index) +{ + return delete_node( + make_first_field("highmem", 0), + make_field("region", region_index), + make_field("size", 0), + 0); +} + +int ps3_repository_delete_highmem_info(unsigned int region_index) +{ + int result; + + result = ps3_repository_delete_highmem_base(region_index); + result += ps3_repository_delete_highmem_size(region_index); + + return result ? -1 : 0; +} + +#endif /* defined(CONFIG_PS3_WRITE_REPOSITORY) */ + #if defined(DEBUG) int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) @@ -1009,7 +1207,7 @@ int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) int result = 0; unsigned int res_index; - pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, + pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, repo->bus_index, repo->dev_index); for (res_index = 0; res_index < 10; res_index++) { @@ -1021,13 +1219,13 @@ int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) if (result) { if (result != LV1_NO_ENTRY) - pr_debug("%s:%d ps3_repository_read_dev_intr" + pr_devel("%s:%d ps3_repository_read_dev_intr" " (%u:%u) failed\n", __func__, __LINE__, repo->bus_index, repo->dev_index); break; } - pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", + pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", __func__, __LINE__, repo->bus_index, repo->dev_index, intr_type, interrupt_id); } @@ -1042,18 +1240,18 @@ int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) if (result) { if (result != LV1_NO_ENTRY) - pr_debug("%s:%d ps3_repository_read_dev_reg" + pr_devel("%s:%d ps3_repository_read_dev_reg" " (%u:%u) failed\n", __func__, __LINE__, repo->bus_index, repo->dev_index); break; } - pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", + pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n", __func__, __LINE__, repo->bus_index, repo->dev_index, reg_type, bus_addr, len); } - pr_debug(" <- %s:%d\n", __func__, __LINE__); + pr_devel(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -1063,22 +1261,22 @@ static int dump_stor_dev_info(struct ps3_repository_device *repo) unsigned int num_regions, region_index; u64 port, blk_size, num_blocks; - pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, + pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, repo->bus_index, repo->dev_index); result = ps3_repository_read_stor_dev_info(repo->bus_index, repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); if (result) { - pr_debug("%s:%d ps3_repository_read_stor_dev_info" + pr_devel("%s:%d ps3_repository_read_stor_dev_info" " (%u:%u) failed\n", __func__, __LINE__, repo->bus_index, repo->dev_index); goto out; } - pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " - "%lu, num_regions %u\n", - __func__, __LINE__, repo->bus_index, repo->dev_index, port, - blk_size, num_blocks, num_regions); + pr_devel("%s:%d (%u:%u): port %llu, blk_size %llu, num_blocks " + "%llu, num_regions %u\n", + __func__, __LINE__, repo->bus_index, repo->dev_index, + port, blk_size, num_blocks, num_regions); for (region_index = 0; region_index < num_regions; region_index++) { unsigned int region_id; @@ -1088,19 +1286,20 @@ static int dump_stor_dev_info(struct ps3_repository_device *repo) repo->dev_index, region_index, ®ion_id, ®ion_start, ®ion_size); if (result) { - pr_debug("%s:%d ps3_repository_read_stor_dev_region" + pr_devel("%s:%d ps3_repository_read_stor_dev_region" " (%u:%u) failed\n", __func__, __LINE__, repo->bus_index, repo->dev_index); break; } - pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", + pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", __func__, __LINE__, repo->bus_index, repo->dev_index, - region_id, region_start, region_size); + region_id, (unsigned long)region_start, + (unsigned long)region_size); } out: - pr_debug(" <- %s:%d\n", __func__, __LINE__); + pr_devel(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -1109,7 +1308,7 @@ static int dump_device_info(struct ps3_repository_device *repo, { int result = 0; - pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); + pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); for (repo->dev_index = 0; repo->dev_index < num_dev; repo->dev_index++) { @@ -1118,7 +1317,7 @@ static int dump_device_info(struct ps3_repository_device *repo, repo->dev_index, &repo->dev_type); if (result) { - pr_debug("%s:%d ps3_repository_read_dev_type" + pr_devel("%s:%d ps3_repository_read_dev_type" " (%u:%u) failed\n", __func__, __LINE__, repo->bus_index, repo->dev_index); break; @@ -1128,15 +1327,15 @@ static int dump_device_info(struct ps3_repository_device *repo, repo->dev_index, &repo->dev_id); if (result) { - pr_debug("%s:%d ps3_repository_read_dev_id" + pr_devel("%s:%d ps3_repository_read_dev_id" " (%u:%u) failed\n", __func__, __LINE__, repo->bus_index, repo->dev_index); continue; } - pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__, + pr_devel("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__, __LINE__, repo->bus_index, repo->dev_index, - repo->dev_type, repo->dev_id); + repo->dev_type, (unsigned long)repo->dev_id); ps3_repository_dump_resource_info(repo); @@ -1144,7 +1343,7 @@ static int dump_device_info(struct ps3_repository_device *repo, dump_stor_dev_info(repo); } - pr_debug(" <- %s:%d\n", __func__, __LINE__); + pr_devel(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -1153,7 +1352,7 @@ int ps3_repository_dump_bus_info(void) int result = 0; struct ps3_repository_device repo; - pr_debug(" -> %s:%d\n", __func__, __LINE__); + pr_devel(" -> %s:%d\n", __func__, __LINE__); memset(&repo, 0, sizeof(repo)); @@ -1164,7 +1363,7 @@ int ps3_repository_dump_bus_info(void) &repo.bus_type); if (result) { - pr_debug("%s:%d read_bus_type(%u) failed\n", + pr_devel("%s:%d read_bus_type(%u) failed\n", __func__, __LINE__, repo.bus_index); break; } @@ -1173,32 +1372,32 @@ int ps3_repository_dump_bus_info(void) &repo.bus_id); if (result) { - pr_debug("%s:%d read_bus_id(%u) failed\n", + pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__, repo.bus_index); continue; } if (repo.bus_index != repo.bus_id) - pr_debug("%s:%d bus_index != bus_id\n", + pr_devel("%s:%d bus_index != bus_id\n", __func__, __LINE__); result = ps3_repository_read_bus_num_dev(repo.bus_index, &num_dev); if (result) { - pr_debug("%s:%d read_bus_num_dev(%u) failed\n", + pr_devel("%s:%d read_bus_num_dev(%u) failed\n", __func__, __LINE__, repo.bus_index); continue; } - pr_debug("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n", + pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n", __func__, __LINE__, repo.bus_index, repo.bus_type, - repo.bus_id, num_dev); + (unsigned long)repo.bus_id, num_dev); dump_device_info(&repo, num_dev); } - pr_debug(" <- %s:%d\n", __func__, __LINE__); + pr_devel(" <- %s:%d\n", __func__, __LINE__); return result; } diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 149bea2ce58..3f509f86432 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -23,6 +23,7 @@ #include <linux/fs.h> #include <linux/root_dev.h> #include <linux/console.h> +#include <linux/export.h> #include <linux/bootmem.h> #include <asm/machdep.h> @@ -183,19 +184,25 @@ early_param("ps3flash", early_parse_ps3flash); #define prealloc_ps3flash_bounce_buffer() do { } while (0) #endif -static int ps3_set_dabr(unsigned long dabr) +static int ps3_set_dabr(unsigned long dabr, unsigned long dabrx) { - enum {DABR_USER = 1, DABR_KERNEL = 2,}; + /* Have to set at least one bit in the DABRX */ + if (dabrx == 0 && dabr == 0) + dabrx = DABRX_USER; + /* hypervisor only allows us to set BTI, Kernel and user */ + dabrx &= DABRX_BTI | DABRX_KERNEL | DABRX_USER; - return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0; + return lv1_set_dabr(dabr, dabrx) ? -1 : 0; } static void __init ps3_setup_arch(void) { + u64 tmp; DBG(" -> %s:%d\n", __func__, __LINE__); - lv1_get_version_info(&ps3_firmware_version.raw); + lv1_get_version_info(&ps3_firmware_version.raw, &tmp); + printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", ps3_firmware_version.major, ps3_firmware_version.minor, ps3_firmware_version.rev); diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index 51ffde40af2..b358bec6c8c 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c @@ -39,7 +39,7 @@ #define MSG_COUNT 4 static DEFINE_PER_CPU(unsigned int [MSG_COUNT], ps3_ipi_virqs); -static void do_message_pass(int target, int msg) +static void ps3_smp_message_pass(int cpu, int msg) { int result; unsigned int virq; @@ -49,72 +49,59 @@ static void do_message_pass(int target, int msg) return; } - virq = per_cpu(ps3_ipi_virqs, target)[msg]; + virq = per_cpu(ps3_ipi_virqs, cpu)[msg]; result = ps3_send_event_locally(virq); if (result) DBG("%s:%d: ps3_send_event_locally(%d, %d) failed" - " (%d)\n", __func__, __LINE__, target, msg, result); + " (%d)\n", __func__, __LINE__, cpu, msg, result); } -static void ps3_smp_message_pass(int target, int msg) +static int __init ps3_smp_probe(void) { int cpu; - if (target < NR_CPUS) - do_message_pass(target, msg); - else if (target == MSG_ALL_BUT_SELF) { - for_each_online_cpu(cpu) - if (cpu != smp_processor_id()) - do_message_pass(cpu, msg); - } else { - for_each_online_cpu(cpu) - do_message_pass(cpu, msg); - } -} + for (cpu = 0; cpu < 2; cpu++) { + int result; + unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); + int i; -static int ps3_smp_probe(void) -{ - return 2; -} + DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); -static void __init ps3_smp_setup_cpu(int cpu) -{ - int result; - unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); - int i; + /* + * Check assumptions on ps3_ipi_virqs[] indexing. If this + * check fails, then a different mapping of PPC_MSG_ + * to index needs to be setup. + */ - DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); + BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); + BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); + BUILD_BUG_ON(PPC_MSG_TICK_BROADCAST != 2); + BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); - /* - * Check assumptions on ps3_ipi_virqs[] indexing. If this - * check fails, then a different mapping of PPC_MSG_ - * to index needs to be setup. - */ + for (i = 0; i < MSG_COUNT; i++) { + result = ps3_event_receive_port_setup(cpu, &virqs[i]); - BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); - BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); - BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2); - BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); + if (result) + continue; - for (i = 0; i < MSG_COUNT; i++) { - result = ps3_event_receive_port_setup(cpu, &virqs[i]); + DBG("%s:%d: (%d, %d) => virq %u\n", + __func__, __LINE__, cpu, i, virqs[i]); - if (result) - continue; + result = smp_request_message_ipi(virqs[i], i); - DBG("%s:%d: (%d, %d) => virq %u\n", - __func__, __LINE__, cpu, i, virqs[i]); + if (result) + virqs[i] = NO_IRQ; + else + ps3_register_ipi_irq(cpu, virqs[i]); + } - result = smp_request_message_ipi(virqs[i], i); + ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); - if (result) - virqs[i] = NO_IRQ; + DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); } - ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); - - DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); + return 2; } void ps3_smp_cleanup_cpu(int cpu) @@ -137,7 +124,6 @@ static struct smp_ops_t ps3_smp_ops = { .probe = ps3_smp_probe, .message_pass = ps3_smp_message_pass, .kick_cpu = smp_generic_kick_cpu, - .setup_cpu = ps3_smp_setup_cpu, }; void smp_init_ps3(void) diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index 39a472e9e80..a0bca05e26b 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/mmzone.h> +#include <linux/export.h> #include <linux/io.h> #include <linux/mm.h> @@ -142,7 +143,7 @@ static void _dump_areas(unsigned int spe_id, unsigned long priv2, pr_debug("%s:%d: shadow: %lxh\n", func, line, shadow); } -inline u64 ps3_get_spe_id(void *arg) +u64 ps3_get_spe_id(void *arg) { return spu_pdata(arg)->spe_id; } @@ -153,7 +154,7 @@ static unsigned long get_vas_id(void) u64 id; lv1_get_logical_ppe_id(&id); - lv1_get_virtual_address_space_id_of_ppe(id, &id); + lv1_get_virtual_address_space_id_of_ppe(&id); return id; } @@ -197,7 +198,7 @@ static void spu_unmap(struct spu *spu) * The current HV requires the spu shadow regs to be mapped with the * PTE page protection bits set as read-only (PP=3). This implementation * uses the low level __ioremap() to bypass the page protection settings - * inforced by ioremap_flags() to get the needed PTE bits set for the + * inforced by ioremap_prot() to get the needed PTE bits set for the * shadow regs. */ @@ -214,7 +215,7 @@ static int __init setup_areas(struct spu *spu) goto fail_ioremap; } - spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys, + spu->local_store = (__force void *)ioremap_prot(spu->local_store_phys, LS_SIZE, _PAGE_NO_CACHE); if (!spu->local_store) { diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 23083c39752..5606fe36faf 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -20,7 +20,7 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/slab.h> @@ -515,7 +515,8 @@ core_initcall(ps3_system_bus_init); * to the dma address (mapping) of the first page. */ static void * ps3_alloc_coherent(struct device *_dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag, + struct dma_attrs *attrs) { int result; struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); @@ -552,7 +553,7 @@ clean_none: } static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, - dma_addr_t dma_handle) + dma_addr_t dma_handle, struct dma_attrs *attrs) { struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); @@ -695,22 +696,29 @@ static int ps3_dma_supported(struct device *_dev, u64 mask) return mask >= DMA_BIT_MASK(32); } +static u64 ps3_dma_get_required_mask(struct device *_dev) +{ + return DMA_BIT_MASK(32); +} + static struct dma_map_ops ps3_sb_dma_ops = { - .alloc_coherent = ps3_alloc_coherent, - .free_coherent = ps3_free_coherent, + .alloc = ps3_alloc_coherent, + .free = ps3_free_coherent, .map_sg = ps3_sb_map_sg, .unmap_sg = ps3_sb_unmap_sg, .dma_supported = ps3_dma_supported, + .get_required_mask = ps3_dma_get_required_mask, .map_page = ps3_sb_map_page, .unmap_page = ps3_unmap_page, }; static struct dma_map_ops ps3_ioc0_dma_ops = { - .alloc_coherent = ps3_alloc_coherent, - .free_coherent = ps3_free_coherent, + .alloc = ps3_alloc_coherent, + .free = ps3_free_coherent, .map_sg = ps3_ioc0_map_sg, .unmap_sg = ps3_ioc0_unmap_sg, .dma_supported = ps3_dma_supported, + .get_required_mask = ps3_dma_get_required_mask, .map_page = ps3_ioc0_map_page, .unmap_page = ps3_unmap_page, }; diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c index 40b5cb43300..ce73ce86561 100644 --- a/arch/powerpc/platforms/ps3/time.c +++ b/arch/powerpc/platforms/ps3/time.c @@ -89,10 +89,8 @@ static int __init ps3_rtc_init(void) return -ENODEV; pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - return 0; + return PTR_ERR_OR_ZERO(pdev); } module_init(ps3_rtc_init); |
