Commit bc00351edd5c1b84d48c3fdca740fedfce4ae6ce

Authored by Geoff Levand
Committed by Benjamin Herrenschmidt
1 parent c6c9eacef0

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>

Showing 1 changed file with 62 additions and 3 deletions Side-by-side Diff

drivers/ps3/ps3stor_lib.c
... ... @@ -23,7 +23,66 @@
23 23 #include <asm/lv1call.h>
24 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 + */
26 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 +}
  85 +
27 86 static int ps3stor_probe_access(struct ps3_storage_device *dev)
28 87 {
29 88 int res, error;
... ... @@ -90,7 +149,7 @@
90 149 int error, res, alignment;
91 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 153 if (error) {
95 154 dev_err(&dev->sbd.core,
96 155 "%s:%u: ps3_open_hv_device failed %d\n", __func__,
... ... @@ -166,7 +225,7 @@
166 225 fail_sb_event_receive_port_destroy:
167 226 ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
168 227 fail_close_device:
169   - ps3_close_hv_device(&dev->sbd);
  228 + ps3stor_close_hv_device(&dev->sbd);
170 229 fail:
171 230 return error;
172 231 }
... ... @@ -193,7 +252,7 @@
193 252 "%s:%u: destroy event receive port failed %d\n",
194 253 __func__, __LINE__, error);
195 254  
196   - error = ps3_close_hv_device(&dev->sbd);
  255 + error = ps3stor_close_hv_device(&dev->sbd);
197 256 if (error)
198 257 dev_err(&dev->sbd.core,
199 258 "%s:%u: ps3_close_hv_device failed %d\n", __func__,