#include <asm/lv1call.h>
#include <asm/ps3stor.h>
+/*
+ * A workaround for flash memory I/O errors when the internal hard disk
+ * has not been formatted for OtherOS use. Delay disk close until flash
+ * memory is closed.
+ */
+
+static struct ps3_flash_workaround {
+ int flash_open;
+ int disk_open;
+ struct ps3_system_bus_device *disk_sbd;
+} ps3_flash_workaround;
+
+static int ps3stor_open_hv_device(struct ps3_system_bus_device *sbd)
+{
+ int error = ps3_open_hv_device(sbd);
+
+ if (error)
+ return error;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_FLASH)
+ ps3_flash_workaround.flash_open = 1;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_DISK)
+ ps3_flash_workaround.disk_open = 1;
+
+ return 0;
+}
+
+static int ps3stor_close_hv_device(struct ps3_system_bus_device *sbd)
+{
+ int error;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_DISK
+ && ps3_flash_workaround.disk_open
+ && ps3_flash_workaround.flash_open) {
+ ps3_flash_workaround.disk_sbd = sbd;
+ return 0;
+ }
+
+ error = ps3_close_hv_device(sbd);
+
+ if (error)
+ return error;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_DISK)
+ ps3_flash_workaround.disk_open = 0;
+
+ if (sbd->match_id == PS3_MATCH_ID_STOR_FLASH) {
+ ps3_flash_workaround.flash_open = 0;
+
+ if (ps3_flash_workaround.disk_sbd) {
+ ps3_close_hv_device(ps3_flash_workaround.disk_sbd);
+ ps3_flash_workaround.disk_open = 0;
+ ps3_flash_workaround.disk_sbd = NULL;
+ }
+ }
+
+ return 0;
+}
static int ps3stor_probe_access(struct ps3_storage_device *dev)
{
if (n > 1)
dev_info(&dev->sbd.core,
"%s:%u: %lu accessible regions found. Only the first "
- "one will be used",
+ "one will be used\n",
__func__, __LINE__, n);
dev->region_idx = __ffs(dev->accessible_regions);
dev_info(&dev->sbd.core,
- "First accessible region has index %u start %lu size %lu\n",
+ "First accessible region has index %u start %llu size %llu\n",
dev->region_idx, dev->regions[dev->region_idx].start,
dev->regions[dev->region_idx].size);
int error, res, alignment;
enum ps3_dma_page_size page_size;
- error = ps3_open_hv_device(&dev->sbd);
+ error = ps3stor_open_hv_device(&dev->sbd);
if (error) {
dev_err(&dev->sbd.core,
"%s:%u: ps3_open_hv_device failed %d\n", __func__,
fail_sb_event_receive_port_destroy:
ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
fail_close_device:
- ps3_close_hv_device(&dev->sbd);
+ ps3stor_close_hv_device(&dev->sbd);
fail:
return error;
}
"%s:%u: destroy event receive port failed %d\n",
__func__, __LINE__, error);
- error = ps3_close_hv_device(&dev->sbd);
+ error = ps3stor_close_hv_device(&dev->sbd);
if (error)
dev_err(&dev->sbd.core,
"%s:%u: ps3_close_hv_device failed %d\n", __func__,
const char *op = write ? "write" : "read";
int res;
- dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+ dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
__func__, __LINE__, op, sectors, start_sector);
init_completion(&dev->done);
wait_for_completion(&dev->done);
if (dev->lv1_status) {
- dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
__LINE__, op, dev->lv1_status);
return dev->lv1_status;
}
{
int res;
- dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%llx\n", __func__,
__LINE__, cmd);
init_completion(&dev->done);
arg2, arg3, arg4, &dev->tag);
if (res) {
dev_err(&dev->sbd.core,
- "%s:%u: send_device_command 0x%lx failed %d\n",
+ "%s:%u: send_device_command 0x%llx failed %d\n",
__func__, __LINE__, cmd, res);
return -1;
}
wait_for_completion(&dev->done);
if (dev->lv1_status) {
- dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
+ dev_dbg(&dev->sbd.core, "%s:%u: command 0x%llx failed 0x%llx\n",
__func__, __LINE__, cmd, dev->lv1_status);
return dev->lv1_status;
}
- dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: command 0x%llx completed\n", __func__,
__LINE__, cmd);
return 0;