~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/block/ps3vram.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ps3vram - Use extra PS3 video ram as MTD block device.
 
3
 *
 
4
 * Copyright 2009 Sony Corporation
 
5
 *
 
6
 * Based on the MTD ps3vram driver, which is
 
7
 * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com>
 
8
 * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr>
 
9
 */
 
10
 
 
11
#include <linux/blkdev.h>
 
12
#include <linux/delay.h>
 
13
#include <linux/module.h>
 
14
#include <linux/proc_fs.h>
 
15
#include <linux/seq_file.h>
 
16
#include <linux/slab.h>
 
17
 
 
18
#include <asm/cell-regs.h>
 
19
#include <asm/firmware.h>
 
20
#include <asm/lv1call.h>
 
21
#include <asm/ps3.h>
 
22
#include <asm/ps3gpu.h>
 
23
 
 
24
 
 
25
#define DEVICE_NAME             "ps3vram"
 
26
 
 
27
 
 
28
#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */
 
29
#define XDR_IOIF 0x0c000000
 
30
 
 
31
#define FIFO_BASE XDR_IOIF
 
32
#define FIFO_SIZE (64 * 1024)
 
33
 
 
34
#define DMA_PAGE_SIZE (4 * 1024)
 
35
 
 
36
#define CACHE_PAGE_SIZE (256 * 1024)
 
37
#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE)
 
38
 
 
39
#define CACHE_OFFSET CACHE_PAGE_SIZE
 
40
#define FIFO_OFFSET 0
 
41
 
 
42
#define CTRL_PUT 0x10
 
43
#define CTRL_GET 0x11
 
44
#define CTRL_TOP 0x15
 
45
 
 
46
#define UPLOAD_SUBCH    1
 
47
#define DOWNLOAD_SUBCH  2
 
48
 
 
49
#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN    0x0000030c
 
50
#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY       0x00000104
 
51
 
 
52
#define CACHE_PAGE_PRESENT 1
 
53
#define CACHE_PAGE_DIRTY   2
 
54
 
 
55
struct ps3vram_tag {
 
56
        unsigned int address;
 
57
        unsigned int flags;
 
58
};
 
59
 
 
60
struct ps3vram_cache {
 
61
        unsigned int page_count;
 
62
        unsigned int page_size;
 
63
        struct ps3vram_tag *tags;
 
64
        unsigned int hit;
 
65
        unsigned int miss;
 
66
};
 
67
 
 
68
struct ps3vram_priv {
 
69
        struct request_queue *queue;
 
70
        struct gendisk *gendisk;
 
71
 
 
72
        u64 size;
 
73
 
 
74
        u64 memory_handle;
 
75
        u64 context_handle;
 
76
        u32 *ctrl;
 
77
        void *reports;
 
78
        u8 *xdr_buf;
 
79
 
 
80
        u32 *fifo_base;
 
81
        u32 *fifo_ptr;
 
82
 
 
83
        struct ps3vram_cache cache;
 
84
 
 
85
        spinlock_t lock;        /* protecting list of bios */
 
86
        struct bio_list list;
 
87
};
 
88
 
 
89
 
 
90
static int ps3vram_major;
 
91
 
 
92
 
 
93
static const struct block_device_operations ps3vram_fops = {
 
94
        .owner          = THIS_MODULE,
 
95
};
 
96
 
 
97
 
 
98
#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */
 
99
#define DMA_NOTIFIER_OFFSET_BASE 0x1000     /* first DMA notifier offset */
 
100
#define DMA_NOTIFIER_SIZE        0x40
 
101
#define NOTIFIER 7      /* notifier used for completion report */
 
102
 
 
103
static char *size = "256M";
 
104
module_param(size, charp, 0);
 
105
MODULE_PARM_DESC(size, "memory size");
 
106
 
 
107
static u32 *ps3vram_get_notifier(void *reports, int notifier)
 
108
{
 
109
        return reports + DMA_NOTIFIER_OFFSET_BASE +
 
110
               DMA_NOTIFIER_SIZE * notifier;
 
111
}
 
112
 
 
113
static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev)
 
114
{
 
115
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
116
        u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
 
117
        int i;
 
118
 
 
119
        for (i = 0; i < 4; i++)
 
120
                notify[i] = 0xffffffff;
 
121
}
 
122
 
 
123
static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev,
 
124
                                 unsigned int timeout_ms)
 
125
{
 
126
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
127
        u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
 
128
        unsigned long timeout;
 
129
 
 
130
        for (timeout = 20; timeout; timeout--) {
 
131
                if (!notify[3])
 
132
                        return 0;
 
133
                udelay(10);
 
134
        }
 
135
 
 
136
        timeout = jiffies + msecs_to_jiffies(timeout_ms);
 
137
 
 
138
        do {
 
139
                if (!notify[3])
 
140
                        return 0;
 
141
                msleep(1);
 
142
        } while (time_before(jiffies, timeout));
 
143
 
 
144
        return -ETIMEDOUT;
 
145
}
 
146
 
 
147
static void ps3vram_init_ring(struct ps3_system_bus_device *dev)
 
148
{
 
149
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
150
 
 
151
        priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
 
152
        priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET;
 
153
}
 
154
 
 
155
static int ps3vram_wait_ring(struct ps3_system_bus_device *dev,
 
156
                             unsigned int timeout_ms)
 
157
{
 
158
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
159
        unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
 
160
 
 
161
        do {
 
162
                if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET])
 
163
                        return 0;
 
164
                msleep(1);
 
165
        } while (time_before(jiffies, timeout));
 
166
 
 
167
        dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n",
 
168
                 priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET],
 
169
                 priv->ctrl[CTRL_TOP]);
 
170
 
 
171
        return -ETIMEDOUT;
 
172
}
 
173
 
 
174
static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data)
 
175
{
 
176
        *(priv->fifo_ptr)++ = data;
 
177
}
 
178
 
 
179
static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, u32 tag,
 
180
                               u32 size)
 
181
{
 
182
        ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag);
 
183
}
 
184
 
 
185
static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev)
 
186
{
 
187
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
188
        int status;
 
189
 
 
190
        ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
 
191
 
 
192
        priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
 
193
 
 
194
        /* asking the HV for a blit will kick the FIFO */
 
195
        status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
 
196
        if (status)
 
197
                dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n",
 
198
                        __func__, status);
 
199
 
 
200
        priv->fifo_ptr = priv->fifo_base;
 
201
}
 
202
 
 
203
static void ps3vram_fire_ring(struct ps3_system_bus_device *dev)
 
204
{
 
205
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
206
        int status;
 
207
 
 
208
        mutex_lock(&ps3_gpu_mutex);
 
209
 
 
210
        priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET +
 
211
                               (priv->fifo_ptr - priv->fifo_base) * sizeof(u32);
 
212
 
 
213
        /* asking the HV for a blit will kick the FIFO */
 
214
        status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
 
215
        if (status)
 
216
                dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n",
 
217
                        __func__, status);
 
218
 
 
219
        if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) >
 
220
            FIFO_SIZE - 1024) {
 
221
                dev_dbg(&dev->core, "FIFO full, rewinding\n");
 
222
                ps3vram_wait_ring(dev, 200);
 
223
                ps3vram_rewind_ring(dev);
 
224
        }
 
225
 
 
226
        mutex_unlock(&ps3_gpu_mutex);
 
227
}
 
228
 
 
229
static void ps3vram_bind(struct ps3_system_bus_device *dev)
 
230
{
 
231
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
232
 
 
233
        ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1);
 
234
        ps3vram_out_ring(priv, 0x31337303);
 
235
        ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3);
 
236
        ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
 
237
        ps3vram_out_ring(priv, 0xfeed0001);     /* DMA system RAM instance */
 
238
        ps3vram_out_ring(priv, 0xfeed0000);     /* DMA video RAM instance */
 
239
 
 
240
        ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1);
 
241
        ps3vram_out_ring(priv, 0x3137c0de);
 
242
        ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3);
 
243
        ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
 
244
        ps3vram_out_ring(priv, 0xfeed0000);     /* DMA video RAM instance */
 
245
        ps3vram_out_ring(priv, 0xfeed0001);     /* DMA system RAM instance */
 
246
 
 
247
        ps3vram_fire_ring(dev);
 
248
}
 
249
 
 
250
static int ps3vram_upload(struct ps3_system_bus_device *dev,
 
251
                          unsigned int src_offset, unsigned int dst_offset,
 
252
                          int len, int count)
 
253
{
 
254
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
255
 
 
256
        ps3vram_begin_ring(priv, UPLOAD_SUBCH,
 
257
                           NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
 
258
        ps3vram_out_ring(priv, XDR_IOIF + src_offset);
 
259
        ps3vram_out_ring(priv, dst_offset);
 
260
        ps3vram_out_ring(priv, len);
 
261
        ps3vram_out_ring(priv, len);
 
262
        ps3vram_out_ring(priv, len);
 
263
        ps3vram_out_ring(priv, count);
 
264
        ps3vram_out_ring(priv, (1 << 8) | 1);
 
265
        ps3vram_out_ring(priv, 0);
 
266
 
 
267
        ps3vram_notifier_reset(dev);
 
268
        ps3vram_begin_ring(priv, UPLOAD_SUBCH,
 
269
                           NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
 
270
        ps3vram_out_ring(priv, 0);
 
271
        ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1);
 
272
        ps3vram_out_ring(priv, 0);
 
273
        ps3vram_fire_ring(dev);
 
274
        if (ps3vram_notifier_wait(dev, 200) < 0) {
 
275
                dev_warn(&dev->core, "%s: Notifier timeout\n", __func__);
 
276
                return -1;
 
277
        }
 
278
 
 
279
        return 0;
 
280
}
 
281
 
 
282
static int ps3vram_download(struct ps3_system_bus_device *dev,
 
283
                            unsigned int src_offset, unsigned int dst_offset,
 
284
                            int len, int count)
 
285
{
 
286
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
287
 
 
288
        ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
 
289
                           NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
 
290
        ps3vram_out_ring(priv, src_offset);
 
291
        ps3vram_out_ring(priv, XDR_IOIF + dst_offset);
 
292
        ps3vram_out_ring(priv, len);
 
293
        ps3vram_out_ring(priv, len);
 
294
        ps3vram_out_ring(priv, len);
 
295
        ps3vram_out_ring(priv, count);
 
296
        ps3vram_out_ring(priv, (1 << 8) | 1);
 
297
        ps3vram_out_ring(priv, 0);
 
298
 
 
299
        ps3vram_notifier_reset(dev);
 
300
        ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
 
301
                           NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
 
302
        ps3vram_out_ring(priv, 0);
 
303
        ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1);
 
304
        ps3vram_out_ring(priv, 0);
 
305
        ps3vram_fire_ring(dev);
 
306
        if (ps3vram_notifier_wait(dev, 200) < 0) {
 
307
                dev_warn(&dev->core, "%s: Notifier timeout\n", __func__);
 
308
                return -1;
 
309
        }
 
310
 
 
311
        return 0;
 
312
}
 
313
 
 
314
static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry)
 
315
{
 
316
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
317
        struct ps3vram_cache *cache = &priv->cache;
 
318
 
 
319
        if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY))
 
320
                return;
 
321
 
 
322
        dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry,
 
323
                cache->tags[entry].address);
 
324
        if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size,
 
325
                           cache->tags[entry].address, DMA_PAGE_SIZE,
 
326
                           cache->page_size / DMA_PAGE_SIZE) < 0) {
 
327
                dev_err(&dev->core,
 
328
                        "Failed to upload from 0x%x to " "0x%x size 0x%x\n",
 
329
                        entry * cache->page_size, cache->tags[entry].address,
 
330
                        cache->page_size);
 
331
        }
 
332
        cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY;
 
333
}
 
334
 
 
335
static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry,
 
336
                               unsigned int address)
 
337
{
 
338
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
339
        struct ps3vram_cache *cache = &priv->cache;
 
340
 
 
341
        dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address);
 
342
        if (ps3vram_download(dev, address,
 
343
                             CACHE_OFFSET + entry * cache->page_size,
 
344
                             DMA_PAGE_SIZE,
 
345
                             cache->page_size / DMA_PAGE_SIZE) < 0) {
 
346
                dev_err(&dev->core,
 
347
                        "Failed to download from 0x%x to 0x%x size 0x%x\n",
 
348
                        address, entry * cache->page_size, cache->page_size);
 
349
        }
 
350
 
 
351
        cache->tags[entry].address = address;
 
352
        cache->tags[entry].flags |= CACHE_PAGE_PRESENT;
 
353
}
 
354
 
 
355
 
 
356
static void ps3vram_cache_flush(struct ps3_system_bus_device *dev)
 
357
{
 
358
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
359
        struct ps3vram_cache *cache = &priv->cache;
 
360
        int i;
 
361
 
 
362
        dev_dbg(&dev->core, "FLUSH\n");
 
363
        for (i = 0; i < cache->page_count; i++) {
 
364
                ps3vram_cache_evict(dev, i);
 
365
                cache->tags[i].flags = 0;
 
366
        }
 
367
}
 
368
 
 
369
static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev,
 
370
                                        loff_t address)
 
371
{
 
372
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
373
        struct ps3vram_cache *cache = &priv->cache;
 
374
        unsigned int base;
 
375
        unsigned int offset;
 
376
        int i;
 
377
        static int counter;
 
378
 
 
379
        offset = (unsigned int) (address & (cache->page_size - 1));
 
380
        base = (unsigned int) (address - offset);
 
381
 
 
382
        /* fully associative check */
 
383
        for (i = 0; i < cache->page_count; i++) {
 
384
                if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) &&
 
385
                    cache->tags[i].address == base) {
 
386
                        cache->hit++;
 
387
                        dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i,
 
388
                                cache->tags[i].address);
 
389
                        return i;
 
390
                }
 
391
        }
 
392
 
 
393
        /* choose a random entry */
 
394
        i = (jiffies + (counter++)) % cache->page_count;
 
395
        dev_dbg(&dev->core, "Using entry %d\n", i);
 
396
 
 
397
        ps3vram_cache_evict(dev, i);
 
398
        ps3vram_cache_load(dev, i, base);
 
399
 
 
400
        cache->miss++;
 
401
        return i;
 
402
}
 
403
 
 
404
static int ps3vram_cache_init(struct ps3_system_bus_device *dev)
 
405
{
 
406
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
407
 
 
408
        priv->cache.page_count = CACHE_PAGE_COUNT;
 
409
        priv->cache.page_size = CACHE_PAGE_SIZE;
 
410
        priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) *
 
411
                                   CACHE_PAGE_COUNT, GFP_KERNEL);
 
412
        if (priv->cache.tags == NULL) {
 
413
                dev_err(&dev->core, "Could not allocate cache tags\n");
 
414
                return -ENOMEM;
 
415
        }
 
416
 
 
417
        dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n",
 
418
                CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024);
 
419
 
 
420
        return 0;
 
421
}
 
422
 
 
423
static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev)
 
424
{
 
425
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
426
 
 
427
        ps3vram_cache_flush(dev);
 
428
        kfree(priv->cache.tags);
 
429
}
 
430
 
 
431
static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
 
432
                        size_t len, size_t *retlen, u_char *buf)
 
433
{
 
434
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
435
        unsigned int cached, count;
 
436
 
 
437
        dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__,
 
438
                (unsigned int)from, len);
 
439
 
 
440
        if (from >= priv->size)
 
441
                return -EIO;
 
442
 
 
443
        if (len > priv->size - from)
 
444
                len = priv->size - from;
 
445
 
 
446
        /* Copy from vram to buf */
 
447
        count = len;
 
448
        while (count) {
 
449
                unsigned int offset, avail;
 
450
                unsigned int entry;
 
451
 
 
452
                offset = (unsigned int) (from & (priv->cache.page_size - 1));
 
453
                avail  = priv->cache.page_size - offset;
 
454
 
 
455
                entry = ps3vram_cache_match(dev, from);
 
456
                cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
 
457
 
 
458
                dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x "
 
459
                        "avail=%08x count=%08x\n", __func__,
 
460
                        (unsigned int)from, cached, offset, avail, count);
 
461
 
 
462
                if (avail > count)
 
463
                        avail = count;
 
464
                memcpy(buf, priv->xdr_buf + cached, avail);
 
465
 
 
466
                buf += avail;
 
467
                count -= avail;
 
468
                from += avail;
 
469
        }
 
470
 
 
471
        *retlen = len;
 
472
        return 0;
 
473
}
 
474
 
 
475
static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
 
476
                         size_t len, size_t *retlen, const u_char *buf)
 
477
{
 
478
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
479
        unsigned int cached, count;
 
480
 
 
481
        if (to >= priv->size)
 
482
                return -EIO;
 
483
 
 
484
        if (len > priv->size - to)
 
485
                len = priv->size - to;
 
486
 
 
487
        /* Copy from buf to vram */
 
488
        count = len;
 
489
        while (count) {
 
490
                unsigned int offset, avail;
 
491
                unsigned int entry;
 
492
 
 
493
                offset = (unsigned int) (to & (priv->cache.page_size - 1));
 
494
                avail  = priv->cache.page_size - offset;
 
495
 
 
496
                entry = ps3vram_cache_match(dev, to);
 
497
                cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
 
498
 
 
499
                dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x "
 
500
                        "avail=%08x count=%08x\n", __func__, (unsigned int)to,
 
501
                        cached, offset, avail, count);
 
502
 
 
503
                if (avail > count)
 
504
                        avail = count;
 
505
                memcpy(priv->xdr_buf + cached, buf, avail);
 
506
 
 
507
                priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;
 
508
 
 
509
                buf += avail;
 
510
                count -= avail;
 
511
                to += avail;
 
512
        }
 
513
 
 
514
        *retlen = len;
 
515
        return 0;
 
516
}
 
517
 
 
518
static int ps3vram_proc_show(struct seq_file *m, void *v)
 
519
{
 
520
        struct ps3vram_priv *priv = m->private;
 
521
 
 
522
        seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss);
 
523
        return 0;
 
524
}
 
525
 
 
526
static int ps3vram_proc_open(struct inode *inode, struct file *file)
 
527
{
 
528
        return single_open(file, ps3vram_proc_show, PDE(inode)->data);
 
529
}
 
530
 
 
531
static const struct file_operations ps3vram_proc_fops = {
 
532
        .owner          = THIS_MODULE,
 
533
        .open           = ps3vram_proc_open,
 
534
        .read           = seq_read,
 
535
        .llseek         = seq_lseek,
 
536
        .release        = single_release,
 
537
};
 
538
 
 
539
static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
 
540
{
 
541
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
542
        struct proc_dir_entry *pde;
 
543
 
 
544
        pde = proc_create_data(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops,
 
545
                               priv);
 
546
        if (!pde)
 
547
                dev_warn(&dev->core, "failed to create /proc entry\n");
 
548
}
 
549
 
 
550
static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
 
551
                                  struct bio *bio)
 
552
{
 
553
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
554
        int write = bio_data_dir(bio) == WRITE;
 
555
        const char *op = write ? "write" : "read";
 
556
        loff_t offset = bio->bi_sector << 9;
 
557
        int error = 0;
 
558
        struct bio_vec *bvec;
 
559
        unsigned int i;
 
560
        struct bio *next;
 
561
 
 
562
        bio_for_each_segment(bvec, bio, i) {
 
563
                /* PS3 is ppc64, so we don't handle highmem */
 
564
                char *ptr = page_address(bvec->bv_page) + bvec->bv_offset;
 
565
                size_t len = bvec->bv_len, retlen;
 
566
 
 
567
                dev_dbg(&dev->core, "    %s %zu bytes at offset %llu\n", op,
 
568
                        len, offset);
 
569
                if (write)
 
570
                        error = ps3vram_write(dev, offset, len, &retlen, ptr);
 
571
                else
 
572
                        error = ps3vram_read(dev, offset, len, &retlen, ptr);
 
573
 
 
574
                if (error) {
 
575
                        dev_err(&dev->core, "%s failed\n", op);
 
576
                        goto out;
 
577
                }
 
578
 
 
579
                if (retlen != len) {
 
580
                        dev_err(&dev->core, "Short %s\n", op);
 
581
                        error = -EIO;
 
582
                        goto out;
 
583
                }
 
584
 
 
585
                offset += len;
 
586
        }
 
587
 
 
588
        dev_dbg(&dev->core, "%s completed\n", op);
 
589
 
 
590
out:
 
591
        spin_lock_irq(&priv->lock);
 
592
        bio_list_pop(&priv->list);
 
593
        next = bio_list_peek(&priv->list);
 
594
        spin_unlock_irq(&priv->lock);
 
595
 
 
596
        bio_endio(bio, error);
 
597
        return next;
 
598
}
 
599
 
 
600
static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
 
601
{
 
602
        struct ps3_system_bus_device *dev = q->queuedata;
 
603
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
604
        int busy;
 
605
 
 
606
        dev_dbg(&dev->core, "%s\n", __func__);
 
607
 
 
608
        spin_lock_irq(&priv->lock);
 
609
        busy = !bio_list_empty(&priv->list);
 
610
        bio_list_add(&priv->list, bio);
 
611
        spin_unlock_irq(&priv->lock);
 
612
 
 
613
        if (busy)
 
614
                return;
 
615
 
 
616
        do {
 
617
                bio = ps3vram_do_bio(dev, bio);
 
618
        } while (bio);
 
619
}
 
620
 
 
621
static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
 
622
{
 
623
        struct ps3vram_priv *priv;
 
624
        int error, status;
 
625
        struct request_queue *queue;
 
626
        struct gendisk *gendisk;
 
627
        u64 ddr_size, ddr_lpar, ctrl_lpar, info_lpar, reports_lpar,
 
628
            reports_size, xdr_lpar;
 
629
        char *rest;
 
630
 
 
631
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 
632
        if (!priv) {
 
633
                error = -ENOMEM;
 
634
                goto fail;
 
635
        }
 
636
 
 
637
        spin_lock_init(&priv->lock);
 
638
        bio_list_init(&priv->list);
 
639
        ps3_system_bus_set_drvdata(dev, priv);
 
640
 
 
641
        /* Allocate XDR buffer (1MiB aligned) */
 
642
        priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL,
 
643
                get_order(XDR_BUF_SIZE));
 
644
        if (priv->xdr_buf == NULL) {
 
645
                dev_err(&dev->core, "Could not allocate XDR buffer\n");
 
646
                error = -ENOMEM;
 
647
                goto fail_free_priv;
 
648
        }
 
649
 
 
650
        /* Put FIFO at begginning of XDR buffer */
 
651
        priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET);
 
652
        priv->fifo_ptr = priv->fifo_base;
 
653
 
 
654
        /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */
 
655
        if (ps3_open_hv_device(dev)) {
 
656
                dev_err(&dev->core, "ps3_open_hv_device failed\n");
 
657
                error = -EAGAIN;
 
658
                goto out_free_xdr_buf;
 
659
        }
 
660
 
 
661
        /* Request memory */
 
662
        status = -1;
 
663
        ddr_size = ALIGN(memparse(size, &rest), 1024*1024);
 
664
        if (!ddr_size) {
 
665
                dev_err(&dev->core, "Specified size is too small\n");
 
666
                error = -EINVAL;
 
667
                goto out_close_gpu;
 
668
        }
 
669
 
 
670
        while (ddr_size > 0) {
 
671
                status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0,
 
672
                                                 &priv->memory_handle,
 
673
                                                 &ddr_lpar);
 
674
                if (!status)
 
675
                        break;
 
676
                ddr_size -= 1024*1024;
 
677
        }
 
678
        if (status) {
 
679
                dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n",
 
680
                        status);
 
681
                error = -ENOMEM;
 
682
                goto out_close_gpu;
 
683
        }
 
684
 
 
685
        /* Request context */
 
686
        status = lv1_gpu_context_allocate(priv->memory_handle, 0,
 
687
                                          &priv->context_handle, &ctrl_lpar,
 
688
                                          &info_lpar, &reports_lpar,
 
689
                                          &reports_size);
 
690
        if (status) {
 
691
                dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n",
 
692
                        status);
 
693
                error = -ENOMEM;
 
694
                goto out_free_memory;
 
695
        }
 
696
 
 
697
        /* Map XDR buffer to RSX */
 
698
        xdr_lpar = ps3_mm_phys_to_lpar(__pa(priv->xdr_buf));
 
699
        status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
 
700
                                       xdr_lpar, XDR_BUF_SIZE,
 
701
                                       CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
 
702
                                       CBE_IOPTE_M);
 
703
        if (status) {
 
704
                dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n",
 
705
                        status);
 
706
                error = -ENOMEM;
 
707
                goto out_free_context;
 
708
        }
 
709
 
 
710
        priv->ctrl = ioremap(ctrl_lpar, 64 * 1024);
 
711
        if (!priv->ctrl) {
 
712
                dev_err(&dev->core, "ioremap CTRL failed\n");
 
713
                error = -ENOMEM;
 
714
                goto out_unmap_context;
 
715
        }
 
716
 
 
717
        priv->reports = ioremap(reports_lpar, reports_size);
 
718
        if (!priv->reports) {
 
719
                dev_err(&dev->core, "ioremap REPORTS failed\n");
 
720
                error = -ENOMEM;
 
721
                goto out_unmap_ctrl;
 
722
        }
 
723
 
 
724
        mutex_lock(&ps3_gpu_mutex);
 
725
        ps3vram_init_ring(dev);
 
726
        mutex_unlock(&ps3_gpu_mutex);
 
727
 
 
728
        priv->size = ddr_size;
 
729
 
 
730
        ps3vram_bind(dev);
 
731
 
 
732
        mutex_lock(&ps3_gpu_mutex);
 
733
        error = ps3vram_wait_ring(dev, 100);
 
734
        mutex_unlock(&ps3_gpu_mutex);
 
735
        if (error < 0) {
 
736
                dev_err(&dev->core, "Failed to initialize channels\n");
 
737
                error = -ETIMEDOUT;
 
738
                goto out_unmap_reports;
 
739
        }
 
740
 
 
741
        ps3vram_cache_init(dev);
 
742
        ps3vram_proc_init(dev);
 
743
 
 
744
        queue = blk_alloc_queue(GFP_KERNEL);
 
745
        if (!queue) {
 
746
                dev_err(&dev->core, "blk_alloc_queue failed\n");
 
747
                error = -ENOMEM;
 
748
                goto out_cache_cleanup;
 
749
        }
 
750
 
 
751
        priv->queue = queue;
 
752
        queue->queuedata = dev;
 
753
        blk_queue_make_request(queue, ps3vram_make_request);
 
754
        blk_queue_max_segments(queue, BLK_MAX_SEGMENTS);
 
755
        blk_queue_max_segment_size(queue, BLK_MAX_SEGMENT_SIZE);
 
756
        blk_queue_max_hw_sectors(queue, BLK_SAFE_MAX_SECTORS);
 
757
 
 
758
        gendisk = alloc_disk(1);
 
759
        if (!gendisk) {
 
760
                dev_err(&dev->core, "alloc_disk failed\n");
 
761
                error = -ENOMEM;
 
762
                goto fail_cleanup_queue;
 
763
        }
 
764
 
 
765
        priv->gendisk = gendisk;
 
766
        gendisk->major = ps3vram_major;
 
767
        gendisk->first_minor = 0;
 
768
        gendisk->fops = &ps3vram_fops;
 
769
        gendisk->queue = queue;
 
770
        gendisk->private_data = dev;
 
771
        gendisk->driverfs_dev = &dev->core;
 
772
        strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name));
 
773
        set_capacity(gendisk, priv->size >> 9);
 
774
 
 
775
        dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n",
 
776
                 gendisk->disk_name, get_capacity(gendisk) >> 11);
 
777
 
 
778
        add_disk(gendisk);
 
779
        return 0;
 
780
 
 
781
fail_cleanup_queue:
 
782
        blk_cleanup_queue(queue);
 
783
out_cache_cleanup:
 
784
        remove_proc_entry(DEVICE_NAME, NULL);
 
785
        ps3vram_cache_cleanup(dev);
 
786
out_unmap_reports:
 
787
        iounmap(priv->reports);
 
788
out_unmap_ctrl:
 
789
        iounmap(priv->ctrl);
 
790
out_unmap_context:
 
791
        lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, xdr_lpar,
 
792
                              XDR_BUF_SIZE, CBE_IOPTE_M);
 
793
out_free_context:
 
794
        lv1_gpu_context_free(priv->context_handle);
 
795
out_free_memory:
 
796
        lv1_gpu_memory_free(priv->memory_handle);
 
797
out_close_gpu:
 
798
        ps3_close_hv_device(dev);
 
799
out_free_xdr_buf:
 
800
        free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
 
801
fail_free_priv:
 
802
        kfree(priv);
 
803
        ps3_system_bus_set_drvdata(dev, NULL);
 
804
fail:
 
805
        return error;
 
806
}
 
807
 
 
808
static int ps3vram_remove(struct ps3_system_bus_device *dev)
 
809
{
 
810
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
811
 
 
812
        del_gendisk(priv->gendisk);
 
813
        put_disk(priv->gendisk);
 
814
        blk_cleanup_queue(priv->queue);
 
815
        remove_proc_entry(DEVICE_NAME, NULL);
 
816
        ps3vram_cache_cleanup(dev);
 
817
        iounmap(priv->reports);
 
818
        iounmap(priv->ctrl);
 
819
        lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
 
820
                              ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)),
 
821
                              XDR_BUF_SIZE, CBE_IOPTE_M);
 
822
        lv1_gpu_context_free(priv->context_handle);
 
823
        lv1_gpu_memory_free(priv->memory_handle);
 
824
        ps3_close_hv_device(dev);
 
825
        free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
 
826
        kfree(priv);
 
827
        ps3_system_bus_set_drvdata(dev, NULL);
 
828
        return 0;
 
829
}
 
830
 
 
831
static struct ps3_system_bus_driver ps3vram = {
 
832
        .match_id       = PS3_MATCH_ID_GPU,
 
833
        .match_sub_id   = PS3_MATCH_SUB_ID_GPU_RAMDISK,
 
834
        .core.name      = DEVICE_NAME,
 
835
        .core.owner     = THIS_MODULE,
 
836
        .probe          = ps3vram_probe,
 
837
        .remove         = ps3vram_remove,
 
838
        .shutdown       = ps3vram_remove,
 
839
};
 
840
 
 
841
 
 
842
static int __init ps3vram_init(void)
 
843
{
 
844
        int error;
 
845
 
 
846
        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 
847
                return -ENODEV;
 
848
 
 
849
        error = register_blkdev(0, DEVICE_NAME);
 
850
        if (error <= 0) {
 
851
                pr_err("%s: register_blkdev failed %d\n", DEVICE_NAME, error);
 
852
                return error;
 
853
        }
 
854
        ps3vram_major = error;
 
855
 
 
856
        pr_info("%s: registered block device major %d\n", DEVICE_NAME,
 
857
                ps3vram_major);
 
858
 
 
859
        error = ps3_system_bus_driver_register(&ps3vram);
 
860
        if (error)
 
861
                unregister_blkdev(ps3vram_major, DEVICE_NAME);
 
862
 
 
863
        return error;
 
864
}
 
865
 
 
866
static void __exit ps3vram_exit(void)
 
867
{
 
868
        ps3_system_bus_driver_unregister(&ps3vram);
 
869
        unregister_blkdev(ps3vram_major, DEVICE_NAME);
 
870
}
 
871
 
 
872
module_init(ps3vram_init);
 
873
module_exit(ps3vram_exit);
 
874
 
 
875
MODULE_LICENSE("GPL");
 
876
MODULE_DESCRIPTION("PS3 Video RAM Storage Driver");
 
877
MODULE_AUTHOR("Sony Corporation");
 
878
MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK);