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