Merge branch 'for-2.6.30' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[pandora-kernel.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(struct file *file, char __user *buf, size_t count,
108                              loff_t *pos)
109 {
110         struct ps3_storage_device *dev = ps3flash_dev;
111         struct ps3flash_private *priv = dev->sbd.core.driver_data;
112         u64 size, start_sector, end_sector, offset;
113         ssize_t sectors_read;
114         size_t remaining, n;
115
116         dev_dbg(&dev->sbd.core,
117                 "%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
118                 __func__, __LINE__, count, *pos, buf);
119
120         size = dev->regions[dev->region_idx].size*dev->blk_size;
121         if (*pos >= size || !count)
122                 return 0;
123
124         if (*pos + count > size) {
125                 dev_dbg(&dev->sbd.core,
126                         "%s:%u Truncating count from %zu to %llu\n", __func__,
127                         __LINE__, count, size - *pos);
128                 count = size - *pos;
129         }
130
131         start_sector = *pos / dev->blk_size;
132         offset = *pos % dev->blk_size;
133         end_sector = DIV_ROUND_UP(*pos + count, dev->blk_size);
134
135         remaining = count;
136         do {
137                 mutex_lock(&priv->mutex);
138
139                 sectors_read = ps3flash_read_sectors(dev, start_sector,
140                                                      end_sector-start_sector,
141                                                      0);
142                 if (sectors_read < 0) {
143                         mutex_unlock(&priv->mutex);
144                         goto fail;
145                 }
146
147                 n = min_t(u64, remaining, sectors_read*dev->blk_size-offset);
148                 dev_dbg(&dev->sbd.core,
149                         "%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
150                         __func__, __LINE__, n, dev->bounce_buf+offset, buf);
151                 if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
152                         mutex_unlock(&priv->mutex);
153                         sectors_read = -EFAULT;
154                         goto fail;
155                 }
156
157                 mutex_unlock(&priv->mutex);
158
159                 *pos += n;
160                 buf += n;
161                 remaining -= n;
162                 start_sector += sectors_read;
163                 offset = 0;
164         } while (remaining > 0);
165
166         return count;
167
168 fail:
169         return sectors_read;
170 }
171
172 static ssize_t ps3flash_write(struct file *file, const char __user *buf,
173                               size_t count, loff_t *pos)
174 {
175         struct ps3_storage_device *dev = ps3flash_dev;
176         struct ps3flash_private *priv = dev->sbd.core.driver_data;
177         u64 size, chunk_sectors, start_write_sector, end_write_sector,
178             end_read_sector, start_read_sector, head, tail, offset;
179         ssize_t res;
180         size_t remaining, n;
181         unsigned int sec_off;
182
183         dev_dbg(&dev->sbd.core,
184                 "%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
185                 __func__, __LINE__, count, *pos, buf);
186
187         size = dev->regions[dev->region_idx].size*dev->blk_size;
188         if (*pos >= size || !count)
189                 return 0;
190
191         if (*pos + count > size) {
192                 dev_dbg(&dev->sbd.core,
193                         "%s:%u Truncating count from %zu to %llu\n", __func__,
194                         __LINE__, count, size - *pos);
195                 count = size - *pos;
196         }
197
198         chunk_sectors = dev->bounce_size / dev->blk_size;
199
200         start_write_sector = *pos / dev->bounce_size * chunk_sectors;
201         offset = *pos % dev->bounce_size;
202         end_write_sector = DIV_ROUND_UP(*pos + count, dev->bounce_size) *
203                            chunk_sectors;
204
205         end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
206         start_read_sector = (*pos + count) / dev->blk_size;
207
208         /*
209          * As we have to write in 256 KiB chunks, while we can read in blk_size
210          * (usually 512 bytes) chunks, we perform the following steps:
211          *   1. Read from start_write_sector to end_read_sector ("head")
212          *   2. Read from start_read_sector to end_write_sector ("tail")
213          *   3. Copy data to buffer
214          *   4. Write from start_write_sector to end_write_sector
215          * All of this is complicated by using only one 256 KiB bounce buffer.
216          */
217
218         head = end_read_sector - start_write_sector;
219         tail = end_write_sector - start_read_sector;
220
221         remaining = count;
222         do {
223                 mutex_lock(&priv->mutex);
224
225                 if (end_read_sector >= start_read_sector) {
226                         /* Merge head and tail */
227                         dev_dbg(&dev->sbd.core,
228                                 "Merged head and tail: %llu sectors at %llu\n",
229                                 chunk_sectors, start_write_sector);
230                         res = ps3flash_read_sectors(dev, start_write_sector,
231                                                     chunk_sectors, 0);
232                         if (res < 0)
233                                 goto fail;
234                 } else {
235                         if (head) {
236                                 /* Read head */
237                                 dev_dbg(&dev->sbd.core,
238                                         "head: %llu sectors at %llu\n", head,
239                                         start_write_sector);
240                                 res = ps3flash_read_sectors(dev,
241                                                             start_write_sector,
242                                                             head, 0);
243                                 if (res < 0)
244                                         goto fail;
245                         }
246                         if (start_read_sector <
247                             start_write_sector+chunk_sectors) {
248                                 /* Read tail */
249                                 dev_dbg(&dev->sbd.core,
250                                         "tail: %llu sectors at %llu\n", tail,
251                                         start_read_sector);
252                                 sec_off = start_read_sector-start_write_sector;
253                                 res = ps3flash_read_sectors(dev,
254                                                             start_read_sector,
255                                                             tail, sec_off);
256                                 if (res < 0)
257                                         goto fail;
258                         }
259                 }
260
261                 n = min_t(u64, remaining, dev->bounce_size-offset);
262                 dev_dbg(&dev->sbd.core,
263                         "%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
264                         __func__, __LINE__, n, buf, dev->bounce_buf+offset);
265                 if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
266                         res = -EFAULT;
267                         goto fail;
268                 }
269
270                 res = ps3flash_write_chunk(dev, start_write_sector);
271                 if (res < 0)
272                         goto fail;
273
274                 mutex_unlock(&priv->mutex);
275
276                 *pos += n;
277                 buf += n;
278                 remaining -= n;
279                 start_write_sector += chunk_sectors;
280                 head = 0;
281                 offset = 0;
282         } while (remaining > 0);
283
284         return count;
285
286 fail:
287         mutex_unlock(&priv->mutex);
288         return res;
289 }
290
291
292 static irqreturn_t ps3flash_interrupt(int irq, void *data)
293 {
294         struct ps3_storage_device *dev = data;
295         int res;
296         u64 tag, status;
297
298         res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
299
300         if (tag != dev->tag)
301                 dev_err(&dev->sbd.core,
302                         "%s:%u: tag mismatch, got %llx, expected %llx\n",
303                         __func__, __LINE__, tag, dev->tag);
304
305         if (res) {
306                 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
307                         __func__, __LINE__, res, status);
308         } else {
309                 dev->lv1_status = status;
310                 complete(&dev->done);
311         }
312         return IRQ_HANDLED;
313 }
314
315
316 static const struct file_operations ps3flash_fops = {
317         .owner  = THIS_MODULE,
318         .llseek = ps3flash_llseek,
319         .read   = ps3flash_read,
320         .write  = ps3flash_write,
321 };
322
323 static struct miscdevice ps3flash_misc = {
324         .minor  = MISC_DYNAMIC_MINOR,
325         .name   = DEVICE_NAME,
326         .fops   = &ps3flash_fops,
327 };
328
329 static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
330 {
331         struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
332         struct ps3flash_private *priv;
333         int error;
334         unsigned long tmp;
335
336         tmp = dev->regions[dev->region_idx].start*dev->blk_size;
337         if (tmp % FLASH_BLOCK_SIZE) {
338                 dev_err(&dev->sbd.core,
339                         "%s:%u region start %lu is not aligned\n", __func__,
340                         __LINE__, tmp);
341                 return -EINVAL;
342         }
343         tmp = dev->regions[dev->region_idx].size*dev->blk_size;
344         if (tmp % FLASH_BLOCK_SIZE) {
345                 dev_err(&dev->sbd.core,
346                         "%s:%u region size %lu is not aligned\n", __func__,
347                         __LINE__, tmp);
348                 return -EINVAL;
349         }
350
351         /* use static buffer, kmalloc cannot allocate 256 KiB */
352         if (!ps3flash_bounce_buffer.address)
353                 return -ENODEV;
354
355         if (ps3flash_dev) {
356                 dev_err(&dev->sbd.core,
357                         "Only one FLASH device is supported\n");
358                 return -EBUSY;
359         }
360
361         ps3flash_dev = dev;
362
363         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
364         if (!priv) {
365                 error = -ENOMEM;
366                 goto fail;
367         }
368
369         dev->sbd.core.driver_data = priv;
370         mutex_init(&priv->mutex);
371
372         dev->bounce_size = ps3flash_bounce_buffer.size;
373         dev->bounce_buf = ps3flash_bounce_buffer.address;
374
375         error = ps3stor_setup(dev, ps3flash_interrupt);
376         if (error)
377                 goto fail_free_priv;
378
379         ps3flash_misc.parent = &dev->sbd.core;
380         error = misc_register(&ps3flash_misc);
381         if (error) {
382                 dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
383                         __func__, __LINE__, error);
384                 goto fail_teardown;
385         }
386
387         dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
388                  __func__, __LINE__, ps3flash_misc.minor);
389         return 0;
390
391 fail_teardown:
392         ps3stor_teardown(dev);
393 fail_free_priv:
394         kfree(priv);
395         dev->sbd.core.driver_data = NULL;
396 fail:
397         ps3flash_dev = NULL;
398         return error;
399 }
400
401 static int ps3flash_remove(struct ps3_system_bus_device *_dev)
402 {
403         struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
404
405         misc_deregister(&ps3flash_misc);
406         ps3stor_teardown(dev);
407         kfree(dev->sbd.core.driver_data);
408         dev->sbd.core.driver_data = NULL;
409         ps3flash_dev = NULL;
410         return 0;
411 }
412
413
414 static struct ps3_system_bus_driver ps3flash = {
415         .match_id       = PS3_MATCH_ID_STOR_FLASH,
416         .core.name      = DEVICE_NAME,
417         .core.owner     = THIS_MODULE,
418         .probe          = ps3flash_probe,
419         .remove         = ps3flash_remove,
420         .shutdown       = ps3flash_remove,
421 };
422
423
424 static int __init ps3flash_init(void)
425 {
426         return ps3_system_bus_driver_register(&ps3flash);
427 }
428
429 static void __exit ps3flash_exit(void)
430 {
431         ps3_system_bus_driver_unregister(&ps3flash);
432 }
433
434 module_init(ps3flash_init);
435 module_exit(ps3flash_exit);
436
437 MODULE_LICENSE("GPL");
438 MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver");
439 MODULE_AUTHOR("Sony Corporation");
440 MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);