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/uaccess.h> 24 25 #include <asm/lv1call.h> 26 #include <asm/ps3stor.h> 27 28 29 #define DEVICE_NAME "ps3flash" 30 31 #define FLASH_BLOCK_SIZE (256*1024) 32 33 34 struct ps3flash_private { 35 struct mutex mutex; /* Bounce buffer mutex */ 36 u64 chunk_sectors; 37 int tag; /* Start sector of buffer, -1 if invalid */ 38 bool dirty; 39 }; 40 41 static struct ps3_storage_device *ps3flash_dev; 42 43 static int ps3flash_read_write_sectors(struct ps3_storage_device *dev, 44 u64 start_sector, int write) 45 { 46 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 47 u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 48 start_sector, priv->chunk_sectors, 49 write); 50 if (res) { 51 dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__, 52 __LINE__, write ? "write" : "read", res); 53 return -EIO; 54 } 55 return 0; 56 } 57 58 static int ps3flash_writeback(struct ps3_storage_device *dev) 59 { 60 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 61 int res; 62 63 if (!priv->dirty || priv->tag < 0) 64 return 0; 65 66 res = ps3flash_read_write_sectors(dev, priv->tag, 1); 67 if (res) 68 return res; 69 70 priv->dirty = false; 71 return 0; 72 } 73 74 static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector) 75 { 76 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 77 int res; 78 79 if (start_sector == priv->tag) 80 return 0; 81 82 res = ps3flash_writeback(dev); 83 if (res) 84 return res; 85 86 priv->tag = -1; 87 88 res = ps3flash_read_write_sectors(dev, start_sector, 0); 89 if (res) 90 return res; 91 92 priv->tag = start_sector; 93 return 0; 94 } 95 96 static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin) 97 { 98 struct ps3_storage_device *dev = ps3flash_dev; 99 loff_t res; 100 101 mutex_lock(&file->f_mapping->host->i_mutex); 102 switch (origin) { 103 case 1: 104 offset += file->f_pos; 105 break; 106 case 2: 107 offset += dev->regions[dev->region_idx].size*dev->blk_size; 108 break; 109 } 110 if (offset < 0) { 111 res = -EINVAL; 112 goto out; 113 } 114 115 file->f_pos = offset; 116 res = file->f_pos; 117 118 out: 119 mutex_unlock(&file->f_mapping->host->i_mutex); 120 return res; 121 } 122 123 static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf, 124 size_t count, loff_t *pos) 125 { 126 struct ps3_storage_device *dev = ps3flash_dev; 127 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 128 u64 size, sector, offset; 129 int res; 130 size_t remaining, n; 131 const void *src; 132 133 dev_dbg(&dev->sbd.core, 134 "%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n", 135 __func__, __LINE__, count, *pos, userbuf, kernelbuf); 136 137 size = dev->regions[dev->region_idx].size*dev->blk_size; 138 if (*pos >= size || !count) 139 return 0; 140 141 if (*pos + count > size) { 142 dev_dbg(&dev->sbd.core, 143 "%s:%u Truncating count from %zu to %llu\n", __func__, 144 __LINE__, count, size - *pos); 145 count = size - *pos; 146 } 147 148 sector = *pos / dev->bounce_size * priv->chunk_sectors; 149 offset = *pos % dev->bounce_size; 150 151 remaining = count; 152 do { 153 n = min_t(u64, remaining, dev->bounce_size - offset); 154 src = dev->bounce_buf + offset; 155 156 mutex_lock(&priv->mutex); 157 158 res = ps3flash_fetch(dev, sector); 159 if (res) 160 goto fail; 161 162 dev_dbg(&dev->sbd.core, 163 "%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n", 164 __func__, __LINE__, n, src, userbuf, kernelbuf); 165 if (userbuf) { 166 if (copy_to_user(userbuf, src, n)) { 167 res = -EFAULT; 168 goto fail; 169 } 170 userbuf += n; 171 } 172 if (kernelbuf) { 173 memcpy(kernelbuf, src, n); 174 kernelbuf += n; 175 } 176 177 mutex_unlock(&priv->mutex); 178 179 *pos += n; 180 remaining -= n; 181 sector += priv->chunk_sectors; 182 offset = 0; 183 } while (remaining > 0); 184 185 return count; 186 187 fail: 188 mutex_unlock(&priv->mutex); 189 return res; 190 } 191 192 static ssize_t ps3flash_write(const char __user *userbuf, 193 const void *kernelbuf, size_t count, loff_t *pos) 194 { 195 struct ps3_storage_device *dev = ps3flash_dev; 196 struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); 197 u64 size, sector, offset; 198 int res = 0; 199 size_t remaining, n; 200 void *dst; 201 202 dev_dbg(&dev->sbd.core, 203 "%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n", 204 __func__, __LINE__, count, *pos, userbuf, kernelbuf); 205 206 size = dev->regions[dev->region_idx].size*dev->blk_size; 207 if (*pos >= size || !count) 208 return 0; 209 210 if (*pos + count > size) { 211 dev_dbg(&dev->sbd.core, 212 "%s:%u Truncating count from %zu to %llu\n", __func__, 213 __LINE__, count, size - *pos); 214 count = size - *pos; 215 } 216 217 sector = *pos / dev->bounce_size * priv->chunk_sectors; 218 offset = *pos % dev->bounce_size; 219 220 remaining = count; 221 do { 222 n = min_t(u64, remaining, dev->bounce_size - offset); 223 dst = dev->bounce_buf + offset; 224 225 mutex_lock(&priv->mutex); 226 227 if (n != dev->bounce_size) 228 res = ps3flash_fetch(dev, sector); 229 else if (sector != priv->tag) 230 res = ps3flash_writeback(dev); 231 if (res) 232 goto fail; 233 234 dev_dbg(&dev->sbd.core, 235 "%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n", 236 __func__, __LINE__, n, userbuf, kernelbuf, dst); 237 if (userbuf) { 238 if (copy_from_user(dst, userbuf, n)) { 239 res = -EFAULT; 240 goto fail; 241 } 242 userbuf += n; 243 } 244 if (kernelbuf) { 245 memcpy(dst, kernelbuf, n); 246 kernelbuf += n; 247 } 248 249 priv->tag = sector; 250 priv->dirty = true; 251 252 mutex_unlock(&priv->mutex); 253 254 *pos += n; 255 remaining -= n; 256 sector += priv->chunk_sectors; 257 offset = 0; 258 } while (remaining > 0); 259 260 return count; 261 262 fail: 263 mutex_unlock(&priv->mutex); 264 return res; 265 } 266 267 static ssize_t ps3flash_user_read(struct file *file, char __user *buf, 268 size_t count, loff_t *pos) 269 { 270 return ps3flash_read(buf, NULL, count, pos); 271 } 272 273 static ssize_t ps3flash_user_write(struct file *file, const char __user *buf, 274 size_t count, loff_t *pos) 275 { 276 return ps3flash_write(buf, NULL, count, pos); 277 } 278 279 static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos) 280 { 281 return ps3flash_read(NULL, buf, count, &pos); 282 } 283 284 static ssize_t ps3flash_kernel_write(const void *buf, size_t count, 285 loff_t pos) 286 { 287 ssize_t res; 288 int wb; 289 290 res = ps3flash_write(NULL, buf, count, &pos); 291 if (res < 0) 292 return res; 293 294 /* Make kernel writes synchronous */ 295 wb = ps3flash_writeback(ps3flash_dev); 296 if (wb) 297 return wb; 298 299 return res; 300 } 301 302 static int ps3flash_flush(struct file *file, fl_owner_t id) 303 { 304 return ps3flash_writeback(ps3flash_dev); 305 } 306 307 static int ps3flash_fsync(struct file *file, struct dentry *dentry, 308 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