aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ps3
diff options
context:
space:
mode:
authorGeoff Levand <geoffrey.levand@am.sony.com>2009-09-09 09:28:05 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-09-10 21:28:00 -0400
commitbc00351edd5c1b84d48c3fdca740fedfce4ae6ce (patch)
treeb6e85ec226b7a7e94fac1699b9cf64a4c721c117 /drivers/ps3
parentc6c9eacef09a94b5866b83556196440aca876702 (diff)
powerpc/ps3: Workaround for flash memory I/O error
A workaround for flash memory I/O errors when the PS3 internal hard disk has not been formatted for OtherOS use. This error condition mainly effects 'Live CD' users who have not formatted the PS3's internal hard disk for OtherOS. Fixes errors similar to these when using the ps3-flash-util or ps3-boot-game-os programs: ps3flash read failed 0x2050000 os_area_header_read: read error: os_area_header: Input/output error main:627: os_area_read_hp error. ERROR: can't change boot flag Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/ps3')
-rw-r--r--drivers/ps3/ps3stor_lib.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
index 18066d555397..af0afa1db4a8 100644
--- a/drivers/ps3/ps3stor_lib.c
+++ b/drivers/ps3/ps3stor_lib.c
@@ -23,6 +23,65 @@
23#include <asm/lv1call.h> 23#include <asm/lv1call.h>
24#include <asm/ps3stor.h> 24#include <asm/ps3stor.h>
25 25
26/*
27 * A workaround for flash memory I/O errors when the internal hard disk
28 * has not been formatted for OtherOS use. Delay disk close until flash
29 * memory is closed.
30 */
31
32static struct ps3_flash_workaround {
33 int flash_open;
34 int disk_open;
35 struct ps3_system_bus_device *disk_sbd;
36} ps3_flash_workaround;
37
38static int ps3stor_open_hv_device(struct ps3_system_bus_device *sbd)
39{
40 int error = ps3_open_hv_device(sbd);
41
42 if (error)
43 return error;
44
45 if (sbd->match_id == PS3_MATCH_ID_STOR_FLASH)
46 ps3_flash_workaround.flash_open = 1;
47
48 if (sbd->match_id == PS3_MATCH_ID_STOR_DISK)
49 ps3_flash_workaround.disk_open = 1;
50
51 return 0;
52}
53
54static int ps3stor_close_hv_device(struct ps3_system_bus_device *sbd)
55{
56 int error;
57
58 if (sbd->match_id == PS3_MATCH_ID_STOR_DISK
59 && ps3_flash_workaround.disk_open
60 && ps3_flash_workaround.flash_open) {
61 ps3_flash_workaround.disk_sbd = sbd;
62 return 0;
63 }
64
65 error = ps3_close_hv_device(sbd);
66
67 if (error)
68 return error;
69
70 if (sbd->match_id == PS3_MATCH_ID_STOR_DISK)
71 ps3_flash_workaround.disk_open = 0;
72
73 if (sbd->match_id == PS3_MATCH_ID_STOR_FLASH) {
74 ps3_flash_workaround.flash_open = 0;
75
76 if (ps3_flash_workaround.disk_sbd) {
77 ps3_close_hv_device(ps3_flash_workaround.disk_sbd);
78 ps3_flash_workaround.disk_open = 0;
79 ps3_flash_workaround.disk_sbd = NULL;
80 }
81 }
82
83 return 0;
84}
26 85
27static int ps3stor_probe_access(struct ps3_storage_device *dev) 86static int ps3stor_probe_access(struct ps3_storage_device *dev)
28{ 87{
@@ -90,7 +149,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
90 int error, res, alignment; 149 int error, res, alignment;
91 enum ps3_dma_page_size page_size; 150 enum ps3_dma_page_size page_size;
92 151
93 error = ps3_open_hv_device(&dev->sbd); 152 error = ps3stor_open_hv_device(&dev->sbd);
94 if (error) { 153 if (error) {
95 dev_err(&dev->sbd.core, 154 dev_err(&dev->sbd.core,
96 "%s:%u: ps3_open_hv_device failed %d\n", __func__, 155 "%s:%u: ps3_open_hv_device failed %d\n", __func__,
@@ -166,7 +225,7 @@ fail_free_irq:
166fail_sb_event_receive_port_destroy: 225fail_sb_event_receive_port_destroy:
167 ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq); 226 ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
168fail_close_device: 227fail_close_device:
169 ps3_close_hv_device(&dev->sbd); 228 ps3stor_close_hv_device(&dev->sbd);
170fail: 229fail:
171 return error; 230 return error;
172} 231}
@@ -193,7 +252,7 @@ void ps3stor_teardown(struct ps3_storage_device *dev)
193 "%s:%u: destroy event receive port failed %d\n", 252 "%s:%u: destroy event receive port failed %d\n",
194 __func__, __LINE__, error); 253 __func__, __LINE__, error);
195 254
196 error = ps3_close_hv_device(&dev->sbd); 255 error = ps3stor_close_hv_device(&dev->sbd);
197 if (error) 256 if (error)
198 dev_err(&dev->sbd.core, 257 dev_err(&dev->sbd.core,
199 "%s:%u: ps3_close_hv_device failed %d\n", __func__, 258 "%s:%u: ps3_close_hv_device failed %d\n", __func__,