Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PS3 FLASH ROM Storage Driver
0004  *
0005  * Copyright (C) 2007 Sony Computer Entertainment Inc.
0006  * Copyright 2007 Sony Corp.
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; /* Bounce buffer mutex */
0026     u64 chunk_sectors;
0027     int tag;        /* Start sector of buffer, -1 if invalid */
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     /* Make kernel writes synchronous */
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     /* use static buffer, kmalloc cannot allocate 256 KiB */
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);