Lines Matching +full:cache +full:- +full:op +full:- +full:block +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)
72 u64 size; member
83 struct ps3vram_cache cache; member
97 static char *size = "256M"; variable
98 module_param(size, charp, 0);
99 MODULE_PARM_DESC(size, "memory size");
110 u32 __iomem *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); in ps3vram_notifier_reset()
121 u32 __iomem *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); in ps3vram_notifier_wait()
124 for (timeout = 20; timeout; timeout--) { in ps3vram_notifier_wait()
138 return -ETIMEDOUT; in ps3vram_notifier_wait()
145 iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_PUT); in ps3vram_init_ring()
146 iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_GET); in ps3vram_init_ring()
156 if (ioread32be(priv->ctrl + CTRL_PUT) == ioread32be(priv->ctrl + CTRL_GET)) in ps3vram_wait_ring()
161 dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n", in ps3vram_wait_ring()
162 ioread32be(priv->ctrl + CTRL_PUT), ioread32be(priv->ctrl + CTRL_GET), in ps3vram_wait_ring()
163 ioread32be(priv->ctrl + CTRL_TOP)); in ps3vram_wait_ring()
165 return -ETIMEDOUT; in ps3vram_wait_ring()
170 *(priv->fifo_ptr)++ = data; in ps3vram_out_ring()
174 u32 size) in ps3vram_begin_ring() argument
176 ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); in ps3vram_begin_ring()
186 iowrite32be(FIFO_BASE + FIFO_OFFSET, priv->ctrl + CTRL_PUT); in ps3vram_rewind_ring()
189 status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0); in ps3vram_rewind_ring()
191 dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n", in ps3vram_rewind_ring()
194 priv->fifo_ptr = priv->fifo_base; in ps3vram_rewind_ring()
204 iowrite32be(FIFO_BASE + FIFO_OFFSET + (priv->fifo_ptr - priv->fifo_base) in ps3vram_fire_ring()
205 * sizeof(u32), priv->ctrl + CTRL_PUT); in ps3vram_fire_ring()
208 status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0); in ps3vram_fire_ring()
210 dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n", in ps3vram_fire_ring()
213 if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > in ps3vram_fire_ring()
214 FIFO_SIZE - 1024) { in ps3vram_fire_ring()
215 dev_dbg(&dev->core, "FIFO full, rewinding\n"); in ps3vram_fire_ring()
269 dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); in ps3vram_upload()
270 return -1; in ps3vram_upload()
301 dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); in ps3vram_download()
302 return -1; in ps3vram_download()
311 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_evict() local
313 if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY)) in ps3vram_cache_evict()
316 dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry, in ps3vram_cache_evict()
317 cache->tags[entry].address); in ps3vram_cache_evict()
318 if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size, in ps3vram_cache_evict()
319 cache->tags[entry].address, DMA_PAGE_SIZE, in ps3vram_cache_evict()
320 cache->page_size / DMA_PAGE_SIZE) < 0) { in ps3vram_cache_evict()
321 dev_err(&dev->core, in ps3vram_cache_evict()
322 "Failed to upload from 0x%x to " "0x%x size 0x%x\n", in ps3vram_cache_evict()
323 entry * cache->page_size, cache->tags[entry].address, in ps3vram_cache_evict()
324 cache->page_size); in ps3vram_cache_evict()
326 cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; in ps3vram_cache_evict()
333 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_load() local
335 dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address); in ps3vram_cache_load()
337 CACHE_OFFSET + entry * cache->page_size, in ps3vram_cache_load()
339 cache->page_size / DMA_PAGE_SIZE) < 0) { in ps3vram_cache_load()
340 dev_err(&dev->core, in ps3vram_cache_load()
341 "Failed to download from 0x%x to 0x%x size 0x%x\n", in ps3vram_cache_load()
342 address, entry * cache->page_size, cache->page_size); in ps3vram_cache_load()
345 cache->tags[entry].address = address; in ps3vram_cache_load()
346 cache->tags[entry].flags |= CACHE_PAGE_PRESENT; in ps3vram_cache_load()
353 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_flush() local
356 dev_dbg(&dev->core, "FLUSH\n"); in ps3vram_cache_flush()
357 for (i = 0; i < cache->page_count; i++) { in ps3vram_cache_flush()
359 cache->tags[i].flags = 0; in ps3vram_cache_flush()
367 struct ps3vram_cache *cache = &priv->cache; in ps3vram_cache_match() local
373 offset = (unsigned int) (address & (cache->page_size - 1)); in ps3vram_cache_match()
374 base = (unsigned int) (address - offset); in ps3vram_cache_match()
377 for (i = 0; i < cache->page_count; i++) { in ps3vram_cache_match()
378 if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && in ps3vram_cache_match()
379 cache->tags[i].address == base) { in ps3vram_cache_match()
380 cache->hit++; in ps3vram_cache_match()
381 dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i, in ps3vram_cache_match()
382 cache->tags[i].address); in ps3vram_cache_match()
388 i = (jiffies + (counter++)) % cache->page_count; in ps3vram_cache_match()
389 dev_dbg(&dev->core, "Using entry %d\n", i); in ps3vram_cache_match()
394 cache->miss++; in ps3vram_cache_match()
402 priv->cache.page_count = CACHE_PAGE_COUNT; in ps3vram_cache_init()
403 priv->cache.page_size = CACHE_PAGE_SIZE; in ps3vram_cache_init()
404 priv->cache.tags = kcalloc(CACHE_PAGE_COUNT, in ps3vram_cache_init()
407 if (!priv->cache.tags) in ps3vram_cache_init()
408 return -ENOMEM; in ps3vram_cache_init()
410 dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n", in ps3vram_cache_init()
421 kfree(priv->cache.tags); in ps3vram_cache_cleanup()
430 dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__, in ps3vram_read()
433 if (from >= priv->size) in ps3vram_read()
436 if (len > priv->size - from) in ps3vram_read()
437 len = priv->size - from; in ps3vram_read()
445 offset = (unsigned int) (from & (priv->cache.page_size - 1)); in ps3vram_read()
446 avail = priv->cache.page_size - offset; in ps3vram_read()
449 cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; in ps3vram_read()
451 dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x " in ps3vram_read()
457 memcpy(buf, priv->xdr_buf + cached, avail); in ps3vram_read()
460 count -= avail; in ps3vram_read()
474 if (to >= priv->size) in ps3vram_write()
477 if (len > priv->size - to) in ps3vram_write()
478 len = priv->size - to; in ps3vram_write()
486 offset = (unsigned int) (to & (priv->cache.page_size - 1)); in ps3vram_write()
487 avail = priv->cache.page_size - offset; in ps3vram_write()
490 cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; in ps3vram_write()
492 dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x " in ps3vram_write()
498 memcpy(priv->xdr_buf + cached, buf, avail); in ps3vram_write()
500 priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; in ps3vram_write()
503 count -= avail; in ps3vram_write()
513 struct ps3vram_priv *priv = m->private; in ps3vram_proc_show()
515 seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss); in ps3vram_proc_show()
527 dev_warn(&dev->core, "failed to create /proc entry\n"); in ps3vram_proc_init()
535 const char *op = write ? "write" : "read"; in ps3vram_do_bio() local
536 loff_t offset = bio->bi_iter.bi_sector << 9; in ps3vram_do_bio()
547 dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, in ps3vram_do_bio()
555 dev_err(&dev->core, "%s failed\n", op); in ps3vram_do_bio()
560 dev_err(&dev->core, "Short %s\n", op); in ps3vram_do_bio()
568 dev_dbg(&dev->core, "%s completed\n", op); in ps3vram_do_bio()
571 spin_lock_irq(&priv->lock); in ps3vram_do_bio()
572 bio_list_pop(&priv->list); in ps3vram_do_bio()
573 next = bio_list_peek(&priv->list); in ps3vram_do_bio()
574 spin_unlock_irq(&priv->lock); in ps3vram_do_bio()
576 bio->bi_status = error; in ps3vram_do_bio()
583 struct ps3_system_bus_device *dev = bio->bi_bdev->bd_disk->private_data; in ps3vram_submit_bio()
587 dev_dbg(&dev->core, "%s\n", __func__); in ps3vram_submit_bio()
589 spin_lock_irq(&priv->lock); in ps3vram_submit_bio()
590 busy = !bio_list_empty(&priv->list); in ps3vram_submit_bio()
591 bio_list_add(&priv->list, bio); in ps3vram_submit_bio()
592 spin_unlock_irq(&priv->lock); in ps3vram_submit_bio()
618 error = -ENOMEM; in ps3vram_probe()
622 spin_lock_init(&priv->lock); in ps3vram_probe()
623 bio_list_init(&priv->list); in ps3vram_probe()
627 priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, in ps3vram_probe()
629 if (priv->xdr_buf == NULL) { in ps3vram_probe()
630 dev_err(&dev->core, "Could not allocate XDR buffer\n"); in ps3vram_probe()
631 error = -ENOMEM; in ps3vram_probe()
636 priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); in ps3vram_probe()
637 priv->fifo_ptr = priv->fifo_base; in ps3vram_probe()
641 dev_err(&dev->core, "ps3_open_hv_device failed\n"); in ps3vram_probe()
642 error = -EAGAIN; in ps3vram_probe()
647 status = -1; in ps3vram_probe()
648 ddr_size = ALIGN(memparse(size, &rest), 1024*1024); in ps3vram_probe()
650 dev_err(&dev->core, "Specified size is too small\n"); in ps3vram_probe()
651 error = -EINVAL; in ps3vram_probe()
657 &priv->memory_handle, in ps3vram_probe()
661 ddr_size -= 1024*1024; in ps3vram_probe()
664 dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n", in ps3vram_probe()
666 error = -ENOMEM; in ps3vram_probe()
671 status = lv1_gpu_context_allocate(priv->memory_handle, 0, in ps3vram_probe()
672 &priv->context_handle, &ctrl_lpar, in ps3vram_probe()
676 dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n", in ps3vram_probe()
678 error = -ENOMEM; in ps3vram_probe()
683 xdr_lpar = ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)); in ps3vram_probe()
684 status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, in ps3vram_probe()
689 dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n", in ps3vram_probe()
691 error = -ENOMEM; in ps3vram_probe()
695 priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); in ps3vram_probe()
696 if (!priv->ctrl) { in ps3vram_probe()
697 dev_err(&dev->core, "ioremap CTRL failed\n"); in ps3vram_probe()
698 error = -ENOMEM; in ps3vram_probe()
702 priv->reports = ioremap(reports_lpar, reports_size); in ps3vram_probe()
703 if (!priv->reports) { in ps3vram_probe()
704 dev_err(&dev->core, "ioremap REPORTS failed\n"); in ps3vram_probe()
705 error = -ENOMEM; in ps3vram_probe()
713 priv->size = ddr_size; in ps3vram_probe()
721 dev_err(&dev->core, "Failed to initialize channels\n"); in ps3vram_probe()
722 error = -ETIMEDOUT; in ps3vram_probe()
735 dev_err(&dev->core, "blk_alloc_disk failed\n"); in ps3vram_probe()
736 error = -ENOMEM; in ps3vram_probe()
740 priv->gendisk = gendisk; in ps3vram_probe()
741 gendisk->major = ps3vram_major; in ps3vram_probe()
742 gendisk->minors = 1; in ps3vram_probe()
743 gendisk->flags |= GENHD_FL_NO_PART; in ps3vram_probe()
744 gendisk->fops = &ps3vram_fops; in ps3vram_probe()
745 gendisk->private_data = dev; in ps3vram_probe()
746 strscpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name)); in ps3vram_probe()
747 set_capacity(gendisk, priv->size >> 9); in ps3vram_probe()
749 dev_info(&dev->core, "%s: Using %llu MiB of GPU memory\n", in ps3vram_probe()
750 gendisk->disk_name, get_capacity(gendisk) >> 11); in ps3vram_probe()
752 error = device_add_disk(&dev->core, gendisk, NULL); in ps3vram_probe()
764 iounmap(priv->reports); in ps3vram_probe()
766 iounmap(priv->ctrl); in ps3vram_probe()
768 lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, xdr_lpar, in ps3vram_probe()
771 lv1_gpu_context_free(priv->context_handle); in ps3vram_probe()
773 lv1_gpu_memory_free(priv->memory_handle); in ps3vram_probe()
777 free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); in ps3vram_probe()
789 del_gendisk(priv->gendisk); in ps3vram_remove()
790 put_disk(priv->gendisk); in ps3vram_remove()
793 iounmap(priv->reports); in ps3vram_remove()
794 iounmap(priv->ctrl); in ps3vram_remove()
795 lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, in ps3vram_remove()
796 ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), in ps3vram_remove()
798 lv1_gpu_context_free(priv->context_handle); in ps3vram_remove()
799 lv1_gpu_memory_free(priv->memory_handle); in ps3vram_remove()
801 free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); in ps3vram_remove()
822 return -ENODEV; in ps3vram_init()
831 pr_info("%s: registered block device major %d\n", DEVICE_NAME, in ps3vram_init()