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