cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ps3vram.c (22315B)


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