^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2014-2016, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "test/nfit_test.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <pmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <nd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) long nr_pages, void **kaddr, pfn_t *pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) if (unlikely(is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) / 512,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) PFN_PHYS(nr_pages))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Limit dax to a single page at a time given vmalloc()-backed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * in the nfit_test case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (get_nfit_res(pmem->phys_addr + offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (kaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *kaddr = pmem->virt_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) page = vmalloc_to_page(pmem->virt_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *pfn = page_to_pfn_t(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) pr_debug_ratelimited("%s: pmem: %p pgoff: %#lx pfn: %#lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) __func__, pmem, pgoff, page_to_pfn(page));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (kaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *kaddr = pmem->virt_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * If badblocks are present, limit known good range to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * requested range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (unlikely(pmem->bb.count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return PHYS_PFN(pmem->size - pmem->pfn_pad - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }