Lines Matching +full:i +full:- +full:cache +full:- +full:size

1 // SPDX-License-Identifier: GPL-2.0-only
3 * ps3vram - Use extra PS3 video ram as block device.
8 * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com>
19 #include <asm/cell-regs.h>
38 #define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE)
73 u64 size; member
84 struct ps3vram_cache cache; member
98 static char *size = "256M"; variable
99 module_param(size, charp, 0);
100 MODULE_PARM_DESC(size, "memory size");
111 u32 __iomem *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); in ps3vram_notifier_reset()
112 int i; in ps3vram_notifier_reset() local
114 for (i = 0; i < 4; i++) in ps3vram_notifier_reset()
115 iowrite32be(0xffffffff, notify + i); in ps3vram_notifier_reset()
122 u32 __iomem *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); in ps3vram_notifier_wait()
125 for (timeout = 20; timeout; timeout--) { in ps3vram_notifier_wait()
139 return -ETIMEDOUT; in ps3vram_notifier_wait()
146 iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_PUT); in ps3vram_init_ring()
147 iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_GET); in ps3vram_init_ring()
157 if (ioread32be(priv->ctrl + CTRL_PUT) == ioread32be(priv->ctrl + CTRL_GET)) in ps3vram_wait_ring()
162 dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n", in ps3vram_wait_ring()
163 ioread32be(priv->ctrl + CTRL_PUT), ioread32be(priv->ctrl + CTRL_GET), in ps3vram_wait_ring()
164 ioread32be(priv->ctrl + CTRL_TOP)); in ps3vram_wait_ring()
166 return -ETIMEDOUT; in ps3vram_wait_ring()
171 *(priv->fifo_ptr)++ = data; in ps3vram_out_ring()
175 u32 size) in ps3vram_begin_ring() argument
177 ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); in ps3vram_begin_ring()
187 iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_PUT); in ps3vram_rewind_ring()
190 status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0); in ps3vram_rewind_ring()
192 dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n", in ps3vram_rewind_ring()
195 priv->fifo_ptr = priv->fifo_base; in ps3vram_rewind_ring()
205 iowrite32be(FIFO_BASE + FIFO_OFFSET + (priv->fifo_ptr - priv->fifo_base) in ps3vram_fire_ring()
206 * sizeof(u32), priv->ctrl + CTRL_PUT); in ps3vram_fire_ring()
209 status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0); in ps3vram_fire_ring()
211 dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n", in ps3vram_fire_ring()
214 if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > in ps3vram_fire_ring()
215 FIFO_SIZE - 1024) { in ps3vram_fire_ring()
216 dev_dbg(&dev->core, "FIFO full, rewinding\n"); in ps3vram_fire_ring()
270 dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); in ps3vram_upload()
271 return -1; in ps3vram_upload()
302 dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); in ps3vram_download()
303 return -1; in ps3vram_download()
312 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_evict() local
314 if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY)) in ps3vram_cache_evict()
317 dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry, in ps3vram_cache_evict()
318 cache->tags[entry].address); in ps3vram_cache_evict()
319 if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size, in ps3vram_cache_evict()
320 cache->tags[entry].address, DMA_PAGE_SIZE, in ps3vram_cache_evict()
321 cache->page_size / DMA_PAGE_SIZE) < 0) { in ps3vram_cache_evict()
322 dev_err(&dev->core, in ps3vram_cache_evict()
323 "Failed to upload from 0x%x to " "0x%x size 0x%x\n", in ps3vram_cache_evict()
324 entry * cache->page_size, cache->tags[entry].address, in ps3vram_cache_evict()
325 cache->page_size); in ps3vram_cache_evict()
327 cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; in ps3vram_cache_evict()
334 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_load() local
336 dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address); in ps3vram_cache_load()
338 CACHE_OFFSET + entry * cache->page_size, in ps3vram_cache_load()
340 cache->page_size / DMA_PAGE_SIZE) < 0) { in ps3vram_cache_load()
341 dev_err(&dev->core, in ps3vram_cache_load()
342 "Failed to download from 0x%x to 0x%x size 0x%x\n", in ps3vram_cache_load()
343 address, entry * cache->page_size, cache->page_size); in ps3vram_cache_load()
346 cache->tags[entry].address = address; in ps3vram_cache_load()
347 cache->tags[entry].flags |= CACHE_PAGE_PRESENT; in ps3vram_cache_load()
354 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_flush() local
355 int i; in ps3vram_cache_flush() local
357 dev_dbg(&dev->core, "FLUSH\n"); in ps3vram_cache_flush()
358 for (i = 0; i < cache->page_count; i++) { in ps3vram_cache_flush()
359 ps3vram_cache_evict(dev, i); in ps3vram_cache_flush()
360 cache->tags[i].flags = 0; in ps3vram_cache_flush()
368 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_match() local
371 int i; in ps3vram_cache_match() local
374 offset = (unsigned int) (address & (cache->page_size - 1)); in ps3vram_cache_match()
375 base = (unsigned int) (address - offset); in ps3vram_cache_match()
378 for (i = 0; i < cache->page_count; i++) { in ps3vram_cache_match()
379 if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && in ps3vram_cache_match()
380 cache->tags[i].address == base) { in ps3vram_cache_match()
381 cache->hit++; in ps3vram_cache_match()
382 dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i, in ps3vram_cache_match()
383 cache->tags[i].address); in ps3vram_cache_match()
384 return i; in ps3vram_cache_match()
389 i = (jiffies + (counter++)) % cache->page_count; in ps3vram_cache_match()
390 dev_dbg(&dev->core, "Using entry %d\n", i); in ps3vram_cache_match()
392 ps3vram_cache_evict(dev, i); in ps3vram_cache_match()
393 ps3vram_cache_load(dev, i, base); in ps3vram_cache_match()
395 cache->miss++; in ps3vram_cache_match()
396 return i; in ps3vram_cache_match()
403 priv->cache.page_count = CACHE_PAGE_COUNT; in ps3vram_cache_init()
404 priv->cache.page_size = CACHE_PAGE_SIZE; in ps3vram_cache_init()
405 priv->cache.tags = kcalloc(CACHE_PAGE_COUNT, in ps3vram_cache_init()
408 if (!priv->cache.tags) in ps3vram_cache_init()
409 return -ENOMEM; in ps3vram_cache_init()
411 dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n", in ps3vram_cache_init()
422 kfree(priv->cache.tags); in ps3vram_cache_cleanup()
431 dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__, in ps3vram_read()
434 if (from >= priv->size) in ps3vram_read()
437 if (len > priv->size - from) in ps3vram_read()
438 len = priv->size - from; in ps3vram_read()
446 offset = (unsigned int) (from & (priv->cache.page_size - 1)); in ps3vram_read()
447 avail = priv->cache.page_size - offset; in ps3vram_read()
450 cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; in ps3vram_read()
452 dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x " in ps3vram_read()
458 memcpy(buf, priv->xdr_buf + cached, avail); in ps3vram_read()
461 count -= avail; in ps3vram_read()
475 if (to >= priv->size) in ps3vram_write()
478 if (len > priv->size - to) in ps3vram_write()
479 len = priv->size - to; in ps3vram_write()
487 offset = (unsigned int) (to & (priv->cache.page_size - 1)); in ps3vram_write()
488 avail = priv->cache.page_size - offset; in ps3vram_write()
491 cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; in ps3vram_write()
493 dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x " in ps3vram_write()
499 memcpy(priv->xdr_buf + cached, buf, avail); in ps3vram_write()
501 priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; in ps3vram_write()
504 count -= avail; in ps3vram_write()
514 struct ps3vram_priv *priv = m->private; in ps3vram_proc_show()
516 seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss); in ps3vram_proc_show()
528 dev_warn(&dev->core, "failed to create /proc entry\n"); in ps3vram_proc_init()
537 loff_t offset = bio->bi_iter.bi_sector << 9; in ps3vram_do_bio()
548 dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, in ps3vram_do_bio()
556 dev_err(&dev->core, "%s failed\n", op); in ps3vram_do_bio()
561 dev_err(&dev->core, "Short %s\n", op); in ps3vram_do_bio()
569 dev_dbg(&dev->core, "%s completed\n", op); in ps3vram_do_bio()
572 spin_lock_irq(&priv->lock); in ps3vram_do_bio()
573 bio_list_pop(&priv->list); in ps3vram_do_bio()
574 next = bio_list_peek(&priv->list); in ps3vram_do_bio()
575 spin_unlock_irq(&priv->lock); in ps3vram_do_bio()
577 bio->bi_status = error; in ps3vram_do_bio()
584 struct ps3_system_bus_device *dev = bio->bi_disk->private_data; in ps3vram_submit_bio()
588 dev_dbg(&dev->core, "%s\n", __func__); in ps3vram_submit_bio()
592 spin_lock_irq(&priv->lock); in ps3vram_submit_bio()
593 busy = !bio_list_empty(&priv->list); in ps3vram_submit_bio()
594 bio_list_add(&priv->list, bio); in ps3vram_submit_bio()
595 spin_unlock_irq(&priv->lock); in ps3vram_submit_bio()
624 error = -ENOMEM; in ps3vram_probe()
628 spin_lock_init(&priv->lock); in ps3vram_probe()
629 bio_list_init(&priv->list); in ps3vram_probe()
633 priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, in ps3vram_probe()
635 if (priv->xdr_buf == NULL) { in ps3vram_probe()
636 dev_err(&dev->core, "Could not allocate XDR buffer\n"); in ps3vram_probe()
637 error = -ENOMEM; in ps3vram_probe()
642 priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); in ps3vram_probe()
643 priv->fifo_ptr = priv->fifo_base; in ps3vram_probe()
647 dev_err(&dev->core, "ps3_open_hv_device failed\n"); in ps3vram_probe()
648 error = -EAGAIN; in ps3vram_probe()
653 status = -1; in ps3vram_probe()
654 ddr_size = ALIGN(memparse(size, &rest), 1024*1024); in ps3vram_probe()
656 dev_err(&dev->core, "Specified size is too small\n"); in ps3vram_probe()
657 error = -EINVAL; in ps3vram_probe()
663 &priv->memory_handle, in ps3vram_probe()
667 ddr_size -= 1024*1024; in ps3vram_probe()
670 dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n", in ps3vram_probe()
672 error = -ENOMEM; in ps3vram_probe()
677 status = lv1_gpu_context_allocate(priv->memory_handle, 0, in ps3vram_probe()
678 &priv->context_handle, &ctrl_lpar, in ps3vram_probe()
682 dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n", in ps3vram_probe()
684 error = -ENOMEM; in ps3vram_probe()
689 xdr_lpar = ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)); in ps3vram_probe()
690 status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, in ps3vram_probe()
695 dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n", in ps3vram_probe()
697 error = -ENOMEM; in ps3vram_probe()
701 priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); in ps3vram_probe()
702 if (!priv->ctrl) { in ps3vram_probe()
703 dev_err(&dev->core, "ioremap CTRL failed\n"); in ps3vram_probe()
704 error = -ENOMEM; in ps3vram_probe()
708 priv->reports = ioremap(reports_lpar, reports_size); in ps3vram_probe()
709 if (!priv->reports) { in ps3vram_probe()
710 dev_err(&dev->core, "ioremap REPORTS failed\n"); in ps3vram_probe()
711 error = -ENOMEM; in ps3vram_probe()
719 priv->size = ddr_size; in ps3vram_probe()
727 dev_err(&dev->core, "Failed to initialize channels\n"); in ps3vram_probe()
728 error = -ETIMEDOUT; in ps3vram_probe()
741 dev_err(&dev->core, "blk_alloc_queue failed\n"); in ps3vram_probe()
742 error = -ENOMEM; in ps3vram_probe()
746 priv->queue = queue; in ps3vram_probe()
753 dev_err(&dev->core, "alloc_disk failed\n"); in ps3vram_probe()
754 error = -ENOMEM; in ps3vram_probe()
758 priv->gendisk = gendisk; in ps3vram_probe()
759 gendisk->major = ps3vram_major; in ps3vram_probe()
760 gendisk->first_minor = 0; in ps3vram_probe()
761 gendisk->fops = &ps3vram_fops; in ps3vram_probe()
762 gendisk->queue = queue; in ps3vram_probe()
763 gendisk->private_data = dev; in ps3vram_probe()
764 strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name)); in ps3vram_probe()
765 set_capacity(gendisk, priv->size >> 9); in ps3vram_probe()
767 dev_info(&dev->core, "%s: Using %llu MiB of GPU memory\n", in ps3vram_probe()
768 gendisk->disk_name, get_capacity(gendisk) >> 11); in ps3vram_probe()
770 device_add_disk(&dev->core, gendisk, NULL); in ps3vram_probe()
779 iounmap(priv->reports); in ps3vram_probe()
781 iounmap(priv->ctrl); in ps3vram_probe()
783 lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, xdr_lpar, in ps3vram_probe()
786 lv1_gpu_context_free(priv->context_handle); in ps3vram_probe()
788 lv1_gpu_memory_free(priv->memory_handle); in ps3vram_probe()
792 free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); in ps3vram_probe()
804 del_gendisk(priv->gendisk); in ps3vram_remove()
805 put_disk(priv->gendisk); in ps3vram_remove()
806 blk_cleanup_queue(priv->queue); in ps3vram_remove()
809 iounmap(priv->reports); in ps3vram_remove()
810 iounmap(priv->ctrl); in ps3vram_remove()
811 lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, in ps3vram_remove()
812 ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), in ps3vram_remove()
814 lv1_gpu_context_free(priv->context_handle); in ps3vram_remove()
815 lv1_gpu_memory_free(priv->memory_handle); in ps3vram_remove()
817 free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); in ps3vram_remove()
839 return -ENODEV; in ps3vram_init()