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, int datasync) 309 { 310 return ps3flash_writeback(ps3flash_dev); 311 } 312 313 static irqreturn_t ps3flash_interrupt(int irq, void *data) 314 { 315 struct ps3_storage_device *dev = data; 316 int res; 317 u64 tag, status; 318 319 res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); 320 321 if (tag != dev->tag) 322 dev_err(&dev->sbd.core, 323 "%s:%u: tag mismatch, got %llx, expected %llx\n", 324 __func__, __LINE__, tag, dev->tag); 325 326 if (res) { 327 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n", 328 __func__, __LINE__, res, status); 329 } else { 330 dev->lv1_status = status; 331 complete(&dev->done); 332 } 333 return IRQ_HANDLED; 334 } 335 336 static const struct file_operations ps3flash_fops = { 337 .owner = THIS_MODULE, 338 .llseek = ps3flash_llseek, 339 .read = ps3flash_user_read, 340 .write = ps3flash_user_write, 341 .flush = ps3flash_flush, 342 .fsync = ps3flash_fsync, 343 }; 344 345 static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = { 346 .read = ps3flash_kernel_read, 347 .write = ps3flash_kernel_write, 348 }; 349 350 static struct miscdevice ps3flash_misc = { 351 .minor = MISC_DYNAMIC_MINOR, 352 .name = DEVICE_NAME, 353 .fops = &ps3flash_fops, 354 }; 355 356 static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) 357 { 358 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); 359 struct ps3flash_private *priv; 360 int error; 361 unsigned long tmp; 362 363 tmp = dev->regions[dev->region_idx].start*dev->blk_size; 364 if (tmp % FLASH_BLOCK_SIZE) { 365 dev_err(&dev->sbd.core, 366 "%s:%u region start %lu is not aligned\n", __func__, 367 __LINE__, tmp); 368 return -EINVAL; 369 } 370 tmp = dev->regions[dev->region_idx].size*dev->blk_size; 371 if (tmp % FLASH_BLOCK_SIZE) { 372 dev_err(&dev->sbd.core, 373 "%s:%u region size %lu is not aligned\n", __func__, 374 __LINE__, tmp); 375 return -EINVAL; 376 } 377 378 /* use static buffer, kmalloc cannot allocate 256 KiB */ 379 if (!ps3flash_bounce_buffer.address) 380 return -ENODEV; 381 382 if (ps3flash_dev) { 383 dev_err(&dev->sbd.core, 384 "Only one FLASH device is supported\n"); 385 return -EBUSY; 386 } 387 388 ps3flash_dev = dev; 389 390 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 391 if (!priv) { 392 error = -ENOMEM; 393 goto fail; 394 } 395 396 ps3_system_bus_set_drvdata(&dev->sbd, priv); 397 mutex_init(&priv->mutex); 398 priv->tag = -1; 399 400 dev->bounce_size = ps3flash_bounce_buffer.size; 401 dev->bounce_buf = ps3flash_bounce_buffer.address; 402 priv->chunk_sectors = dev->bounce_size / dev->blk_size; 403 404 error = ps3stor_setup(dev, ps3flash_interrupt); 405 if (error) 406 goto fail_free_priv; 407 408 ps3flash_misc.parent = &dev->sbd.core; 409 error = misc_register(&ps3flash_misc); 410 if (error) { 411 dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n", 412 __func__, __LINE__, error); 413 goto fail_teardown; 414 } 415 416 dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n", 417 __func__, __LINE__, ps3flash_misc.minor); 418 419 ps3_os_area_flash_register(&ps3flash_kernel_ops); 420 return 0; 421 422 fail_teardown: 423 ps3stor_teardown(dev); 424 fail_free_priv: 425 kfree(priv); 426 ps3_system_bus_set_drvdata(&dev->sbd, NULL); 427 fail: 428 ps3flash_dev = NULL; 429 return error; 430 } 431 432 static int ps3flash_remove(struct ps3_system_bus_device *_dev) 433 { 434 struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); 435 436 ps3_os_area_flash_register(NULL); 437 misc_deregister(&ps3flash_misc); 438 ps3stor_teardown(dev); 439 kfree(ps3_system_bus_get_drvdata(&dev->sbd)); 440 ps3_system_bus_set_drvdata(&dev->sbd, NULL); 441 ps3flash_dev = NULL; 442 return 0; 443 } 444 445 446 static struct ps3_system_bus_driver ps3flash = { 447 .match_id = PS3_MATCH_ID_STOR_FLASH, 448 .core.name = DEVICE_NAME, 449 .core.owner = THIS_MODULE, 450 .probe = ps3flash_probe, 451 .remove = ps3flash_remove, 452 .shutdown = ps3flash_remove, 453 }; 454 455 456 static int __init ps3flash_init(void) 457 { 458 return ps3_system_bus_driver_register(&ps3flash); 459 } 460 461 static void __exit ps3flash_exit(void) 462 { 463 ps3_system_bus_driver_unregister(&ps3flash); 464 } 465 466 module_init(ps3flash_init); 467 module_exit(ps3flash_exit); 468 469 MODULE_LICENSE("GPL"); 470 MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver"); 471 MODULE_AUTHOR("Sony Corporation"); 472 MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH); 473