diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:55:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:55:47 -0700 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/platforms/cell | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'arch/powerpc/platforms/cell')
28 files changed, 421 insertions, 829 deletions
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index f88a7c76f29..61d12f18303 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -13,15 +13,13 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o endif # needed only when building loadable spufs.ko -spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o spu-manage-$(CONFIG_PPC_CELLEB) += spu_manage.o spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ - spu_coredump.o \ - $(spufs-modular-m) \ + spu_syscalls.o \ $(spu-priv1-y) \ $(spu-manage-y) \ spufs/ diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 4c9ab5b70ba..1245b2f517b 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -64,13 +64,11 @@ struct axon_msic { - struct device_node *dn; struct irq_host *irq_host; __le32 *fifo; dcr_host_t dcr_host; struct list_head list; u32 read_offset; - u32 dcr_base; }; static LIST_HEAD(axon_msic_list); @@ -79,12 +77,12 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) { pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); - dcr_write(msic->dcr_host, msic->dcr_base + dcr_n, val); + dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val); } static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n) { - return dcr_read(msic->dcr_host, msic->dcr_base + dcr_n); + return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n); } static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) @@ -126,7 +124,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) const phandle *ph; struct axon_msic *msic = NULL; - dn = pci_device_to_OF_node(dev); + dn = of_node_get(pci_device_to_OF_node(dev)); if (!dn) { dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); return NULL; @@ -183,7 +181,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) int len; const u32 *prop; - dn = pci_device_to_OF_node(dev); + dn = of_node_get(pci_device_to_OF_node(dev)); if (!dn) { dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); return -ENODEV; @@ -295,15 +293,7 @@ static int msic_host_map(struct irq_host *h, unsigned int virq, return 0; } -static int msic_host_match(struct irq_host *host, struct device_node *dn) -{ - struct axon_msic *msic = host->host_data; - - return msic->dn == dn; -} - static struct irq_host_ops msic_host_ops = { - .match = msic_host_match, .map = msic_host_map, }; @@ -314,7 +304,8 @@ static int axon_msi_notify_reboot(struct notifier_block *nb, u32 tmp; list_for_each_entry(msic, &axon_msic_list, list) { - pr_debug("axon_msi: disabling %s\n", msic->dn->full_name); + pr_debug("axon_msi: disabling %s\n", + msic->irq_host->of_node->full_name); tmp = msic_dcr_read(msic, MSIC_CTRL_REG); tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; msic_dcr_write(msic, MSIC_CTRL_REG, tmp); @@ -332,7 +323,7 @@ static int axon_msi_setup_one(struct device_node *dn) struct page *page; struct axon_msic *msic; unsigned int virq; - int dcr_len; + int dcr_base, dcr_len; pr_debug("axon_msi: setting up dn %s\n", dn->full_name); @@ -343,17 +334,17 @@ static int axon_msi_setup_one(struct device_node *dn) goto out; } - msic->dcr_base = dcr_resource_start(dn, 0); + dcr_base = dcr_resource_start(dn, 0); dcr_len = dcr_resource_len(dn, 0); - if (msic->dcr_base == 0 || dcr_len == 0) { + if (dcr_base == 0 || dcr_len == 0) { printk(KERN_ERR "axon_msi: couldn't parse dcr properties on %s\n", dn->full_name); goto out; } - msic->dcr_host = dcr_map(dn, msic->dcr_base, dcr_len); + msic->dcr_host = dcr_map(dn, dcr_base, dcr_len); if (!DCR_MAP_OK(msic->dcr_host)) { printk(KERN_ERR "axon_msi: dcr_map failed for %s\n", dn->full_name); @@ -370,8 +361,8 @@ static int axon_msi_setup_one(struct device_node *dn) msic->fifo = page_address(page); - msic->irq_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, NR_IRQS, - &msic_host_ops, 0); + msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, + NR_IRQS, &msic_host_ops, 0); if (!msic->irq_host) { printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", dn->full_name); @@ -387,8 +378,6 @@ static int axon_msi_setup_one(struct device_node *dn) goto out_free_host; } - msic->dn = of_node_get(dn); - set_irq_data(virq, msic); set_irq_chained_handler(virq, axon_msi_cascade); pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index 0b6e8ee85ab..901236fa0f0 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -24,7 +24,7 @@ #include <asm/machdep.h> #include <asm/of_platform.h> #include <asm/prom.h> -#include "cbe_regs.h" +#include <asm/cell-regs.h> #include "cbe_cpufreq.h" static DEFINE_MUTEX(cbe_switch_mutex); diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c index 163263b3e1c..70fa7aef5ed 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c @@ -28,8 +28,8 @@ #include <linux/time.h> #include <asm/machdep.h> #include <asm/hw_irq.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "cbe_cpufreq.h" /* to write to MIC register */ diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c index fc6f38982ff..6a2c1b0a9a9 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c @@ -27,12 +27,12 @@ #include <asm/processor.h> #include <asm/prom.h> #include <asm/pmi.h> +#include <asm/cell-regs.h> #ifdef DEBUG #include <asm/time.h> #endif -#include "cbe_regs.h" #include "cbe_cpufreq.h" static u8 pmi_slow_mode_limit[MAX_CBE]; diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index c8f7f000742..16a9b07e7b0 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -16,8 +16,7 @@ #include <asm/ptrace.h> #include <asm/of_device.h> #include <asm/of_platform.h> - -#include "cbe_regs.h" +#include <asm/cell-regs.h> /* * Current implementation uses "cpu" nodes. We build our own mapping diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h deleted file mode 100644 index b24025f2ac7..00000000000 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * cbe_regs.h - * - * This file is intended to hold the various register definitions for CBE - * on-chip system devices (memory controller, IO controller, etc...) - * - * (C) Copyright IBM Corporation 2001,2006 - * - * Authors: Maximino Aguilar (maguilar@us.ibm.com) - * David J. Erb (djerb@us.ibm.com) - * - * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. - */ - -#ifndef CBE_REGS_H -#define CBE_REGS_H - -#include <asm/cell-pmu.h> - -/* - * - * Some HID register definitions - * - */ - -/* CBE specific HID0 bits */ -#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul -#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul -#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul -#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul - -#define MAX_CBE 2 - -/* - * - * Pervasive unit register definitions - * - */ - -union spe_reg { - u64 val; - u8 spe[8]; -}; - -union ppe_spe_reg { - u64 val; - struct { - u32 ppe; - u32 spe; - }; -}; - - -struct cbe_pmd_regs { - /* Debug Bus Control */ - u64 pad_0x0000; /* 0x0000 */ - - u64 group_control; /* 0x0008 */ - - u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */ - - u64 debug_bus_control; /* 0x00a8 */ - - u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */ - - u64 trace_aux_data; /* 0x0100 */ - u64 trace_buffer_0_63; /* 0x0108 */ - u64 trace_buffer_64_127; /* 0x0110 */ - u64 trace_address; /* 0x0118 */ - u64 ext_tr_timer; /* 0x0120 */ - - u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */ - - /* Performance Monitor */ - u64 pm_status; /* 0x0400 */ - u64 pm_control; /* 0x0408 */ - u64 pm_interval; /* 0x0410 */ - u64 pm_ctr[4]; /* 0x0418 */ - u64 pm_start_stop; /* 0x0438 */ - u64 pm07_control[8]; /* 0x0440 */ - - u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */ - - /* Thermal Sensor Registers */ - union spe_reg ts_ctsr1; /* 0x0800 */ - u64 ts_ctsr2; /* 0x0808 */ - union spe_reg ts_mtsr1; /* 0x0810 */ - u64 ts_mtsr2; /* 0x0818 */ - union spe_reg ts_itr1; /* 0x0820 */ - u64 ts_itr2; /* 0x0828 */ - u64 ts_gitr; /* 0x0830 */ - u64 ts_isr; /* 0x0838 */ - u64 ts_imr; /* 0x0840 */ - union spe_reg tm_cr1; /* 0x0848 */ - u64 tm_cr2; /* 0x0850 */ - u64 tm_simr; /* 0x0858 */ - union ppe_spe_reg tm_tpr; /* 0x0860 */ - union spe_reg tm_str1; /* 0x0868 */ - u64 tm_str2; /* 0x0870 */ - union ppe_spe_reg tm_tsr; /* 0x0878 */ - - /* Power Management */ - u64 pmcr; /* 0x0880 */ -#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 - u64 pmsr; /* 0x0888 */ - - /* Time Base Register */ - u64 tbr; /* 0x0890 */ - - u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ - - /* Fault Isolation Registers */ - u64 checkstop_fir; /* 0x0c00 */ - u64 recoverable_fir; /* 0x0c08 */ - u64 spec_att_mchk_fir; /* 0x0c10 */ - u32 fir_mode_reg; /* 0x0c18 */ - u8 pad_0x0c1c_0x0c20 [4]; /* 0x0c1c */ -#define CBE_PMD_FIR_MODE_M8 0x00800 - u64 fir_enable_mask; /* 0x0c20 */ - - u8 pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28]; /* 0x0c28 */ - u64 ras_esc_0; /* 0x0ca8 */ - u8 pad_0x0cb0_0x1000 [0x1000 - 0x0cb0]; /* 0x0cb0 */ -}; - -extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); -extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); - -/* - * PMU shadow registers - * - * Many of the registers in the performance monitoring unit are write-only, - * so we need to save a copy of what we write to those registers. - * - * The actual data counters are read/write. However, writing to the counters - * only takes effect if the PMU is enabled. Otherwise the value is stored in - * a hardware latch until the next time the PMU is enabled. So we save a copy - * of the counter values if we need to read them back while the PMU is - * disabled. The counter_value_in_latch field is a bitmap indicating which - * counters currently have a value waiting to be written. - */ - -struct cbe_pmd_shadow_regs { - u32 group_control; - u32 debug_bus_control; - u32 trace_address; - u32 ext_tr_timer; - u32 pm_status; - u32 pm_control; - u32 pm_interval; - u32 pm_start_stop; - u32 pm07_control[NR_CTRS]; - - u32 pm_ctr[NR_PHYS_CTRS]; - u32 counter_value_in_latch; -}; - -extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np); -extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu); - -/* - * - * IIC unit register definitions - * - */ - -struct cbe_iic_pending_bits { - u32 data; - u8 flags; - u8 class; - u8 source; - u8 prio; -}; - -#define CBE_IIC_IRQ_VALID 0x80 -#define CBE_IIC_IRQ_IPI 0x40 - -struct cbe_iic_thread_regs { - struct cbe_iic_pending_bits pending; - struct cbe_iic_pending_bits pending_destr; - u64 generate; - u64 prio; -}; - -struct cbe_iic_regs { - u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */ - - /* IIC interrupt registers */ - struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ - - u64 iic_ir; /* 0x0440 */ -#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12) -#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4) -#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf) -#define CBE_IIC_IR_IOC_0 0x0 -#define CBE_IIC_IR_IOC_1S 0xb -#define CBE_IIC_IR_PT_0 0xe -#define CBE_IIC_IR_PT_1 0xf - - u64 iic_is; /* 0x0448 */ -#define CBE_IIC_IS_PMI 0x2 - - u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ - - /* IOC FIR */ - u64 ioc_fir_reset; /* 0x0500 */ - u64 ioc_fir_set; /* 0x0508 */ - u64 ioc_checkstop_enable; /* 0x0510 */ - u64 ioc_fir_error_mask; /* 0x0518 */ - u64 ioc_syserr_enable; /* 0x0520 */ - u64 ioc_fir; /* 0x0528 */ - - u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ -}; - -extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); -extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); - - -struct cbe_mic_tm_regs { - u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */ - - u64 mic_ctl_cnfg2; /* 0x0040 */ -#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL -#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL -#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL -#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL - - u64 pad_0x0048; /* 0x0048 */ - - u64 mic_aux_trc_base; /* 0x0050 */ - u64 mic_aux_trc_max_addr; /* 0x0058 */ - u64 mic_aux_trc_cur_addr; /* 0x0060 */ - u64 mic_aux_trc_grf_addr; /* 0x0068 */ - u64 mic_aux_trc_grf_data; /* 0x0070 */ - - u64 pad_0x0078; /* 0x0078 */ - - u64 mic_ctl_cnfg_0; /* 0x0080 */ -#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL - - u64 pad_0x0088; /* 0x0088 */ - - u64 slow_fast_timer_0; /* 0x0090 */ - u64 slow_next_timer_0; /* 0x0098 */ - - u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */ - - u64 mic_ctl_cnfg_1; /* 0x01c0 */ -#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL - u64 pad_0x01c8; /* 0x01c8 */ - - u64 slow_fast_timer_1; /* 0x01d0 */ - u64 slow_next_timer_1; /* 0x01d8 */ - - u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */ -}; - -extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); -extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); - -/* some utility functions to deal with SMT */ -extern u32 cbe_get_hw_thread_id(int cpu); -extern u32 cbe_cpu_to_node(int cpu); -extern u32 cbe_node_to_cpu(int node); - -/* Init this module early */ -extern void cbe_regs_init(void); - - -#endif /* CBE_REGS_H */ diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index fb5eda48467..4852bf312d8 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -52,8 +52,8 @@ #include <asm/spu.h> #include <asm/io.h> #include <asm/prom.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "spu_priv1_mmio.h" #define TEMP_MIN 65 diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 47264e72202..151fd8b82d6 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -41,9 +41,9 @@ #include <asm/prom.h> #include <asm/ptrace.h> #include <asm/machdep.h> +#include <asm/cell-regs.h> #include "interrupt.h" -#include "cbe_regs.h" struct iic { struct cbe_iic_thread_regs __iomem *regs; @@ -381,7 +381,7 @@ static int __init setup_iic(void) void __init iic_init_IRQ(void) { /* Setup an irq host data structure */ - iic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT, + iic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT, &iic_host_ops, IIC_IRQ_INVALID); BUG_ON(iic_host == NULL); irq_set_default_host(iic_host); diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 760caa76841..faabc3fdc13 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -34,8 +34,8 @@ #include <asm/udbg.h> #include <asm/of_platform.h> #include <asm/lmb.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "interrupt.h" /* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 4ede22d363f..0304589c0a8 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -34,9 +34,9 @@ #include <asm/prom.h> #include <asm/pgtable.h> #include <asm/reg.h> +#include <asm/cell-regs.h> #include "pervasive.h" -#include "cbe_regs.h" static int sysreset_hack; diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index 66ca4b5a1db..1ed30367888 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c @@ -30,8 +30,8 @@ #include <asm/pmc.h> #include <asm/reg.h> #include <asm/spu.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "interrupt.h" /* diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 3961a085b43..b2494ebcdbe 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -10,9 +10,9 @@ #include <asm/prom.h> #include <asm/machdep.h> #include <asm/rtas.h> +#include <asm/cell-regs.h> #include "ras.h" -#include "cbe_regs.h" static void dump_fir(int cpu) diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index db6654272e1..98e7ef8e6fc 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -52,9 +52,9 @@ #include <asm/udbg.h> #include <asm/mpic.h> #include <asm/of_platform.h> +#include <asm/cell-regs.h> #include "interrupt.h" -#include "cbe_regs.h" #include "pervasive.h" #include "ras.h" @@ -83,12 +83,22 @@ static void cell_progress(char *s, unsigned short hex) static int __init cell_publish_devices(void) { + int node; + if (!machine_is(cell)) return 0; /* Publish OF platform devices for southbridge IOs */ of_platform_bus_probe(NULL, NULL, NULL); + /* There is no device for the MIC memory controller, thus we create + * a platform device for it to attach the EDAC driver to. + */ + for_each_online_node(node) { + if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL) + continue; + platform_device_register_simple("cbe-mic", node, NULL, 0); + } return 0; } device_initcall(cell_publish_devices); @@ -161,11 +171,6 @@ static void __init cell_setup_arch(void) /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000; - if (ROOT_DEV == 0) { - printk("No ramdisk, default root is /dev/hda2\n"); - ROOT_DEV = Root_HDA2; - } - /* Find and initialize PCI host bridges */ init_pci_config_tokens(); find_and_init_phbs(); diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 05f4b3d3d75..3f4b4aef756 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -63,7 +63,6 @@ enum { struct spider_pic { struct irq_host *host; - struct device_node *of_node; void __iomem *regs; unsigned int node_id; }; @@ -176,12 +175,6 @@ static struct irq_chip spider_pic = { .set_type = spider_set_irq_type, }; -static int spider_host_match(struct irq_host *h, struct device_node *node) -{ - struct spider_pic *pic = h->host_data; - return node == pic->of_node; -} - static int spider_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -208,7 +201,6 @@ static int spider_host_xlate(struct irq_host *h, struct device_node *ct, } static struct irq_host_ops spider_host_ops = { - .match = spider_host_match, .map = spider_host_map, .xlate = spider_host_xlate, }; @@ -247,18 +239,18 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) * tree in case the device-tree is ever fixed */ struct of_irq oirq; - if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) { + if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) { virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); return virq; } /* Now do the horrible hacks */ - tmp = of_get_property(pic->of_node, "#interrupt-cells", NULL); + tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL); if (tmp == NULL) return NO_IRQ; intsize = *tmp; - imap = of_get_property(pic->of_node, "interrupt-map", &imaplen); + imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen); if (imap == NULL || imaplen < (intsize + 1)) return NO_IRQ; iic = of_find_node_by_phandle(imap[intsize]); @@ -308,15 +300,13 @@ static void __init spider_init_one(struct device_node *of_node, int chip, panic("spider_pic: can't map registers !"); /* Allocate a host */ - pic->host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, SPIDER_SRC_COUNT, - &spider_host_ops, SPIDER_IRQ_INVALID); + pic->host = irq_alloc_host(of_node_get(of_node), IRQ_HOST_MAP_LINEAR, + SPIDER_SRC_COUNT, &spider_host_ops, + SPIDER_IRQ_INVALID); if (pic->host == NULL) panic("spider_pic: can't allocate irq host !"); pic->host->host_data = pic; - /* Fill out other bits */ - pic->of_node = of_node_get(of_node); - /* Go through all sources and disable them */ for (i = 0; i < SPIDER_SRC_COUNT; i++) { void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i; diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 106d2921e2d..c83c3e3f517 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -168,7 +168,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) #else psize = mm->context.user_psize; #endif - vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | + vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | SLB_VSID_USER; break; case VMALLOC_REGION_ID: @@ -176,12 +176,12 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) psize = mmu_vmalloc_psize; else psize = mmu_io_psize; - vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL; break; case KERNEL_REGION_ID: psize = mmu_linear_psize; - vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL; break; default: @@ -458,7 +458,7 @@ static int spu_shutdown(struct sys_device *sysdev) return 0; } -struct sysdev_class spu_sysdev_class = { +static struct sysdev_class spu_sysdev_class = { set_kset_name("spu"), .shutdown = spu_shutdown, }; diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index 47ec3be3edc..dceb8b6a938 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -2,7 +2,7 @@ * System call callback functions for SPUs */ -#define DEBUG +#undef DEBUG #include <linux/kallsyms.h> #include <linux/module.h> @@ -33,7 +33,7 @@ * mbind, mq_open, ipc, ... */ -void *spu_syscall_table[] = { +static void *spu_syscall_table[] = { #define SYSCALL(func) sys_ni_syscall, #define COMPAT_SYS(func) sys_ni_syscall, #define PPC_SYS(func) sys_ni_syscall, diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c deleted file mode 100644 index 4fd37ff1e21..00000000000 --- a/arch/powerpc/platforms/cell/spu_coredump.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SPU core dump code - * - * (C) Copyright 2006 IBM Corp. - * - * Author: Dwayne Grant McConnell <decimal@us.ibm.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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/file.h> -#include <linux/module.h> -#include <linux/syscalls.h> - -#include <asm/spu.h> - -static struct spu_coredump_calls *spu_coredump_calls; -static DEFINE_MUTEX(spu_coredump_mutex); - -int arch_notes_size(void) -{ - long ret; - - ret = -ENOSYS; - mutex_lock(&spu_coredump_mutex); - if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { - ret = spu_coredump_calls->arch_notes_size(); - module_put(spu_coredump_calls->owner); - } - mutex_unlock(&spu_coredump_mutex); - return ret; -} - -void arch_write_notes(struct file *file) -{ - mutex_lock(&spu_coredump_mutex); - if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { - spu_coredump_calls->arch_write_notes(file); - module_put(spu_coredump_calls->owner); - } - mutex_unlock(&spu_coredump_mutex); -} - -int register_arch_coredump_calls(struct spu_coredump_calls *calls) -{ - int ret = 0; - - - mutex_lock(&spu_coredump_mutex); - if (spu_coredump_calls) - ret = -EBUSY; - else - spu_coredump_calls = calls; - mutex_unlock(&spu_coredump_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(register_arch_coredump_calls); - -void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) -{ - BUG_ON(spu_coredump_calls != calls); - - mutex_lock(&spu_coredump_mutex); - spu_coredump_calls = NULL; - mutex_unlock(&spu_coredump_mutex); -} -EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 0e14f532500..1b010707488 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -377,10 +377,10 @@ static int qs20_reg_memory[QS20_SPES_PER_BE] = { 1, 1, 0, 0, 0, 0, 0, 0 }; static struct spu *spu_lookup_reg(int node, u32 reg) { struct spu *spu; - u32 *spu_reg; + const u32 *spu_reg; list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { - spu_reg = (u32*)of_get_property(spu_devnode(spu), "reg", NULL); + spu_reg = of_get_property(spu_devnode(spu), "reg", NULL); if (*spu_reg == reg) return spu; } diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c index 027ac32cc63..a9438b719fe 100644 --- a/arch/powerpc/platforms/cell/spu_syscalls.c +++ b/arch/powerpc/platforms/cell/spu_syscalls.c @@ -2,6 +2,7 @@ * SPU file system -- system call stubs * * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * (C) Copyright 2006-2007, IBM Corporation * * Author: Arnd Bergmann <arndb@de.ibm.com> * @@ -20,44 +21,73 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/file.h> +#include <linux/fs.h> #include <linux/module.h> #include <linux/syscalls.h> +#include <linux/rcupdate.h> #include <asm/spu.h> -struct spufs_calls spufs_calls = { - .owner = NULL, -}; +/* protected by rcu */ +static struct spufs_calls *spufs_calls; -/* These stub syscalls are needed to have the actual implementation - * within a loadable module. When spufs is built into the kernel, - * this file is not used and the syscalls directly enter the fs code */ +#ifdef CONFIG_SPU_FS_MODULE + +static inline struct spufs_calls *spufs_calls_get(void) +{ + struct spufs_calls *calls = NULL; + + rcu_read_lock(); + calls = rcu_dereference(spufs_calls); + if (calls && !try_module_get(calls->owner)) + calls = NULL; + rcu_read_unlock(); + + return calls; +} + +static inline void spufs_calls_put(struct spufs_calls *calls) +{ + BUG_ON(calls != spufs_calls); + + /* we don't need to rcu this, as we hold a reference to the module */ + module_put(spufs_calls->owner); +} + +#else /* !defined CONFIG_SPU_FS_MODULE */ + +static inline struct spufs_calls *spufs_calls_get(void) +{ + return spufs_calls; +} + +static inline void spufs_calls_put(struct spufs_calls *calls) { } + +#endif /* CONFIG_SPU_FS_MODULE */ asmlinkage long sys_spu_create(const char __user *name, unsigned int flags, mode_t mode, int neighbor_fd) { long ret; - struct module *owner = spufs_calls.owner; struct file *neighbor; int fput_needed; + struct spufs_calls *calls; - ret = -ENOSYS; - if (owner && try_module_get(owner)) { - if (flags & SPU_CREATE_AFFINITY_SPU) { - neighbor = fget_light(neighbor_fd, &fput_needed); - ret = -EBADF; - if (neighbor) { - ret = spufs_calls.create_thread(name, flags, - mode, neighbor); - fput_light(neighbor, fput_needed); - } - } - else { - ret = spufs_calls.create_thread(name, flags, - mode, NULL); + calls = spufs_calls_get(); + if (!calls) + return -ENOSYS; + + if (flags & SPU_CREATE_AFFINITY_SPU) { + ret = -EBADF; + neighbor = fget_light(neighbor_fd, &fput_needed); + if (neighbor) { + ret = calls->create_thread(name, flags, mode, neighbor); + fput_light(neighbor, fput_needed); } - module_put(owner); - } + } else + ret = calls->create_thread(name, flags, mode, NULL); + + spufs_calls_put(calls); return ret; } @@ -66,37 +96,69 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) long ret; struct file *filp; int fput_needed; - struct module *owner = spufs_calls.owner; + struct spufs_calls *calls; - ret = -ENOSYS; - if (owner && try_module_get(owner)) { - ret = -EBADF; - filp = fget_light(fd, &fput_needed); - if (filp) { - ret = spufs_calls.spu_run(filp, unpc, ustatus); - fput_light(filp, fput_needed); - } - module_put(owner); + calls = spufs_calls_get(); + if (!calls) + return -ENOSYS; + + ret = -EBADF; + filp = fget_light(fd, &fput_needed); + if (filp) { + ret = calls->spu_run(filp, unpc, ustatus); + fput_light(filp, fput_needed); } + + spufs_calls_put(calls); + return ret; +} + +int elf_coredump_extra_notes_size(void) +{ + struct spufs_calls *calls; + int ret; + + calls = spufs_calls_get(); + if (!calls) + return 0; + + ret = calls->coredump_extra_notes_size(); + + spufs_calls_put(calls); + + return ret; +} + +int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset) +{ + struct spufs_calls *calls; + int ret; + + calls = spufs_calls_get(); + if (!calls) + return 0; + + ret = calls->coredump_extra_notes_write(file, foffset); + + spufs_calls_put(calls); + return ret; } int register_spu_syscalls(struct spufs_calls *calls) { - if (spufs_calls.owner) + if (spufs_calls) return -EBUSY; - spufs_calls.create_thread = calls->create_thread; - spufs_calls.spu_run = calls->spu_run; - smp_mb(); - spufs_calls.owner = calls->owner; + rcu_assign_pointer(spufs_calls, calls); return 0; } EXPORT_SYMBOL_GPL(register_spu_syscalls); void unregister_spu_syscalls(struct spufs_calls *calls) { - BUG_ON(spufs_calls.owner != calls->owner); - spufs_calls.owner = NULL; + BUG_ON(spufs_calls->owner != calls->owner); + rcu_assign_pointer(spufs_calls, NULL); + synchronize_rcu(); } EXPORT_SYMBOL_GPL(unregister_spu_syscalls); diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 5e31799b1e3..80f62363e1c 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -31,16 +31,7 @@ #include "spufs.h" -struct spufs_ctx_info { - struct list_head list; - int dfd; - int memsize; /* in bytes */ - struct spu_context *ctx; -}; - -static LIST_HEAD(ctx_info_list); - -static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer, +static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer, size_t size, loff_t *off) { u64 data; @@ -50,49 +41,57 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *b return spufs_coredump_read[num].read(ctx, buffer, size, off); data = spufs_coredump_read[num].get(ctx); - ret = copy_to_user(buffer, &data, 8); - return ret ? -EFAULT : 8; + ret = snprintf(buffer, size, "0x%.16lx", data); + if (ret >= size) + return size; + return ++ret; /* count trailing NULL */ } /* * These are the only things you should do on a core-file: use only these * functions to write out all the necessary info. */ -static int spufs_dump_write(struct file *file, const void *addr, int nr) +static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset) { - return file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} + unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; + ssize_t written; -static int spufs_dump_seek(struct file *file, loff_t off) -{ - if (file->f_op->llseek) { - if (file->f_op->llseek(file, off, 0) != off) - return 0; - } else - file->f_pos = off; - return 1; + if (*foffset + nr > limit) + return -EIO; + + written = file->f_op->write(file, addr, nr, &file->f_pos); + *foffset += written; + + if (written != nr) + return -EIO; + + return 0; } -static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info) +static int spufs_dump_align(struct file *file, char *buf, loff_t new_off, + loff_t *foffset) { - struct spu_context *ctx; - unsigned long long lslr; + int rc, size; + + size = min((loff_t)PAGE_SIZE, new_off - *foffset); + memset(buf, 0, size); + + rc = 0; + while (rc == 0 && new_off > *foffset) { + size = min((loff_t)PAGE_SIZE, new_off - *foffset); + rc = spufs_dump_write(file, buf, size, foffset); + } - ctx = ctx_info->ctx; - lslr = ctx->csa.priv2.spu_lslr_RW; - ctx_info->memsize = lslr + 1; + return rc; } -static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) +static int spufs_ctx_note_size(struct spu_context *ctx, int dfd) { - int dfd, memsize, i, sz, total = 0; + int i, sz, total = 0; char *name; char fullname[80]; - dfd = ctx_info->dfd; - memsize = ctx_info->memsize; - - for (i = 0; spufs_coredump_read[i].name; i++) { + for (i = 0; spufs_coredump_read[i].name != NULL; i++) { name = spufs_coredump_read[i].name; sz = spufs_coredump_read[i].size; @@ -100,39 +99,12 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) total += sizeof(struct elf_note); total += roundup(strlen(fullname) + 1, 4); - if (!strcmp(name, "mem")) - total += roundup(memsize, 4); - else - total += roundup(sz, 4); + total += roundup(sz, 4); } return total; } -static int spufs_add_one_context(struct file *file, int dfd) -{ - struct spu_context *ctx; - struct spufs_ctx_info *ctx_info; - int size; - - ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; - if (ctx->flags & SPU_CREATE_NOSCHED) - return 0; - - ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL); - if (unlikely(!ctx_info)) - return -ENOMEM; - - ctx_info->dfd = dfd; - ctx_info->ctx = ctx; - - spufs_fill_memsize(ctx_info); - - size = spufs_ctx_note_size(ctx_info); - list_add(&ctx_info->list, &ctx_info_list); - return size; -} - /* * The additional architecture-specific notes for Cell are various * context files in the spu context. @@ -142,33 +114,57 @@ static int spufs_add_one_context(struct file *file, int dfd) * internal functionality to dump them without needing to actually * open the files. */ -static int spufs_arch_notes_size(void) +static struct spu_context *coredump_next_context(int *fd) { struct fdtable *fdt = files_fdtable(current->files); - int size = 0, fd; + struct file *file; + struct spu_context *ctx = NULL; - for (fd = 0; fd < fdt->max_fds; fd++) { - if (FD_ISSET(fd, fdt->open_fds)) { - struct file *file = fcheck(fd); + for (; *fd < fdt->max_fds; (*fd)++) { + if (!FD_ISSET(*fd, fdt->open_fds)) + continue; - if (file && file->f_op == &spufs_context_fops) { - int rval = spufs_add_one_context(file, fd); - if (rval < 0) - break; - size += rval; - } - } + file = fcheck(*fd); + + if (!file || file->f_op != &spufs_context_fops) + continue; + + ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; + if (ctx->flags & SPU_CREATE_NOSCHED) + continue; + + /* start searching the next fd next time we're called */ + (*fd)++; + break; } - return size; + return ctx; } -static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, - struct file *file) +int spufs_coredump_extra_notes_size(void) { struct spu_context *ctx; + int size = 0, rc, fd; + + fd = 0; + while ((ctx = coredump_next_context(&fd)) != NULL) { + spu_acquire_saved(ctx); + rc = spufs_ctx_note_size(ctx, fd); + spu_release_saved(ctx); + if (rc < 0) + break; + + size += rc; + } + + return size; +} + +static int spufs_arch_write_note(struct spu_context *ctx, int i, + struct file *file, int dfd, loff_t *foffset) +{ loff_t pos = 0; - int sz, dfd, rc, total = 0; + int sz, rc, nread, total = 0; const int bufsz = PAGE_SIZE; char *name; char fullname[80], *buf; @@ -176,64 +172,70 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, buf = (void *)get_zeroed_page(GFP_KERNEL); if (!buf) - return; + return -ENOMEM; - dfd = ctx_info->dfd; name = spufs_coredump_read[i].name; - - if (!strcmp(name, "mem")) - sz = ctx_info->memsize; - else - sz = spufs_coredump_read[i].size; - - ctx = ctx_info->ctx; - if (!ctx) - goto out; + sz = spufs_coredump_read[i].size; sprintf(fullname, "SPU/%d/%s", dfd, name); en.n_namesz = strlen(fullname) + 1; en.n_descsz = sz; en.n_type = NT_SPU; - if (!spufs_dump_write(file, &en, sizeof(en))) + rc = spufs_dump_write(file, &en, sizeof(en), foffset); + if (rc) goto out; - if (!spufs_dump_write(file, fullname, en.n_namesz)) + + rc = spufs_dump_write(file, fullname, en.n_namesz, foffset); + if (rc) goto out; - if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) + + rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset); + if (rc) goto out; do { - rc = do_coredump_read(i, ctx, buf, bufsz, &pos); - if (rc > 0) { - if (!spufs_dump_write(file, buf, rc)) + nread = do_coredump_read(i, ctx, buf, bufsz, &pos); + if (nread > 0) { + rc = spufs_dump_write(file, buf, nread, foffset); + if (rc) goto out; - total += rc; + total += nread; } - } while (rc == bufsz && total < sz); + } while (nread == bufsz && total < sz); + + if (nread < 0) { + rc = nread; + goto out; + } + + rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4), + foffset); - spufs_dump_seek(file, roundup((unsigned long)file->f_pos - - total + sz, 4)); out: free_page((unsigned long)buf); + return rc; } -static void spufs_arch_write_notes(struct file *file) +int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset) { - int j; - struct spufs_ctx_info *ctx_info, *next; - - list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) { - spu_acquire_saved(ctx_info->ctx); - for (j = 0; j < spufs_coredump_num_notes; j++) - spufs_arch_write_note(ctx_info, j, file); - spu_release_saved(ctx_info->ctx); - list_del(&ctx_info->list); - kfree(ctx_info); + struct spu_context *ctx; + int fd, j, rc; + + fd = 0; + while ((ctx = coredump_next_context(&fd)) != NULL) { + spu_acquire_saved(ctx); + + for (j = 0; spufs_coredump_read[j].name != NULL; j++) { + rc = spufs_arch_write_note(ctx, j, file, fd, foffset); + if (rc) { + spu_release_saved(ctx); + return rc; + } + } + + spu_release_saved(ctx); } -} -struct spu_coredump_calls spufs_coredump_calls = { - .arch_notes_size = spufs_arch_notes_size, - .arch_write_notes = spufs_arch_write_notes, - .owner = THIS_MODULE, -}; + return 0; +} diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 7de4e919687..d72b16d6816 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -199,9 +199,9 @@ static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) } #ifdef CONFIG_SPU_FS_64K_LS -unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags) +static unsigned long spufs_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) { struct spu_context *ctx = file->private_data; struct spu_state *csa = &ctx->csa; @@ -1076,6 +1076,36 @@ static const struct file_operations spufs_signal2_nosched_fops = { .mmap = spufs_signal2_mmap, }; +/* + * This is a wrapper around DEFINE_SIMPLE_ATTRIBUTE which does the + * work of acquiring (or not) the SPU context before calling through + * to the actual get routine. The set routine is called directly. + */ +#define SPU_ATTR_NOACQUIRE 0 +#define SPU_ATTR_ACQUIRE 1 +#define SPU_ATTR_ACQUIRE_SAVED 2 + +#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \ +static u64 __##__get(void *data) \ +{ \ + struct spu_context *ctx = data; \ + u64 ret; \ + \ + if (__acquire == SPU_ATTR_ACQUIRE) { \ + spu_acquire(ctx); \ + ret = __get(ctx); \ + spu_release(ctx); \ + } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \ + spu_acquire_saved(ctx); \ + ret = __get(ctx); \ + spu_release_saved(ctx); \ + } else \ + ret = __get(ctx); \ + \ + return ret; \ +} \ +DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt); + static void spufs_signal1_type_set(void *data, u64 val) { struct spu_context *ctx = data; @@ -1085,25 +1115,13 @@ static void spufs_signal1_type_set(void *data, u64 val) spu_release(ctx); } -static u64 __spufs_signal1_type_get(void *data) +static u64 spufs_signal1_type_get(struct spu_context *ctx) { - struct spu_context *ctx = data; return ctx->ops->signal1_type_get(ctx); } +DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get, + spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE); -static u64 spufs_signal1_type_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret; - - spu_acquire(ctx); - ret = __spufs_signal1_type_get(data); - spu_release(ctx); - - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get, - spufs_signal1_type_set, "%llu"); static void spufs_signal2_type_set(void *data, u64 val) { @@ -1114,25 +1132,12 @@ static void spufs_signal2_type_set(void *data, u64 val) spu_release(ctx); } -static u64 __spufs_signal2_type_get(void *data) +static u64 spufs_signal2_type_get(struct spu_context *ctx) { - struct spu_context *ctx = data; return ctx->ops->signal2_type_get(ctx); } - -static u64 spufs_signal2_type_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret; - - spu_acquire(ctx); - ret = __spufs_signal2_type_get(data); - spu_release(ctx); - - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, - spufs_signal2_type_set, "%llu"); +DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, + spufs_signal2_type_set, "%llu", SPU_ATTR_ACQUIRE); #if SPUFS_MMAP_4K static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma, @@ -1608,17 +1613,12 @@ static void spufs_npc_set(void *data, u64 val) spu_release(ctx); } -static u64 spufs_npc_get(void *data) +static u64 spufs_npc_get(struct spu_context *ctx) { - struct spu_context *ctx = data; - u64 ret; - spu_acquire(ctx); - ret = ctx->ops->npc_read(ctx); - spu_release(ctx); - return ret; + return ctx->ops->npc_read(ctx); } -DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, - "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, + "0x%llx\n", SPU_ATTR_ACQUIRE); static void spufs_decr_set(void *data, u64 val) { @@ -1629,24 +1629,13 @@ static void spufs_decr_set(void *data, u64 val) spu_release_saved(ctx); } -static u64 __spufs_decr_get(void *data) +static u64 spufs_decr_get(struct spu_context *ctx) { - struct spu_context *ctx = data; struct spu_lscsa *lscsa = ctx->csa.lscsa; return lscsa->decr.slot[0]; } - -static u64 spufs_decr_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret; - spu_acquire_saved(ctx); - ret = __spufs_decr_get(data); - spu_release_saved(ctx); - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, - "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, + "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED); static void spufs_decr_status_set(void *data, u64 val) { @@ -1659,26 +1648,16 @@ static void spufs_decr_status_set(void *data, u64 val) spu_release_saved(ctx); } -static u64 __spufs_decr_status_get(void *data) +static u64 spufs_decr_status_get(struct spu_context *ctx) { - struct spu_context *ctx = data; if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING) return SPU_DECR_STATUS_RUNNING; else return 0; } - -static u64 spufs_decr_status_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret; - spu_acquire_saved(ctx); - ret = __spufs_decr_status_get(data); - spu_release_saved(ctx); - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, - spufs_decr_status_set, "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, + spufs_decr_status_set, "0x%llx\n", + SPU_ATTR_ACQUIRE_SAVED); static void spufs_event_mask_set(void *data, u64 val) { @@ -1689,28 +1668,18 @@ static void spufs_event_mask_set(void *data, u64 val) spu_release_saved(ctx); } -static u64 __spufs_event_mask_get(void *data) +static u64 spufs_event_mask_get(struct spu_context *ctx) { - struct spu_context *ctx = data; struct spu_lscsa *lscsa = ctx->csa.lscsa; return lscsa->event_mask.slot[0]; } -static u64 spufs_event_mask_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret; - spu_acquire_saved(ctx); - ret = __spufs_event_mask_get(data); - spu_release_saved(ctx); - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, - spufs_event_mask_set, "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, + spufs_event_mask_set, "0x%llx\n", + SPU_ATTR_ACQUIRE_SAVED); -static u64 __spufs_event_status_get(void *data) +static u64 spufs_event_status_get(struct spu_context *ctx) { - struct spu_context *ctx = data; struct spu_state *state = &ctx->csa; u64 stat; stat = state->spu_chnlcnt_RW[0]; @@ -1718,19 +1687,8 @@ static u64 __spufs_event_status_get(void *data) return state->spu_chnldata_RW[0]; return 0; } - -static u64 spufs_event_status_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret = 0; - - spu_acquire_saved(ctx); - ret = __spufs_event_status_get(data); - spu_release_saved(ctx); - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, - NULL, "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, + NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED) static void spufs_srr0_set(void *data, u64 val) { @@ -1741,45 +1699,32 @@ static void spufs_srr0_set(void *data, u64 val) spu_release_saved(ctx); } -static u64 spufs_srr0_get(void *data) +static u64 spufs_srr0_get(struct spu_context *ctx) { - struct spu_context *ctx = data; struct spu_lscsa *lscsa = ctx->csa.lscsa; - u64 ret; - spu_acquire_saved(ctx); - ret = lscsa->srr0.slot[0]; - spu_release_saved(ctx); - return ret; + return lscsa->srr0.slot[0]; } -DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, - "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, + "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED) -static u64 spufs_id_get(void *data) +static u64 spufs_id_get(struct spu_context *ctx) { - struct spu_context *ctx = data; u64 num; - spu_acquire(ctx); if (ctx->state == SPU_STATE_RUNNABLE) num = ctx->spu->number; else num = (unsigned int)-1; - spu_release(ctx); return num; } -DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") - -static u64 __spufs_object_id_get(void *data) -{ - struct spu_context *ctx = data; - return ctx->object_id; -} +DEFINE_SPUFS_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n", + SPU_ATTR_ACQUIRE) -static u64 spufs_object_id_get(void *data) +static u64 spufs_object_id_get(struct spu_context *ctx) { /* FIXME: Should there really be no locking here? */ - return __spufs_object_id_get(data); + return ctx->object_id; } static void spufs_object_id_set(void *data, u64 id) @@ -1788,27 +1733,15 @@ static void spufs_object_id_set(void *data, u64 id) ctx->object_id = id; } -DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, - spufs_object_id_set, "0x%llx\n"); +DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, + spufs_object_id_set, "0x%llx\n", SPU_ATTR_NOACQUIRE); -static u64 __spufs_lslr_get(void *data) +static u64 spufs_lslr_get(struct spu_context *ctx) { - struct spu_context *ctx = data; return ctx->csa.priv2.spu_lslr_RW; } - -static u64 spufs_lslr_get(void *data) -{ - struct spu_context *ctx = data; - u64 ret; - - spu_acquire_saved(ctx); - ret = __spufs_lslr_get(data); - spu_release_saved(ctx); - - return ret; -} -DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n") +DEFINE_SPUFS_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n", + SPU_ATTR_ACQUIRE_SAVED); static int spufs_info_open(struct inode *inode, struct file *file) { @@ -2231,25 +2164,25 @@ struct tree_descr spufs_dir_nosched_contents[] = { }; struct spufs_coredump_reader spufs_coredump_read[] = { - { "regs", __spufs_regs_read, NULL, 128 * 16 }, - { "fpcr", __spufs_fpcr_read, NULL, 16 }, - { "lslr", NULL, __spufs_lslr_get, 11 }, - { "decr", NULL, __spufs_decr_get, 11 }, - { "decr_status", NULL, __spufs_decr_status_get, 11 }, - { "mem", __spufs_mem_read, NULL, 256 * 1024, }, - { "signal1", __spufs_signal1_read, NULL, 4 }, - { "signal1_type", NULL, __spufs_signal1_type_get, 2 }, - { "signal2", __spufs_signal2_read, NULL, 4 }, - { "signal2_type", NULL, __spufs_signal2_type_get, 2 }, - { "event_mask", NULL, __spufs_event_mask_get, 8 }, - { "event_status", NULL, __spufs_event_status_get, 8 }, - { "mbox_info", __spufs_mbox_info_read, NULL, 4 }, - { "ibox_info", __spufs_ibox_info_read, NULL, 4 }, - { "wbox_info", __spufs_wbox_info_read, NULL, 16 }, - { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 }, - { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 }, - { "object-id", NULL, __spufs_object_id_get, 19 }, - { }, + { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])}, + { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) }, + { "lslr", NULL, spufs_lslr_get, 19 }, + { "decr", NULL, spufs_decr_get, 19 }, + { "decr_status", NULL, spufs_decr_status_get, 19 }, + { "mem", __spufs_mem_read, NULL, LS_SIZE, }, + { "signal1", __spufs_signal1_read, NULL, sizeof(u32) }, + { "signal1_type", NULL, spufs_signal1_type_get, 19 }, + { "signal2", __spufs_signal2_read, NULL, sizeof(u32) }, + { "signal2_type", NULL, spufs_signal2_type_get, 19 }, + { "event_mask", NULL, spufs_event_mask_get, 19 }, + { "event_status", NULL, spufs_event_status_get, 19 }, + { "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) }, + { "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) }, + { "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)}, + { "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)}, + { "proxydma_info", __spufs_proxydma_info_read, + NULL, sizeof(struct spu_proxydma_info)}, + { "object-id", NULL, spufs_object_id_get, 19 }, + { "npc", NULL, spufs_npc_get, 19 }, + { NULL }, }; -int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1; - diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3d0dd118dd..11098747d09 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -43,6 +43,7 @@ static struct kmem_cache *spufs_inode_cache; char *isolated_loader; +static int isolated_loader_size; static struct inode * spufs_alloc_inode(struct super_block *sb) @@ -667,7 +668,8 @@ spufs_parse_options(char *options, struct inode *root) static void spufs_exit_isolated_loader(void) { - kfree(isolated_loader); + free_pages((unsigned long) isolated_loader, + get_order(isolated_loader_size)); } static void @@ -685,11 +687,12 @@ spufs_init_isolated_loader(void) if (!loader) return; - /* kmalloc should align on a 16 byte boundary..* */ - isolated_loader = kmalloc(size, GFP_KERNEL); + /* the loader must be align on a 16 byte boundary */ + isolated_loader = (char *)__get_free_pages(GFP_KERNEL, get_order(size)); if (!isolated_loader) return; + isolated_loader_size = size; memcpy(isolated_loader, loader, size); printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); } @@ -787,16 +790,11 @@ static int __init spufs_init(void) ret = register_spu_syscalls(&spufs_calls); if (ret) goto out_fs; - ret = register_arch_coredump_calls(&spufs_coredump_calls); - if (ret) - goto out_syscalls; spufs_init_isolated_loader(); return 0; -out_syscalls: - unregister_spu_syscalls(&spufs_calls); out_fs: unregister_filesystem(&spufs_type); out_sched: @@ -812,7 +810,6 @@ static void __exit spufs_exit(void) { spu_sched_exit(); spufs_exit_isolated_loader(); - unregister_arch_coredump_calls(&spufs_coredump_calls); unregister_spu_syscalls(&spufs_calls); unregister_filesystem(&spufs_type); kmem_cache_destroy(spufs_inode_cache); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 958f10e90fd..1ce5e22ea5f 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -205,7 +205,7 @@ static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, * This means we can only do a very rough approximation of POSIX * signal semantics. */ -int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, +static int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, unsigned int *npc) { int ret; @@ -241,7 +241,7 @@ int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, return ret; } -int spu_process_callback(struct spu_context *ctx) +static int spu_process_callback(struct spu_context *ctx) { struct spu_syscall_block s; u32 ls_pointer, npc; diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 5bebe7fbe05..4d257b3f933 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -230,8 +230,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) if (ctx->flags & SPU_CREATE_NOSCHED) atomic_inc(&cbe_spu_info[spu->node].reserved_spus); - if (!list_empty(&ctx->aff_list)) - atomic_inc(&ctx->gang->aff_sched_count); ctx->stats.slb_flt_base = spu->stats.slb_flt; ctx->stats.class2_intr_base = spu->stats.class2_intr; @@ -392,7 +390,6 @@ static int has_affinity(struct spu_context *ctx) if (list_empty(&ctx->aff_list)) return 0; - mutex_lock(&gang->aff_mutex); if (!gang->aff_ref_spu) { if (!(gang->aff_flags & AFF_MERGED)) aff_merge_remaining_ctxs(gang); @@ -400,7 +397,6 @@ static int has_affinity(struct spu_context *ctx) aff_set_offsets(gang); aff_set_ref_point_location(gang); } - mutex_unlock(&gang->aff_mutex); return gang->aff_ref_spu != NULL; } @@ -418,9 +414,16 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) if (spu->ctx->flags & SPU_CREATE_NOSCHED) atomic_dec(&cbe_spu_info[spu->node].reserved_spus); - if (!list_empty(&ctx->aff_list)) - if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) - ctx->gang->aff_ref_spu = NULL; + + if (ctx->gang){ + mutex_lock(&ctx->gang->aff_mutex); + if (has_affinity(ctx)) { + if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) + ctx->gang->aff_ref_spu = NULL; + } + mutex_unlock(&ctx->gang->aff_mutex); + } + spu_switch_notify(spu, NULL); spu_unmap_mappings(ctx); spu_save(&ctx->csa, spu); @@ -511,20 +514,32 @@ static void spu_prio_wait(struct spu_context *ctx) static struct spu *spu_get_idle(struct spu_context *ctx) { - struct spu *spu; + struct spu *spu, *aff_ref_spu; int node, n; - if (has_affinity(ctx)) { - node = ctx->gang->aff_ref_spu->node; + if (ctx->gang) { + mutex_lock(&ctx->gang->aff_mutex); + if (has_affinity(ctx)) { + aff_ref_spu = ctx->gang->aff_ref_spu; + atomic_inc(&ctx->gang->aff_sched_count); + mutex_unlock(&ctx->gang->aff_mutex); + node = aff_ref_spu->node; - mutex_lock(&cbe_spu_info[node].list_mutex); - spu = ctx_location(ctx->gang->aff_ref_spu, ctx->aff_offset, node); - if (spu && spu->alloc_state == SPU_FREE) - goto found; - mutex_unlock(&cbe_spu_info[node].list_mutex); - return NULL; - } + mutex_lock(&cbe_spu_info[node].list_mutex); + spu = ctx_location(aff_ref_spu, ctx->aff_offset, node); + if (spu && spu->alloc_state == SPU_FREE) + goto found; + mutex_unlock(&cbe_spu_info[node].list_mutex); + mutex_lock(&ctx->gang->aff_mutex); + if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) + ctx->gang->aff_ref_spu = NULL; + mutex_unlock(&ctx->gang->aff_mutex); + + return NULL; + } + mutex_unlock(&ctx->gang->aff_mutex); + } node = cpu_to_node(raw_smp_processor_id()); for (n = 0; n < MAX_NUMNODES; n++, node++) { node = (node < MAX_NUMNODES) ? node : 0; diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 2bfdeb8ea8b..ca47b991bda 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -200,9 +200,14 @@ extern struct tree_descr spufs_dir_contents[]; extern struct tree_descr spufs_dir_nosched_contents[]; /* system call implementation */ +extern struct spufs_calls spufs_calls; long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, struct file *filp); +/* ELF coredump callbacks for writing SPU ELF notes */ +extern int spufs_coredump_extra_notes_size(void); +extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset); + extern const struct file_operations spufs_context_fops; /* gang management */ @@ -295,7 +300,7 @@ struct spufs_coredump_reader { char *name; ssize_t (*read)(struct spu_context *ctx, char __user *buffer, size_t size, loff_t *pos); - u64 (*get)(void *data); + u64 (*get)(struct spu_context *ctx); size_t size; }; extern struct spufs_coredump_reader spufs_coredump_read[]; diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 27ffdae98e5..3d64c81cc6e 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -699,7 +699,7 @@ static inline void get_kernel_slb(u64 ea, u64 slb[2]) llp = mmu_psize_defs[mmu_linear_psize].sllp; else llp = mmu_psize_defs[mmu_virtual_psize].sllp; - slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL | llp; slb[1] = (ea & ESID_MASK) | SLB_ESID_V; } @@ -1559,15 +1559,15 @@ static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu) * "wrapped" flag is set, OR in a '1' to * CSA.SPU_Event_Status[Tm]. */ - if (csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED) { - csa->spu_chnldata_RW[0] |= 0x20; - } - if ((csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED) && - (csa->spu_chnlcnt_RW[0] == 0 && - ((csa->spu_chnldata_RW[2] & 0x20) == 0x0) && - ((csa->spu_chnldata_RW[0] & 0x20) != 0x1))) { + if (!(csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED)) + return; + + if ((csa->spu_chnlcnt_RW[0] == 0) && + (csa->spu_chnldata_RW[1] & 0x20) && + !(csa->spu_chnldata_RW[0] & 0x20)) csa->spu_chnlcnt_RW[0] = 1; - } + + csa->spu_chnldata_RW[0] |= 0x20; } static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu) @@ -2146,19 +2146,6 @@ int spu_restore(struct spu_state *new, struct spu *spu) } EXPORT_SYMBOL_GPL(spu_restore); -/** - * spu_harvest - SPU harvest (reset) operation - * @spu: pointer to SPU iomem structure. - * - * Perform SPU harvest (reset) operation. - */ -void spu_harvest(struct spu *spu) -{ - acquire_spu_lock(spu); - harvest(NULL, spu); - release_spu_lock(spu); -} - static void init_prob(struct spu_state *csa) { csa->spu_chnlcnt_RW[9] = 1; diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index 43f0fb88abb..2c34f717019 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -58,26 +58,8 @@ out: return ret; } -#ifndef MODULE -asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) -{ - int fput_needed; - struct file *filp; - long ret; - - ret = -EBADF; - filp = fget_light(fd, &fput_needed); - if (filp) { - ret = do_spu_run(filp, unpc, ustatus); - fput_light(filp, fput_needed); - } - - return ret; -} -#endif - -asmlinkage long do_spu_create(const char __user *pathname, unsigned int flags, - mode_t mode, struct file *neighbor) +static long do_spu_create(const char __user *pathname, unsigned int flags, + mode_t mode, struct file *neighbor) { char *tmp; int ret; @@ -99,32 +81,10 @@ asmlinkage long do_spu_create(const char __user *pathname, unsigned int flags, return ret; } -#ifndef MODULE -asmlinkage long sys_spu_create(const char __user *pathname, unsigned int flags, - mode_t mode, int neighbor_fd) -{ - int fput_needed; - struct file *neighbor; - long ret; - - if (flags & SPU_CREATE_AFFINITY_SPU) { - ret = -EBADF; - neighbor = fget_light(neighbor_fd, &fput_needed); - if (neighbor) { - ret = do_spu_create(pathname, flags, mode, neighbor); - fput_light(neighbor, fput_needed); - } - } - else { - ret = do_spu_create(pathname, flags, mode, NULL); - } - - return ret; -} -#endif - struct spufs_calls spufs_calls = { .create_thread = do_spu_create, .spu_run = do_spu_run, + .coredump_extra_notes_size = spufs_coredump_extra_notes_size, + .coredump_extra_notes_write = spufs_coredump_extra_notes_write, .owner = THIS_MODULE, }; |