aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ps3
diff options
context:
space:
mode:
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__,