Merge remote-tracking branch 'geoff/for-powerpc' into next

This commit is contained in:
Benjamin Herrenschmidt 2012-04-30 14:49:17 +10:00
commit 76ef6a25ce
7 changed files with 285 additions and 70 deletions

View file

@ -6,7 +6,6 @@ CONFIG_NR_CPUS=2
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_SPARSE_IRQ=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
@ -25,7 +24,6 @@ CONFIG_PS3_DISK=y
CONFIG_PS3_ROM=y
CONFIG_PS3_FLASH=y
CONFIG_PS3_VRAM=m
CONFIG_PS3_LPM=m
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
CONFIG_HIGH_RES_TIMERS=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@ -53,8 +51,6 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_DIAG is not set
CONFIG_IPV6=y
CONFIG_BT=m
CONFIG_BT_L2CAP=y
CONFIG_BT_SCO=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
@ -63,7 +59,6 @@ CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_HCIBTUSB=m
CONFIG_CFG80211=m
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_MAC80211=m
CONFIG_MAC80211_RC_PID=y
# CONFIG_MAC80211_RC_MINSTREL is not set
@ -181,7 +176,6 @@ CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_FTRACE is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_CRYPTO_CCM=m

View file

@ -265,8 +265,8 @@ LV1_CALL(get_spe_irq_outlet, 2, 1, 78 )
LV1_CALL(set_spe_privilege_state_area_1_register, 3, 0, 79 )
LV1_CALL(create_repository_node, 6, 0, 90 )
LV1_CALL(read_repository_node, 5, 2, 91 )
LV1_CALL(modify_repository_node_value, 6, 0, 92 )
LV1_CALL(remove_repository_node, 4, 0, 93 )
LV1_CALL(write_repository_node, 6, 0, 92 )
LV1_CALL(delete_repository_node, 4, 0, 93 )
LV1_CALL(read_htab_entries, 2, 5, 95 )
LV1_CALL(set_dabr, 2, 0, 96 )
LV1_CALL(get_total_execution_time, 2, 1, 103 )

View file

@ -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.

View file

@ -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,49 +293,35 @@ 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;
/* Assume a single highmem region. */
BUG_ON(!mem_init_done);
start_addr = map.rm.size;
start_pfn = start_addr >> PAGE_SHIFT;
nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
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) {
pr_err("%s:%d: add_memory failed: (%d)\n",
__func__, __LINE__, result);
return result;
}
memblock_add(start_addr, map.r1.size);
result = online_pages(start_pfn, nr_pages);
result = ps3_repository_read_highmem_info(0, &r->base, &r->size);
if (result)
pr_err("%s:%d: online_pages failed: (%d)\n",
__func__, __LINE__, result);
goto zero_region;
return result;
if (!r->base || !r->size) {
result = -1;
goto zero_region;
}
device_initcall(ps3_mm_add_memory);
r->offset = r->base - map.rm.size;
DBG("%s:%d: Found high region in repository: %llxh %llxh\n",
__func__, __LINE__, r->base, r->size);
return 0;
zero_region:
DBG("%s:%d: No high region in repository.\n", __func__, __LINE__);
r->size = r->base = r->offset = 0;
return result;
}
/*============================================================================*/
/* 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 */
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__);
}

View file

@ -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 */

View file

@ -778,6 +778,72 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
: ps3_repository_read_region_total(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)

View file

@ -477,7 +477,6 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
return 0;
}
EXPORT_SYMBOL_GPL(ps3av_set_audio_mode);
static int ps3av_set_videomode(void)
@ -667,7 +666,8 @@ static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info)
return id;
}
static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
static void ps3av_monitor_info_dump(
const struct ps3av_pkt_av_get_monitor_info *monitor_info)
{
const struct ps3av_info_monitor *info = &monitor_info->info;
const struct ps3av_info_audio *audio = info->audio;
@ -717,8 +717,8 @@ static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *
/* audio block */
for (i = 0; i < info->num_of_audio_block; i++) {
pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: "
"%02x\n",
pr_debug(
"audio[%d] type: %02x max_ch: %02x fs: %02x sbit: %02x\n",
i, audio->type, audio->max_num_of_ch, audio->fs,
audio->sbit);
audio++;
@ -870,21 +870,18 @@ int ps3av_set_video_mode(int id)
return 0;
}
EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
int ps3av_get_auto_mode(void)
{
return ps3av_auto_videomode(&ps3av->av_hw_conf);
}
EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
int ps3av_get_mode(void)
{
return ps3av ? ps3av->ps3av_mode : 0;
}
EXPORT_SYMBOL_GPL(ps3av_get_mode);
/* get resolution by video_mode */
@ -902,7 +899,6 @@ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
*yres = video_mode_table[id].y;
return 0;
}
EXPORT_SYMBOL_GPL(ps3av_video_mode2res);
/* mute */
@ -911,7 +907,6 @@ int ps3av_video_mute(int mute)
return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
: PS3AV_CMD_MUTE_OFF);
}
EXPORT_SYMBOL_GPL(ps3av_video_mute);
/* mute analog output only */
@ -935,7 +930,6 @@ int ps3av_audio_mute(int mute)
return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
: PS3AV_CMD_MUTE_OFF);
}
EXPORT_SYMBOL_GPL(ps3av_audio_mute);
static int __devinit ps3av_probe(struct ps3_system_bus_device *dev)