diff options
Diffstat (limited to 'arch/powerpc/platforms')
| -rw-r--r-- | arch/powerpc/platforms/44x/Kconfig | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/Kconfig.cputype | 43 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powermac/low_i2c.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/Kconfig | 22 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/mm.c | 77 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/platform.h | 16 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/repository.c | 198 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/Kconfig | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/plpar_wrappers.h | 4 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 7 | 
11 files changed, 316 insertions, 58 deletions
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 2e4e64abfab..8abf6fb8f41 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -23,6 +23,8 @@ config BLUESTONE  	default n  	select PPC44x_SIMPLE  	select APM821xx +	select PCI_MSI +	select PPC4xx_MSI  	select PPC4xx_PCI_EXPRESS  	select IBM_EMAC_RGMII  	help diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 425db18580a..61c9550819a 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -78,6 +78,36 @@ config PPC_BOOK3E_64  endchoice +choice +	prompt "CPU selection" +	depends on PPC64 +	default GENERIC_CPU +	help +	  This will create a kernel which is optimised for a particular CPU. +	  The resulting kernel may not run on other CPUs, so use this with care. + +	  If unsure, select Generic. + +config GENERIC_CPU +	bool "Generic" + +config CELL_CPU +	bool "Cell Broadband Engine" + +config POWER4_CPU +	bool "POWER4" + +config POWER5_CPU +	bool "POWER5" + +config POWER6_CPU +	bool "POWER6" + +config POWER7_CPU +	bool "POWER7" + +endchoice +  config PPC_BOOK3S  	def_bool y  	depends on PPC_BOOK3S_32 || PPC_BOOK3S_64 @@ -86,15 +116,6 @@ config PPC_BOOK3E  	def_bool y  	depends on PPC_BOOK3E_64 -config POWER4_ONLY -	bool "Optimize for POWER4" -	depends on PPC64 && PPC_BOOK3S -	default n -	---help--- -	  Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. -	  The resulting binary will not work on POWER3 or RS64 processors -	  when compiled with binutils 2.15 or later. -  config 6xx  	def_bool y  	depends on PPC32 && PPC_BOOK3S @@ -258,7 +279,7 @@ config PPC_ICSWX_PID  	default y  	---help---  	  The PID register in server is used explicitly for ICSWX.  In -	  embedded systems PID managment is done by the system. +	  embedded systems PID management is done by the system.  config PPC_ICSWX_USE_SIGILL  	bool "Should a bad CT cause a SIGILL?" @@ -266,7 +287,7 @@ config PPC_ICSWX_USE_SIGILL  	default n  	---help---  	  Should a bad CT used for "non-record form ICSWX" cause an -	  illegal intruction signal or should it be silent as +	  illegal instruction signal or should it be silent as  	  architected.  	  If in doubt, say N here. diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 03685a329d7..fc536f2971c 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -1503,6 +1503,7 @@ static int __init pmac_i2c_create_platform_devices(void)  		if (bus->platform_dev == NULL)  			return -ENOMEM;  		bus->platform_dev->dev.platform_data = bus; +		bus->platform_dev->dev.of_node = bus->busnode;  		platform_device_add(bus->platform_dev);  	} diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 476d9d9b240..46b7f023252 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -7,7 +7,6 @@ config PPC_PS3  	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 @@ -74,7 +73,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 +84,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 +134,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 @@ -156,7 +168,7 @@ config PS3GELIC_UDBG  	  via the Ethernet port (UDP port number 18194).  	  This driver uses a trivial implementation and is independent -	  from the main network driver. +	  from the main PS3 gelic network driver.  	  If in doubt, say N here. diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index de2aea42170..0c9f643d9e2 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -20,7 +20,6 @@  #include <linux/kernel.h>  #include <linux/export.h> -#include <linux/memory_hotplug.h>  #include <linux/memblock.h>  #include <linux/slab.h> @@ -79,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;  };  /** @@ -96,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 @@ -222,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 @@ -262,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; @@ -279,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); @@ -288,50 +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); +	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/platform.h b/arch/powerpc/platforms/ps3/platform.h index 1a633ed0fe9..d71329a8e32 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h @@ -188,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 7bdfea336f5..9b47ba7a5de 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c @@ -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.   */ @@ -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) diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 178a5f300bc..837cf49357e 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -67,7 +67,7 @@ config IO_EVENT_IRQ  	  This option will only enable the IO event platform code. You  	  will still need to enable or compile the actual drivers -	  that use this infrastruture to handle IO event interrupts. +	  that use this infrastructure to handle IO event interrupts.  	  Say Y if you are unsure. diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index a75e37dc41a..ecd394cf34e 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -489,7 +489,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)  	 * a stack trace will help the device-driver authors figure  	 * out what happened.  So print that out.  	 */ -	dump_stack(); +	WARN(1, "EEH: failure detected\n");  	return 1;  dn_unlock: diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 342797fc0f9..13e8cc43adf 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -22,12 +22,12 @@ static inline long poll_pending(void)  static inline u8 get_cede_latency_hint(void)  { -	return get_lppaca()->gpr5_dword.fields.cede_latency_hint; +	return get_lppaca()->cede_latency_hint;  }  static inline void set_cede_latency_hint(u8 latency_hint)  { -	get_lppaca()->gpr5_dword.fields.cede_latency_hint = latency_hint; +	get_lppaca()->cede_latency_hint = latency_hint;  }  static inline long cede_processor(void) diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 168651acdd8..7b3bf76ef83 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -103,11 +103,13 @@ int pSeries_reconfig_notifier_register(struct notifier_block *nb)  {  	return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);  } +EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);  void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)  {  	blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);  } +EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);  int pSeries_reconfig_notify(unsigned long action, void *p)  { @@ -426,6 +428,7 @@ static int do_remove_property(char *buf, size_t bufsize)  static int do_update_property(char *buf, size_t bufsize)  {  	struct device_node *np; +	struct pSeries_reconfig_prop_update upd_value;  	unsigned char *value;  	char *name, *end, *next_prop;  	int rc, length; @@ -454,6 +457,10 @@ static int do_update_property(char *buf, size_t bufsize)  		return -ENODEV;  	} +	upd_value.node = np; +	upd_value.property = newprop; +	pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value); +  	rc = prom_update_property(np, newprop, oldprop);  	if (rc)  		return rc;  |