Skip to content

Commit

Permalink
ps3: Replace direct file operations by callback
Browse files Browse the repository at this point in the history
Currently the FLASH database is updated by the kernel using file operations,
meant for userspace only. While this works for us because copy_{from,to}_user()
on powerpc can handle kernel pointers, this is unportable and a bad example.
Replace the file operations by callbacks, registered by the ps3flash driver.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Cc: Geoff Levand <geoffrey.levand@am.sony.com>
Acked-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Geert Uytterhoeven authored and Benjamin Herrenschmidt committed Jun 15, 2009
1 parent 47cb996 commit a4e623f
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 87 deletions.
7 changes: 7 additions & 0 deletions arch/powerpc/include/asm/ps3.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void);
extern u64 ps3_os_area_get_rtc_diff(void);
extern void ps3_os_area_set_rtc_diff(u64 rtc_diff);

struct ps3_os_area_flash_ops {
ssize_t (*read)(void *buf, size_t count, loff_t pos);
ssize_t (*write)(const void *buf, size_t count, loff_t pos);
};

extern void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops);

/* dma routines */

enum ps3_dma_page_size {
Expand Down
138 changes: 75 additions & 63 deletions arch/powerpc/platforms/ps3/os-area.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,44 @@ static struct property property_av_multi_out = {
.value = &saved_params.av_multi_out,
};


static DEFINE_MUTEX(os_area_flash_mutex);

static const struct ps3_os_area_flash_ops *os_area_flash_ops;

void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops)
{
mutex_lock(&os_area_flash_mutex);
os_area_flash_ops = ops;
mutex_unlock(&os_area_flash_mutex);
}
EXPORT_SYMBOL_GPL(ps3_os_area_flash_register);

static ssize_t os_area_flash_read(void *buf, size_t count, loff_t pos)
{
ssize_t res = -ENODEV;

mutex_lock(&os_area_flash_mutex);
if (os_area_flash_ops)
res = os_area_flash_ops->read(buf, count, pos);
mutex_unlock(&os_area_flash_mutex);

return res;
}

static ssize_t os_area_flash_write(const void *buf, size_t count, loff_t pos)
{
ssize_t res = -ENODEV;

mutex_lock(&os_area_flash_mutex);
if (os_area_flash_ops)
res = os_area_flash_ops->write(buf, count, pos);
mutex_unlock(&os_area_flash_mutex);

return res;
}


/**
* os_area_set_property - Add or overwrite a saved_params value to the device tree.
*
Expand Down Expand Up @@ -352,12 +390,12 @@ static int db_verify(const struct os_area_db *db)
if (memcmp(db->magic_num, OS_AREA_DB_MAGIC_NUM,
sizeof(db->magic_num))) {
pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
return -1;
return -EINVAL;
}

if (db->version != 1) {
pr_debug("%s:%d version failed\n", __func__, __LINE__);
return -1;
return -EINVAL;
}

return 0;
Expand Down Expand Up @@ -578,59 +616,48 @@ static void os_area_db_init(struct os_area_db *db)
*
*/

static void __maybe_unused update_flash_db(void)
static int update_flash_db(void)
{
int result;
int file;
off_t offset;
const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
struct os_area_header *header;
ssize_t count;
static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
const struct os_area_header *header;
int error;
loff_t pos;
struct os_area_db* db;

/* Read in header and db from flash. */

file = sys_open("/dev/ps3flash", O_RDWR, 0);

if (file < 0) {
pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
goto fail_open;
}

header = kmalloc(buf_len, GFP_KERNEL);

if (!header) {
pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
goto fail_malloc;
pr_debug("%s: kmalloc failed\n", __func__);
return -ENOMEM;
}

offset = sys_lseek(file, 0, SEEK_SET);

if (offset != 0) {
pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
goto fail_header_seek;
count = os_area_flash_read(header, buf_len, 0);
if (count < 0) {
pr_debug("%s: os_area_flash_read failed %zd\n", __func__,
count);
error = count;
goto fail;
}

count = sys_read(file, (char __user *)header, buf_len);

result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
|| count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;

if (result) {
pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
pos = header->db_area_offset * OS_AREA_SEGMENT_SIZE;
if (count < OS_AREA_SEGMENT_SIZE || verify_header(header) ||
count < pos) {
pr_debug("%s: verify_header failed\n", __func__);
dump_header(header);
goto fail_header;
error = -EINVAL;
goto fail;
}

/* Now got a good db offset and some maybe good db data. */

db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
db = (void *)header + pos;

result = db_verify(db);

if (result) {
printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
"formatting.\n", __func__, __LINE__);
error = db_verify(db);
if (error) {
pr_notice("%s: Verify of flash database failed, formatting.\n",
__func__);
dump_db(db);
os_area_db_init(db);
}
Expand All @@ -639,29 +666,16 @@ static void __maybe_unused update_flash_db(void)

db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);

offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
SEEK_SET);

if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
goto fail_db_seek;
}

count = sys_write(file, (const char __user *)db,
sizeof(struct os_area_db));

count = os_area_flash_write(db, sizeof(struct os_area_db), pos);
if (count < sizeof(struct os_area_db)) {
pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
pr_debug("%s: os_area_flash_write failed %zd\n", __func__,
count);
error = count < 0 ? count : -EIO;
}

fail_db_seek:
fail_header:
fail_header_seek:
fail:
kfree(header);
fail_malloc:
sys_close(file);
fail_open:
return;
return error;
}

/**
Expand All @@ -674,24 +688,22 @@ static void __maybe_unused update_flash_db(void)
static void os_area_queue_work_handler(struct work_struct *work)
{
struct device_node *node;
int error;

pr_debug(" -> %s:%d\n", __func__, __LINE__);

node = of_find_node_by_path("/");

if (node) {
os_area_set_property(node, &property_rtc_diff);
of_node_put(node);
} else
pr_debug("%s:%d of_find_node_by_path failed\n",
__func__, __LINE__);

#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
update_flash_db();
#else
printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
__func__, __LINE__);
#endif
error = update_flash_db();
if (error)
pr_warning("%s: Could not update FLASH ROM\n", __func__);

pr_debug(" <- %s:%d\n", __func__, __LINE__);
}

Expand Down
Loading

0 comments on commit a4e623f

Please sign in to comment.