ps3flash.c 11 KB

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