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