diff options
| -rw-r--r-- | drivers/ps3/ps3stor_lib.c | 65 |
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 | |||
| 32 | static 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 | |||
| 38 | static 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 | |||
| 54 | static 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 | ||
| 27 | static int ps3stor_probe_access(struct ps3_storage_device *dev) | 86 | static 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: | |||
| 166 | fail_sb_event_receive_port_destroy: | 225 | fail_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); |
| 168 | fail_close_device: | 227 | fail_close_device: |
| 169 | ps3_close_hv_device(&dev->sbd); | 228 | ps3stor_close_hv_device(&dev->sbd); |
| 170 | fail: | 229 | fail: |
| 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__, |
