From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 31 Jan 2024 03:29:01 +0000 Subject: [PATCH] add lvds1024*800 --- kernel/drivers/soc/rockchip/rockchip_ramdisk.c | 96 ++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 88 insertions(+), 8 deletions(-) diff --git a/kernel/drivers/soc/rockchip/rockchip_ramdisk.c b/kernel/drivers/soc/rockchip/rockchip_ramdisk.c index c7143a96..e2118ac 100644 --- a/kernel/drivers/soc/rockchip/rockchip_ramdisk.c +++ b/kernel/drivers/soc/rockchip/rockchip_ramdisk.c @@ -7,9 +7,12 @@ */ #include <linux/backing-dev.h> +#include <linux/dax.h> #include <linux/module.h> #include <linux/of_address.h> +#include <linux/pfn_t.h> #include <linux/platform_device.h> +#include <linux/uio.h> #define PAGE_SECTORS_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) #define PAGE_SECTORS (1 << PAGE_SECTORS_SHIFT) @@ -21,6 +24,9 @@ struct device *dev; phys_addr_t mem_addr; size_t mem_size; + size_t mem_pages; + void *mem_kaddr; + struct dax_device *dax_dev; }; static int rd_major; @@ -130,7 +136,7 @@ return 0; } -static blk_qc_t rd_make_request(struct request_queue *q, struct bio *bio) +static blk_qc_t rd_submit_bio(struct bio *bio) { struct rd_device *rd = bio->bi_disk->private_data; struct bio_vec bvec; @@ -144,6 +150,10 @@ bio_for_each_segment(bvec, bio, iter) { unsigned int len = bvec.bv_len; int err; + + /* Don't support un-aligned buffer */ + WARN_ON_ONCE((bvec.bv_offset & (SECTOR_SIZE - 1)) || + (len & (SECTOR_SIZE - 1))); err = rd_do_bvec(rd, bvec.bv_page, len, bvec.bv_offset, bio_op(bio), sector); @@ -174,19 +184,74 @@ static const struct block_device_operations rd_fops = { .owner = THIS_MODULE, + .submit_bio = rd_submit_bio, .rw_page = rd_rw_page, +}; + +static long rd_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, + long nr_pages, void **kaddr, pfn_t *pfn) +{ + struct rd_device *rd = dax_get_private(dax_dev); + + phys_addr_t offset = PFN_PHYS(pgoff); + size_t max_nr_pages = rd->mem_pages - pgoff; + + if (kaddr) + *kaddr = rd->mem_kaddr + offset; + if (pfn) + *pfn = phys_to_pfn_t(rd->mem_addr + offset, PFN_DEV | PFN_MAP); + + return nr_pages > max_nr_pages ? max_nr_pages : nr_pages; +} + +static bool rd_dax_supported(struct dax_device *dax_dev, + struct block_device *bdev, int blocksize, + sector_t start, sector_t sectors) +{ + return true; +} + +static size_t rd_dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + return copy_from_iter(addr, bytes, i); +} + +static size_t rd_dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + return copy_to_iter(addr, bytes, i); +} + +static int rd_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, size_t nr_pages) +{ + long rc; + void *kaddr; + + rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL); + if (rc < 0) + return rc; + memset(kaddr, 0, nr_pages << PAGE_SHIFT); + + return 0; +} + +static const struct dax_operations rd_dax_ops = { + .direct_access = rd_dax_direct_access, + .dax_supported = rd_dax_supported, + .copy_from_iter = rd_dax_copy_from_iter, + .copy_to_iter = rd_dax_copy_to_iter, + .zero_page_range = rd_dax_zero_page_range, }; static int rd_init(struct rd_device *rd, int major, int minor) { + int ret; struct gendisk *disk; - rd->rd_queue = blk_alloc_queue(GFP_KERNEL); + rd->rd_queue = blk_alloc_queue(NUMA_NO_NODE); if (!rd->rd_queue) return -ENOMEM; - - blk_queue_make_request(rd->rd_queue, rd_make_request); - blk_queue_max_hw_sectors(rd->rd_queue, 1024); /* This is so fdisk will align partitions on 4k, because of * direct_access API needing 4k alignment, returning a PFN @@ -196,8 +261,10 @@ */ blk_queue_physical_block_size(rd->rd_queue, PAGE_SIZE); disk = alloc_disk(1); - if (!disk) + if (!disk) { + ret = -ENOMEM; goto out_free_queue; + } disk->major = major; disk->first_minor = 0; disk->fops = &rd_fops; @@ -206,11 +273,22 @@ sprintf(disk->disk_name, "rd%d", minor); set_capacity(disk, rd->mem_size >> SECTOR_SHIFT); rd->rd_disk = disk; - rd->rd_queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; + + rd->mem_kaddr = phys_to_virt(rd->mem_addr); + rd->mem_pages = PHYS_PFN(rd->mem_size); + rd->dax_dev = alloc_dax(rd, disk->disk_name, &rd_dax_ops, DAXDEV_F_SYNC); + if (IS_ERR(rd->dax_dev)) { + ret = PTR_ERR(rd->dax_dev); + dev_err(rd->dev, "alloc_dax failed %d\n", ret); + rd->dax_dev = NULL; + goto out_free_queue; + } /* Tell the block layer that this is not a rotational device */ blk_queue_flag_set(QUEUE_FLAG_NONROT, rd->rd_queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, rd->rd_queue); + if (rd->dax_dev) + blk_queue_flag_set(QUEUE_FLAG_DAX, rd->rd_queue); rd->rd_disk->queue = rd->rd_queue; add_disk(rd->rd_disk); @@ -219,7 +297,7 @@ out_free_queue: blk_cleanup_queue(rd->rd_queue); - return -ENOMEM; + return ret; } static int rd_probe(struct platform_device *pdev) @@ -252,6 +330,8 @@ rd->mem_size = resource_size(®); ret = rd_init(rd, rd_major, 0); + dev_info(dev, "0x%zx@%pa -> 0x%px dax:%d ret:%d\n", + rd->mem_size, &rd->mem_addr, rd->mem_kaddr, (bool)rd->dax_dev, ret); return ret; } -- Gitblit v1.6.2