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 loff_t res; 102 103 mutex_lock(&file->f_mapping->host->i_mutex); 104 switch (origin) { 105 case 0: 106 break; 107 case 1: 108 offset += file->f_pos; 109 break; 110 case 2: 111 offset += dev->regions[dev->region_idx].size*dev->blk_size; 112 break; 113 default: 114 offset = -1; 115 } 116 if (offset < 0) { 117 res = -EINVAL; 118 goto out; 119 } 120 121 file->f_pos = offset; 122 res = file->f_pos; 123 124 out: 125 mutex_unlock(&file->f_mapping->host->i_mutex); 126 return res; 127 } 128 129 static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf, 130 size_t count, loff_t *pos) 131 { 132 struct ps3_storage_device *dev = ps3flash_dev; 133 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 134 u64 size, sector, offset; 135 int res; 136 size_t remaining, n; 137 const void *src; 138 139 dev_dbg(&dev->sbd.core, 140 "%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n", 141 __func__, __LINE__, count, *pos, userbuf, kernelbuf); 142 143 size = dev->regions[dev->region_idx].size*dev->blk_size; 144 if (*pos >= size || !count) 145 return 0; 146 147 if (*pos + count > size) { 148 dev_dbg(&dev->sbd.core, 149 "%s:%u Truncating count from %zu to %llu\n", __func__, 150 __LINE__, count, size - *pos); 151 count = size - *pos; 152 } 153 154 sector = *pos / dev->bounce_size * priv->chunk_sectors; 155 offset = *pos % dev->bounce_size; 156 157 remaining = count; 158 do { 159 n = min_t(u64, remaining, dev->bounce_size - offset); 160 src = dev->bounce_buf + offset; 161 162 mutex_lock(&priv->mutex); 163 164 res = ps3flash_fetch(dev, sector); 165 if (res) 166 goto fail; 167 168 dev_dbg(&dev->sbd.core, 169 "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n", 170 __func__, __LINE__, n, src, userbuf, kernelbuf); 171 if (userbuf) { 172 if (copy_to_user(userbuf, src, n)) { 173 res = -EFAULT; 174 goto fail; 175 } 176 userbuf += n; 177 } 178 if (kernelbuf) { 179 memcpy(kernelbuf, src, n); 180 kernelbuf += n; 181 } 182 183 mutex_unlock(&priv->mutex); 184 185 *pos += n; 186 remaining -= n; 187 sector += priv->chunk_sectors; 188 offset = 0; 189 } while (remaining > 0); 190 191 return count; 192 193 fail: 194 mutex_unlock(&priv->mutex); 195 return res; 196 } 197 198 static ssize_t ps3flash_write(const char __user *userbuf, 199 const void *kernelbuf, size_t count, loff_t *pos) 200 { 201 struct ps3_storage_device *dev = ps3flash_dev; 202 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 203 u64 size, sector, offset; 204 int res = 0; 205 size_t remaining, n; 206 void *dst; 207 208 dev_dbg(&dev->sbd.core, 209 "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n", 210 __func__, __LINE__, count, *pos, userbuf, kernelbuf); 211 212 size = dev->regions[dev->region_idx].size*dev->blk_size; 213 if (*pos >= size || !count) 214 return 0; 215 216 if (*pos + count > size) { 217 dev_dbg(&dev->sbd.core, 218 "%s:%u Truncating count from %zu to %llu\n", __func__, 219 __LINE__, count, size - *pos); 220 count = size - *pos; 221 } 222 223 sector = *pos / dev->bounce_size * priv->chunk_sectors; 224 offset = *pos % dev->bounce_size; 225 226 remaining = count; 227 do { 228 n = min_t(u64, remaining, dev->bounce_size - offset); 229 dst = dev->bounce_buf + offset; 230 231 mutex_lock(&priv->mutex); 232 233 if (n != dev->bounce_size) 234 res = ps3flash_fetch(dev, sector); 235 else if (sector != priv->tag) 236 res = ps3flash_writeback(dev); 237 if (res) 238 goto fail; 239 240 dev_dbg(&dev->sbd.core, 241 "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n", 242 __func__, __LINE__, n, userbuf, kernelbuf, dst); 243 if (userbuf) { 244 if (copy_from_user(dst, userbuf, n)) { 245 res = -EFAULT; 246 goto fail; 247 } 248 userbuf += n; 249 } 250 if (kernelbuf) { 251 memcpy(dst, kernelbuf, n); 252 kernelbuf += n; 253 } 254 255 priv->tag = sector; 256 priv->dirty = true; 257 258 mutex_unlock(&priv->mutex); 259 260 *pos += n; 261 remaining -= n; 262 sector += priv->chunk_sectors; 263 offset = 0; 264 } while (remaining > 0); 265 266 return count; 267 268 fail: 269 mutex_unlock(&priv->mutex); 270 return res; 271 } 272 273 static ssize_t ps3flash_user_read(struct file *file, char __user *buf, 274 size_t count, loff_t *pos) 275 { 276 return ps3flash_read(buf, NULL, count, pos); 277 } 278 279 static ssize_t ps3flash_user_write(struct file *file, const char __user *buf, 280 size_t count, loff_t *pos) 281 { 282 return ps3flash_write(buf, NULL, count, pos); 283 } 284 285 static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos) 286 { 287 return ps3flash_read(NULL, buf, count, &pos); 288 } 289 290 static ssize_t ps3flash_kernel_write(const void *buf, size_t count, 291 loff_t pos) 292 { 293 ssize_t res; 294 int wb; 295 296 res = ps3flash_write(NULL, buf, count, &pos); 297 if (res < 0) 298 return res; 299 300 /* Make kernel writes synchronous */ 301 wb = ps3flash_writeback(ps3flash_dev); 302 if (wb) 303 return wb; 304 305 return res; 306 } 307 308 static int ps3flash_flush(struct file *file, fl_owner_t id) 309 { 310 return ps3flash_writeback(ps3flash_dev); 311 } 312 313 static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync) 314 { 315 struct inode *inode = file->f_path.dentry->d_inode; 316 int err; 317 mutex_lock(&inode->i_mutex); 318 err = ps3flash_writeback(ps3flash_dev); 319 mutex_unlock(&inode->i_mutex); 320 return err; 321 } 322 323 static irqreturn_t ps3flash_interrupt(int irq, void *data) 324 { 325 struct ps3_storage_device *dev = data; 326 int res; 327 u64 tag, status; 328 329 res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); 330 331 if (tag != dev->tag) 332 dev_err(&dev->sbd.core, 333 "%s:%u: tag mismatch, got %llx, expected %llx\n", 334 __func__, __LINE__, tag, dev->tag); 335 336 if (res) { 337 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n", 338 __func__, __LINE__, res, status); 339 } else { 340 dev->lv1_status = status; 341 complete(&dev->done); 342 } 343 return IRQ_HANDLED; 344 } 345 346 static const struct file_operations ps3flash_fops = { 347 .owner = THIS_MODULE, 348 .llseek = ps3flash_llseek, 349 .read = ps3flash_user_read, 350 .write = ps3flash_user_write, 351 .flush = ps3flash_flush, 352 .fsync = ps3flash_fsync, 353 }; 354 355 static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = { 356 .read = ps3flash_kernel_read, 357 .write = ps3flash_kernel_write, 358 }; 359 360 static struct miscdevice ps3flash_misc = { 361 .minor = MISC_DYNAMIC_MINOR, 362 .name = DEVICE_NAME, 363 .fops = &ps3flash_fops, 364 }; 365 366 static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) 367 { 368 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); 369 struct ps3flash_private *priv; 370 int error; 371 unsigned long tmp; 372 373 tmp = dev->regions[dev->region_idx].start*dev->blk_size; 374 if (tmp % FLASH_BLOCK_SIZE) { 375 dev_err(&dev->sbd.core, 376 "%s:%u region start %lu is not aligned\n", __func__, 377 __LINE__, tmp); 378 return -EINVAL; 379 } 380 tmp = dev->regions[dev->region_idx].size*dev->blk_size; 381 if (tmp % FLASH_BLOCK_SIZE) { 382 dev_err(&dev->sbd.core, 383 "%s:%u region size %lu is not aligned\n", __func__, 384 __LINE__, tmp); 385 return -EINVAL; 386 } 387 388 /* use static buffer, kmalloc cannot allocate 256 KiB */ 389 if (!ps3flash_bounce_buffer.address) 390 return -ENODEV; 391 392 if (ps3flash_dev) { 393 dev_err(&dev->sbd.core, 394 "Only one FLASH device is supported\n"); 395 return -EBUSY; 396 } 397 398 ps3flash_dev = dev; 399 400 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 401 if (!priv) { 402 error = -ENOMEM; 403 goto fail; 404 } 405 406 ps3_system_bus_set_drvdata(&dev->sbd, priv); 407 mutex_init(&priv->mutex); 408 priv->tag = -1; 409 410 dev->bounce_size = ps3flash_bounce_buffer.size; 411 dev->bounce_buf = ps3flash_bounce_buffer.address; 412 priv->chunk_sectors = dev->bounce_size / dev->blk_size; 413 414 error = ps3stor_setup(dev, ps3flash_interrupt); 415 if (error) 416 goto fail_free_priv; 417 418 ps3flash_misc.parent = &dev->sbd.core; 419 error = misc_register(&ps3flash_misc); 420 if (error) { 421 dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n", 422 __func__, __LINE__, error); 423 goto fail_teardown; 424 } 425 426 dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n", 427 __func__, __LINE__, ps3flash_misc.minor); 428 429 ps3_os_area_flash_register(&ps3flash_kernel_ops); 430 return 0; 431 432 fail_teardown: 433 ps3stor_teardown(dev); 434 fail_free_priv: 435 kfree(priv); 436 ps3_system_bus_set_drvdata(&dev->sbd, NULL); 437 fail: 438 ps3flash_dev = NULL; 439 return error; 440 } 441 442 static int ps3flash_remove(struct ps3_system_bus_device *_dev) 443 { 444 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); 445 446 ps3_os_area_flash_register(NULL); 447 misc_deregister(&ps3flash_misc); 448 ps3stor_teardown(dev); 449 kfree(ps3_system_bus_get_drvdata(&dev->sbd)); 450 ps3_system_bus_set_drvdata(&dev->sbd, NULL); 451 ps3flash_dev = NULL; 452 return 0; 453 } 454 455 456 static struct ps3_system_bus_driver ps3flash = { 457 .match_id = PS3_MATCH_ID_STOR_FLASH, 458 .core.name = DEVICE_NAME, 459 .core.owner = THIS_MODULE, 460 .probe = ps3flash_probe, 461 .remove = ps3flash_remove, 462 .shutdown = ps3flash_remove, 463 }; 464 465 466 static int __init ps3flash_init(void) 467 { 468 return ps3_system_bus_driver_register(&ps3flash); 469 } 470 471 static void __exit ps3flash_exit(void) 472 { 473 ps3_system_bus_driver_unregister(&ps3flash); 474 } 475 476 module_init(ps3flash_init); 477 module_exit(ps3flash_exit); 478 479 MODULE_LICENSE("GPL"); 480 MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver"); 481 MODULE_AUTHOR("Sony Corporation"); 482 MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH); 483