0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/fs.h>
0010 #include <linux/miscdevice.h>
0011 #include <linux/slab.h>
0012 #include <linux/uaccess.h>
0013 #include <linux/module.h>
0014
0015 #include <asm/lv1call.h>
0016 #include <asm/ps3stor.h>
0017
0018
0019 #define DEVICE_NAME "ps3flash"
0020
0021 #define FLASH_BLOCK_SIZE (256*1024)
0022
0023
0024 struct ps3flash_private {
0025 struct mutex mutex;
0026 u64 chunk_sectors;
0027 int tag;
0028 bool dirty;
0029 };
0030
0031 static struct ps3_storage_device *ps3flash_dev;
0032
0033 static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
0034 u64 start_sector, int write)
0035 {
0036 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
0037 u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
0038 start_sector, priv->chunk_sectors,
0039 write);
0040 if (res) {
0041 dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
0042 __LINE__, write ? "write" : "read", res);
0043 return -EIO;
0044 }
0045 return 0;
0046 }
0047
0048 static int ps3flash_writeback(struct ps3_storage_device *dev)
0049 {
0050 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
0051 int res;
0052
0053 if (!priv->dirty || priv->tag < 0)
0054 return 0;
0055
0056 res = ps3flash_read_write_sectors(dev, priv->tag, 1);
0057 if (res)
0058 return res;
0059
0060 priv->dirty = false;
0061 return 0;
0062 }
0063
0064 static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
0065 {
0066 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
0067 int res;
0068
0069 if (start_sector == priv->tag)
0070 return 0;
0071
0072 res = ps3flash_writeback(dev);
0073 if (res)
0074 return res;
0075
0076 priv->tag = -1;
0077
0078 res = ps3flash_read_write_sectors(dev, start_sector, 0);
0079 if (res)
0080 return res;
0081
0082 priv->tag = start_sector;
0083 return 0;
0084 }
0085
0086 static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
0087 {
0088 struct ps3_storage_device *dev = ps3flash_dev;
0089 return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
0090 dev->regions[dev->region_idx].size*dev->blk_size);
0091 }
0092
0093 static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
0094 size_t count, loff_t *pos)
0095 {
0096 struct ps3_storage_device *dev = ps3flash_dev;
0097 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
0098 u64 size, sector, offset;
0099 int res;
0100 size_t remaining, n;
0101 const void *src;
0102
0103 dev_dbg(&dev->sbd.core,
0104 "%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
0105 __func__, __LINE__, count, *pos, userbuf, kernelbuf);
0106
0107 size = dev->regions[dev->region_idx].size*dev->blk_size;
0108 if (*pos >= size || !count)
0109 return 0;
0110
0111 if (*pos + count > size) {
0112 dev_dbg(&dev->sbd.core,
0113 "%s:%u Truncating count from %zu to %llu\n", __func__,
0114 __LINE__, count, size - *pos);
0115 count = size - *pos;
0116 }
0117
0118 sector = *pos / dev->bounce_size * priv->chunk_sectors;
0119 offset = *pos % dev->bounce_size;
0120
0121 remaining = count;
0122 do {
0123 n = min_t(u64, remaining, dev->bounce_size - offset);
0124 src = dev->bounce_buf + offset;
0125
0126 mutex_lock(&priv->mutex);
0127
0128 res = ps3flash_fetch(dev, sector);
0129 if (res)
0130 goto fail;
0131
0132 dev_dbg(&dev->sbd.core,
0133 "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n",
0134 __func__, __LINE__, n, src, userbuf, kernelbuf);
0135 if (userbuf) {
0136 if (copy_to_user(userbuf, src, n)) {
0137 res = -EFAULT;
0138 goto fail;
0139 }
0140 userbuf += n;
0141 }
0142 if (kernelbuf) {
0143 memcpy(kernelbuf, src, n);
0144 kernelbuf += n;
0145 }
0146
0147 mutex_unlock(&priv->mutex);
0148
0149 *pos += n;
0150 remaining -= n;
0151 sector += priv->chunk_sectors;
0152 offset = 0;
0153 } while (remaining > 0);
0154
0155 return count;
0156
0157 fail:
0158 mutex_unlock(&priv->mutex);
0159 return res;
0160 }
0161
0162 static ssize_t ps3flash_write(const char __user *userbuf,
0163 const void *kernelbuf, size_t count, loff_t *pos)
0164 {
0165 struct ps3_storage_device *dev = ps3flash_dev;
0166 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
0167 u64 size, sector, offset;
0168 int res = 0;
0169 size_t remaining, n;
0170 void *dst;
0171
0172 dev_dbg(&dev->sbd.core,
0173 "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
0174 __func__, __LINE__, count, *pos, userbuf, kernelbuf);
0175
0176 size = dev->regions[dev->region_idx].size*dev->blk_size;
0177 if (*pos >= size || !count)
0178 return 0;
0179
0180 if (*pos + count > size) {
0181 dev_dbg(&dev->sbd.core,
0182 "%s:%u Truncating count from %zu to %llu\n", __func__,
0183 __LINE__, count, size - *pos);
0184 count = size - *pos;
0185 }
0186
0187 sector = *pos / dev->bounce_size * priv->chunk_sectors;
0188 offset = *pos % dev->bounce_size;
0189
0190 remaining = count;
0191 do {
0192 n = min_t(u64, remaining, dev->bounce_size - offset);
0193 dst = dev->bounce_buf + offset;
0194
0195 mutex_lock(&priv->mutex);
0196
0197 if (n != dev->bounce_size)
0198 res = ps3flash_fetch(dev, sector);
0199 else if (sector != priv->tag)
0200 res = ps3flash_writeback(dev);
0201 if (res)
0202 goto fail;
0203
0204 dev_dbg(&dev->sbd.core,
0205 "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n",
0206 __func__, __LINE__, n, userbuf, kernelbuf, dst);
0207 if (userbuf) {
0208 if (copy_from_user(dst, userbuf, n)) {
0209 res = -EFAULT;
0210 goto fail;
0211 }
0212 userbuf += n;
0213 }
0214 if (kernelbuf) {
0215 memcpy(dst, kernelbuf, n);
0216 kernelbuf += n;
0217 }
0218
0219 priv->tag = sector;
0220 priv->dirty = true;
0221
0222 mutex_unlock(&priv->mutex);
0223
0224 *pos += n;
0225 remaining -= n;
0226 sector += priv->chunk_sectors;
0227 offset = 0;
0228 } while (remaining > 0);
0229
0230 return count;
0231
0232 fail:
0233 mutex_unlock(&priv->mutex);
0234 return res;
0235 }
0236
0237 static ssize_t ps3flash_user_read(struct file *file, char __user *buf,
0238 size_t count, loff_t *pos)
0239 {
0240 return ps3flash_read(buf, NULL, count, pos);
0241 }
0242
0243 static ssize_t ps3flash_user_write(struct file *file, const char __user *buf,
0244 size_t count, loff_t *pos)
0245 {
0246 return ps3flash_write(buf, NULL, count, pos);
0247 }
0248
0249 static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos)
0250 {
0251 return ps3flash_read(NULL, buf, count, &pos);
0252 }
0253
0254 static ssize_t ps3flash_kernel_write(const void *buf, size_t count,
0255 loff_t pos)
0256 {
0257 ssize_t res;
0258 int wb;
0259
0260 res = ps3flash_write(NULL, buf, count, &pos);
0261 if (res < 0)
0262 return res;
0263
0264
0265 wb = ps3flash_writeback(ps3flash_dev);
0266 if (wb)
0267 return wb;
0268
0269 return res;
0270 }
0271
0272 static int ps3flash_flush(struct file *file, fl_owner_t id)
0273 {
0274 return ps3flash_writeback(ps3flash_dev);
0275 }
0276
0277 static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
0278 {
0279 struct inode *inode = file_inode(file);
0280 int err;
0281 inode_lock(inode);
0282 err = ps3flash_writeback(ps3flash_dev);
0283 inode_unlock(inode);
0284 return err;
0285 }
0286
0287 static irqreturn_t ps3flash_interrupt(int irq, void *data)
0288 {
0289 struct ps3_storage_device *dev = data;
0290 int res;
0291 u64 tag, status;
0292
0293 res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
0294
0295 if (tag != dev->tag)
0296 dev_err(&dev->sbd.core,
0297 "%s:%u: tag mismatch, got %llx, expected %llx\n",
0298 __func__, __LINE__, tag, dev->tag);
0299
0300 if (res) {
0301 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
0302 __func__, __LINE__, res, status);
0303 } else {
0304 dev->lv1_status = status;
0305 complete(&dev->done);
0306 }
0307 return IRQ_HANDLED;
0308 }
0309
0310 static const struct file_operations ps3flash_fops = {
0311 .owner = THIS_MODULE,
0312 .llseek = ps3flash_llseek,
0313 .read = ps3flash_user_read,
0314 .write = ps3flash_user_write,
0315 .flush = ps3flash_flush,
0316 .fsync = ps3flash_fsync,
0317 };
0318
0319 static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = {
0320 .read = ps3flash_kernel_read,
0321 .write = ps3flash_kernel_write,
0322 };
0323
0324 static struct miscdevice ps3flash_misc = {
0325 .minor = MISC_DYNAMIC_MINOR,
0326 .name = DEVICE_NAME,
0327 .fops = &ps3flash_fops,
0328 };
0329
0330 static int ps3flash_probe(struct ps3_system_bus_device *_dev)
0331 {
0332 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
0333 struct ps3flash_private *priv;
0334 int error;
0335 unsigned long tmp;
0336
0337 tmp = dev->regions[dev->region_idx].start*dev->blk_size;
0338 if (tmp % FLASH_BLOCK_SIZE) {
0339 dev_err(&dev->sbd.core,
0340 "%s:%u region start %lu is not aligned\n", __func__,
0341 __LINE__, tmp);
0342 return -EINVAL;
0343 }
0344 tmp = dev->regions[dev->region_idx].size*dev->blk_size;
0345 if (tmp % FLASH_BLOCK_SIZE) {
0346 dev_err(&dev->sbd.core,
0347 "%s:%u region size %lu is not aligned\n", __func__,
0348 __LINE__, tmp);
0349 return -EINVAL;
0350 }
0351
0352
0353 if (!ps3flash_bounce_buffer.address)
0354 return -ENODEV;
0355
0356 if (ps3flash_dev) {
0357 dev_err(&dev->sbd.core,
0358 "Only one FLASH device is supported\n");
0359 return -EBUSY;
0360 }
0361
0362 ps3flash_dev = dev;
0363
0364 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0365 if (!priv) {
0366 error = -ENOMEM;
0367 goto fail;
0368 }
0369
0370 ps3_system_bus_set_drvdata(&dev->sbd, priv);
0371 mutex_init(&priv->mutex);
0372 priv->tag = -1;
0373
0374 dev->bounce_size = ps3flash_bounce_buffer.size;
0375 dev->bounce_buf = ps3flash_bounce_buffer.address;
0376 priv->chunk_sectors = dev->bounce_size / dev->blk_size;
0377
0378 error = ps3stor_setup(dev, ps3flash_interrupt);
0379 if (error)
0380 goto fail_free_priv;
0381
0382 ps3flash_misc.parent = &dev->sbd.core;
0383 error = misc_register(&ps3flash_misc);
0384 if (error) {
0385 dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
0386 __func__, __LINE__, error);
0387 goto fail_teardown;
0388 }
0389
0390 dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
0391 __func__, __LINE__, ps3flash_misc.minor);
0392
0393 ps3_os_area_flash_register(&ps3flash_kernel_ops);
0394 return 0;
0395
0396 fail_teardown:
0397 ps3stor_teardown(dev);
0398 fail_free_priv:
0399 kfree(priv);
0400 ps3_system_bus_set_drvdata(&dev->sbd, NULL);
0401 fail:
0402 ps3flash_dev = NULL;
0403 return error;
0404 }
0405
0406 static void ps3flash_remove(struct ps3_system_bus_device *_dev)
0407 {
0408 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
0409
0410 ps3_os_area_flash_register(NULL);
0411 misc_deregister(&ps3flash_misc);
0412 ps3stor_teardown(dev);
0413 kfree(ps3_system_bus_get_drvdata(&dev->sbd));
0414 ps3_system_bus_set_drvdata(&dev->sbd, NULL);
0415 ps3flash_dev = NULL;
0416 }
0417
0418
0419 static struct ps3_system_bus_driver ps3flash = {
0420 .match_id = PS3_MATCH_ID_STOR_FLASH,
0421 .core.name = DEVICE_NAME,
0422 .core.owner = THIS_MODULE,
0423 .probe = ps3flash_probe,
0424 .remove = ps3flash_remove,
0425 .shutdown = ps3flash_remove,
0426 };
0427
0428
0429 static int __init ps3flash_init(void)
0430 {
0431 return ps3_system_bus_driver_register(&ps3flash);
0432 }
0433
0434 static void __exit ps3flash_exit(void)
0435 {
0436 ps3_system_bus_driver_unregister(&ps3flash);
0437 }
0438
0439 module_init(ps3flash_init);
0440 module_exit(ps3flash_exit);
0441
0442 MODULE_LICENSE("GPL");
0443 MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver");
0444 MODULE_AUTHOR("Sony Corporation");
0445 MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);