935912c538f15 (Thomas Gleixner 2019-05-27 08:55:12 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 2) /*
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 3) * PS3 FLASH ROM Storage Driver
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 4) *
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 5) * Copyright (C) 2007 Sony Computer Entertainment Inc.
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 6) * Copyright 2007 Sony Corp.
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 7) */
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 8)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 9) #include <linux/fs.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 10) #include <linux/miscdevice.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 11) #include <linux/slab.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 12) #include <linux/uaccess.h>
c22405c98d3ff (Paul Gortmaker 2011-07-03 13:35:48 -0400 13) #include <linux/module.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 14)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 15) #include <asm/lv1call.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 16) #include <asm/ps3stor.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 17)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 18)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 19) #define DEVICE_NAME "ps3flash"
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 20)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 21) #define FLASH_BLOCK_SIZE (256*1024)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 22)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 23)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 24) struct ps3flash_private {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 25) struct mutex mutex; /* Bounce buffer mutex */
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 26) u64 chunk_sectors;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 27) int tag; /* Start sector of buffer, -1 if invalid */
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 28) bool dirty;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 29) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 30)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 31) static struct ps3_storage_device *ps3flash_dev;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 32)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 33) static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 34) u64 start_sector, int write)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 35) {
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 36) struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 37) u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 38) start_sector, priv->chunk_sectors,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 39) write);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 40) if (res) {
4c33d2dc34f50 (Stephen Rothwell 2009-01-13 20:06:02 +0000 41) dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 42) __LINE__, write ? "write" : "read", res);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 43) return -EIO;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 44) }
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 45) return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 46) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 47)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 48) static int ps3flash_writeback(struct ps3_storage_device *dev)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 49) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 50) struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 51) int res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 52)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 53) if (!priv->dirty || priv->tag < 0)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 54) return 0;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 55)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 56) res = ps3flash_read_write_sectors(dev, priv->tag, 1);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 57) if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 58) return res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 59)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 60) priv->dirty = false;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 61) return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 62) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 63)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 64) static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 65) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 66) struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 67) int res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 68)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 69) if (start_sector == priv->tag)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 70) return 0;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 71)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 72) res = ps3flash_writeback(dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 73) if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 74) return res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 75)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 76) priv->tag = -1;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 77)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 78) res = ps3flash_read_write_sectors(dev, start_sector, 0);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 79) if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 80) return res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 81)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 82) priv->tag = start_sector;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 83) return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 84) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 85)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 86) static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 87) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 88) struct ps3_storage_device *dev = ps3flash_dev;
ee32465249bee (Al Viro 2013-06-17 10:05:35 +0400 89) return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
ee32465249bee (Al Viro 2013-06-17 10:05:35 +0400 90) dev->regions[dev->region_idx].size*dev->blk_size);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 91) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 92)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 93) static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 94) size_t count, loff_t *pos)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 95) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 96) struct ps3_storage_device *dev = ps3flash_dev;
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 97) struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 98) u64 size, sector, offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 99) int res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 100) size_t remaining, n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 101) const void *src;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 102)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 103) dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 104) "%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 105) __func__, __LINE__, count, *pos, userbuf, kernelbuf);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 106)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 107) size = dev->regions[dev->region_idx].size*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 108) if (*pos >= size || !count)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 109) return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 110)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 111) if (*pos + count > size) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 112) dev_dbg(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 113) "%s:%u Truncating count from %zu to %llu\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 114) __LINE__, count, size - *pos);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 115) count = size - *pos;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 116) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 117)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 118) sector = *pos / dev->bounce_size * priv->chunk_sectors;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 119) offset = *pos % dev->bounce_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 120)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 121) remaining = count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 122) do {
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 123) n = min_t(u64, remaining, dev->bounce_size - offset);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 124) src = dev->bounce_buf + offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 125)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 126) mutex_lock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 127)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 128) res = ps3flash_fetch(dev, sector);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 129) if (res)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 130) goto fail;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 131)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 132) dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 133) "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 134) __func__, __LINE__, n, src, userbuf, kernelbuf);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 135) if (userbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 136) if (copy_to_user(userbuf, src, n)) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 137) res = -EFAULT;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 138) goto fail;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 139) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 140) userbuf += n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 141) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 142) if (kernelbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 143) memcpy(kernelbuf, src, n);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 144) kernelbuf += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 145) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 146)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 147) mutex_unlock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 148)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 149) *pos += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 150) remaining -= n;
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 151) sector += priv->chunk_sectors;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 152) offset = 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 153) } while (remaining > 0);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 154)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 155) return count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 156)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 157) fail:
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 158) mutex_unlock(&priv->mutex);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 159) return res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 160) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 161)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 162) static ssize_t ps3flash_write(const char __user *userbuf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 163) const void *kernelbuf, size_t count, loff_t *pos)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 164) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 165) struct ps3_storage_device *dev = ps3flash_dev;
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 166) struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 167) u64 size, sector, offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 168) int res = 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 169) size_t remaining, n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 170) void *dst;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 171)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 172) dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 173) "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 174) __func__, __LINE__, count, *pos, userbuf, kernelbuf);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 175)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 176) size = dev->regions[dev->region_idx].size*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 177) if (*pos >= size || !count)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 178) return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 179)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 180) if (*pos + count > size) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 181) dev_dbg(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 182) "%s:%u Truncating count from %zu to %llu\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 183) __LINE__, count, size - *pos);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 184) count = size - *pos;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 185) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 186)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 187) sector = *pos / dev->bounce_size * priv->chunk_sectors;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 188) offset = *pos % dev->bounce_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 189)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 190) remaining = count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 191) do {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 192) n = min_t(u64, remaining, dev->bounce_size - offset);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 193) dst = dev->bounce_buf + offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 194)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 195) mutex_lock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 196)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 197) if (n != dev->bounce_size)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 198) res = ps3flash_fetch(dev, sector);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 199) else if (sector != priv->tag)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 200) res = ps3flash_writeback(dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 201) if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 202) goto fail;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 203)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 204) dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 205) "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 206) __func__, __LINE__, n, userbuf, kernelbuf, dst);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 207) if (userbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 208) if (copy_from_user(dst, userbuf, n)) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 209) res = -EFAULT;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 210) goto fail;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 211) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 212) userbuf += n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 213) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 214) if (kernelbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 215) memcpy(dst, kernelbuf, n);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 216) kernelbuf += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 217) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 218)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 219) priv->tag = sector;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 220) priv->dirty = true;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 221)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 222) mutex_unlock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 223)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 224) *pos += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 225) remaining -= n;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 226) sector += priv->chunk_sectors;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 227) offset = 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 228) } while (remaining > 0);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 229)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 230) return count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 231)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 232) fail:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 233) mutex_unlock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 234) return res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 235) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 236)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 237) static ssize_t ps3flash_user_read(struct file *file, char __user *buf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 238) size_t count, loff_t *pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 239) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 240) return ps3flash_read(buf, NULL, count, pos);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 241) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 242)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 243) static ssize_t ps3flash_user_write(struct file *file, const char __user *buf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 244) size_t count, loff_t *pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 245) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 246) return ps3flash_write(buf, NULL, count, pos);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 247) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 248)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 249) static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 250) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 251) return ps3flash_read(NULL, buf, count, &pos);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 252) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 253)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 254) static ssize_t ps3flash_kernel_write(const void *buf, size_t count,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 255) loff_t pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 256) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 257) ssize_t res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 258) int wb;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 259)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 260) res = ps3flash_write(NULL, buf, count, &pos);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 261) if (res < 0)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 262) return res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 263)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 264) /* Make kernel writes synchronous */
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 265) wb = ps3flash_writeback(ps3flash_dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 266) if (wb)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 267) return wb;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 268)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 269) return res;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 270) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 271)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 272) static int ps3flash_flush(struct file *file, fl_owner_t id)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 273) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 274) return ps3flash_writeback(ps3flash_dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 275) }
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 276)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 277) static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 278) {
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 279) struct inode *inode = file_inode(file);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 280) int err;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 281) inode_lock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 282) err = ps3flash_writeback(ps3flash_dev);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 283) inode_unlock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 284) return err;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 285) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 286)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 287) static irqreturn_t ps3flash_interrupt(int irq, void *data)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 288) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 289) struct ps3_storage_device *dev = data;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 290) int res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 291) u64 tag, status;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 292)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 293) res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 294)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 295) if (tag != dev->tag)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 296) dev_err(&dev->sbd.core,
4c33d2dc34f50 (Stephen Rothwell 2009-01-13 20:06:02 +0000 297) "%s:%u: tag mismatch, got %llx, expected %llx\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 298) __func__, __LINE__, tag, dev->tag);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 299)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 300) if (res) {
4c33d2dc34f50 (Stephen Rothwell 2009-01-13 20:06:02 +0000 301) dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 302) __func__, __LINE__, res, status);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 303) } else {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 304) dev->lv1_status = status;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 305) complete(&dev->done);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 306) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 307) return IRQ_HANDLED;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 308) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 309)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 310) static const struct file_operations ps3flash_fops = {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 311) .owner = THIS_MODULE,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 312) .llseek = ps3flash_llseek,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 313) .read = ps3flash_user_read,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 314) .write = ps3flash_user_write,
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 315) .flush = ps3flash_flush,
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 316) .fsync = ps3flash_fsync,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 317) };
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 318)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 319) static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 320) .read = ps3flash_kernel_read,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 321) .write = ps3flash_kernel_write,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 322) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 323)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 324) static struct miscdevice ps3flash_misc = {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 325) .minor = MISC_DYNAMIC_MINOR,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 326) .name = DEVICE_NAME,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 327) .fops = &ps3flash_fops,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 328) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 329)
2223cbec33ef3 (Bill Pemberton 2012-11-19 13:22:51 -0500 330) static int ps3flash_probe(struct ps3_system_bus_device *_dev)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 331) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 332) struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 333) struct ps3flash_private *priv;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 334) int error;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 335) unsigned long tmp;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 336)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 337) tmp = dev->regions[dev->region_idx].start*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 338) if (tmp % FLASH_BLOCK_SIZE) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 339) dev_err(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 340) "%s:%u region start %lu is not aligned\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 341) __LINE__, tmp);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 342) return -EINVAL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 343) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 344) tmp = dev->regions[dev->region_idx].size*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 345) if (tmp % FLASH_BLOCK_SIZE) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 346) dev_err(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 347) "%s:%u region size %lu is not aligned\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 348) __LINE__, tmp);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 349) return -EINVAL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 350) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 351)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 352) /* use static buffer, kmalloc cannot allocate 256 KiB */
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 353) if (!ps3flash_bounce_buffer.address)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 354) return -ENODEV;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 355)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 356) if (ps3flash_dev) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 357) dev_err(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 358) "Only one FLASH device is supported\n");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 359) return -EBUSY;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 360) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 361)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 362) ps3flash_dev = dev;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 363)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 364) priv = kzalloc(sizeof(*priv), GFP_KERNEL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 365) if (!priv) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 366) error = -ENOMEM;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 367) goto fail;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 368) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 369)
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 370) ps3_system_bus_set_drvdata(&dev->sbd, priv);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 371) mutex_init(&priv->mutex);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 372) priv->tag = -1;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 373)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 374) dev->bounce_size = ps3flash_bounce_buffer.size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 375) dev->bounce_buf = ps3flash_bounce_buffer.address;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 376) priv->chunk_sectors = dev->bounce_size / dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 377)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 378) error = ps3stor_setup(dev, ps3flash_interrupt);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 379) if (error)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 380) goto fail_free_priv;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 381)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 382) ps3flash_misc.parent = &dev->sbd.core;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 383) error = misc_register(&ps3flash_misc);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 384) if (error) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 385) dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 386) __func__, __LINE__, error);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 387) goto fail_teardown;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 388) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 389)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 390) dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 391) __func__, __LINE__, ps3flash_misc.minor);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 392)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 393) ps3_os_area_flash_register(&ps3flash_kernel_ops);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 394) return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 395)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 396) fail_teardown:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 397) ps3stor_teardown(dev);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 398) fail_free_priv:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 399) kfree(priv);
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 400) ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 401) fail:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 402) ps3flash_dev = NULL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 403) return error;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 404) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 405)
6d247e4d26496 (Uwe Kleine-König 2020-11-26 17:59:50 +0100 406) static void ps3flash_remove(struct ps3_system_bus_device *_dev)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 407) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 408) struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 409)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 410) ps3_os_area_flash_register(NULL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 411) misc_deregister(&ps3flash_misc);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 412) ps3stor_teardown(dev);
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 413) kfree(ps3_system_bus_get_drvdata(&dev->sbd));
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 414) ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 415) ps3flash_dev = NULL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 416) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 417)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 418)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 419) static struct ps3_system_bus_driver ps3flash = {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 420) .match_id = PS3_MATCH_ID_STOR_FLASH,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 421) .core.name = DEVICE_NAME,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 422) .core.owner = THIS_MODULE,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 423) .probe = ps3flash_probe,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 424) .remove = ps3flash_remove,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 425) .shutdown = ps3flash_remove,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 426) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 427)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 428)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 429) static int __init ps3flash_init(void)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 430) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 431) return ps3_system_bus_driver_register(&ps3flash);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 432) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 433)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 434) static void __exit ps3flash_exit(void)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 435) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 436) ps3_system_bus_driver_unregister(&ps3flash);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 437) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 438)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 439) module_init(ps3flash_init);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 440) module_exit(ps3flash_exit);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 441)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 442) MODULE_LICENSE("GPL");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 443) MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 444) MODULE_AUTHOR("Sony Corporation");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 445) MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);