Commit edd2a9d1 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Paul Mackerras

[POWERPC] PS3: Fix storage probe logic

Fix the PS3 storage probe logic to properly find device regions on cold
startup.

 o Change the storage probe event mask from notify_device_ready
   to notify_region_update.
 o Improve the storage probe error handling.
 o Change ps3_storage_wait_for_device() to use a temporary variable to hold
   the buffer address.
Signed-off-by: default avatarGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: default avatarGeoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent f5996449
...@@ -273,55 +273,58 @@ static int ps3stor_wait_for_completion(u64 dev_id, u64 tag, ...@@ -273,55 +273,58 @@ static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
{ {
int error = -ENODEV;
int result; int result;
const u64 notification_dev_id = (u64)-1LL; const u64 notification_dev_id = (u64)-1LL;
const unsigned int timeout = HZ; const unsigned int timeout = HZ;
u64 lpar; u64 lpar;
u64 tag; u64 tag;
void *buf;
enum ps3_notify_type {
notify_device_ready = 0,
notify_region_probe = 1,
notify_region_update = 2,
};
struct { struct {
u64 operation_code; /* must be zero */ u64 operation_code; /* must be zero */
u64 event_mask; /* 1 = device ready */ u64 event_mask; /* OR of 1UL << enum ps3_notify_type */
} *notify_cmd; } *notify_cmd;
struct { struct {
u64 event_type; /* notify_device_ready */ u64 event_type; /* enum ps3_notify_type */
u64 bus_id; u64 bus_id;
u64 dev_id; u64 dev_id;
u64 dev_type; u64 dev_type;
u64 dev_port; u64 dev_port;
} *notify_event; } *notify_event;
enum {
notify_device_ready = 1
};
pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__, pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__,
__LINE__, repo->bus_id, repo->dev_id, repo->dev_type); __LINE__, repo->bus_id, repo->dev_id, repo->dev_type);
notify_cmd = kzalloc(512, GFP_KERNEL); buf = kzalloc(512, GFP_KERNEL);
notify_event = (void *)notify_cmd; if (!buf)
if (!notify_cmd)
return -ENOMEM; return -ENOMEM;
lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd)); lpar = ps3_mm_phys_to_lpar(__pa(buf));
notify_cmd = buf;
notify_event = buf;
result = lv1_open_device(repo->bus_id, notification_dev_id, 0); result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
if (result) { if (result) {
printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
__LINE__, ps3_result(result)); __LINE__, ps3_result(result));
result = -ENODEV;
goto fail_free; goto fail_free;
} }
/* Setup and write the request for device notification. */ /* Setup and write the request for device notification. */
notify_cmd->operation_code = 0; /* must be zero */ notify_cmd->operation_code = 0; /* must be zero */
notify_cmd->event_mask = 0x01; /* device ready */ notify_cmd->event_mask = 1UL << notify_region_probe;
result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
&tag); &tag);
if (result) { if (result) {
printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
ps3_result(result)); ps3_result(result));
result = -ENODEV;
goto fail_close; goto fail_close;
} }
...@@ -332,13 +335,11 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) ...@@ -332,13 +335,11 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
if (result) { if (result) {
printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
__LINE__, ps3_result(result)); __LINE__, ps3_result(result));
result = -ENODEV;
goto fail_close; goto fail_close;
} }
/* Loop here processing the requested notification events. */ /* Loop here processing the requested notification events. */
result = -ENODEV;
while (1) { while (1) {
memset(notify_event, 0, sizeof(*notify_event)); memset(notify_event, 0, sizeof(*notify_event));
...@@ -358,7 +359,7 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) ...@@ -358,7 +359,7 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
break; break;
} }
if (notify_event->event_type != notify_device_ready || if (notify_event->event_type != notify_region_probe ||
notify_event->bus_id != repo->bus_id) { notify_event->bus_id != repo->bus_id) {
pr_debug("%s:%u: bad notify_event: event %lu, " pr_debug("%s:%u: bad notify_event: event %lu, "
"dev_id %lu, dev_type %lu\n", "dev_id %lu, dev_type %lu\n",
...@@ -386,9 +387,9 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) ...@@ -386,9 +387,9 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
fail_close: fail_close:
lv1_close_device(repo->bus_id, notification_dev_id); lv1_close_device(repo->bus_id, notification_dev_id);
fail_free: fail_free:
kfree(notify_cmd); kfree(buf);
pr_debug(" <- %s:%u\n", __func__, __LINE__); pr_debug(" <- %s:%u\n", __func__, __LINE__);
return result; return error;
} }
static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment