diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2016-03-02 06:41:30 +0100 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2016-03-02 06:41:30 +0100 |
commit | 867bddcf7be374221a04b7ae89f93a5f5d703ee6 (patch) | |
tree | a75da5441438f10c900ea3b6b4e1d14544360a62 /driver/rdma.c | |
parent | 8933c45c177556353570f92513bb49f182ce3be8 (diff) | |
download | pcitool-867bddcf7be374221a04b7ae89f93a5f5d703ee6.tar.gz pcitool-867bddcf7be374221a04b7ae89f93a5f5d703ee6.tar.bz2 pcitool-867bddcf7be374221a04b7ae89f93a5f5d703ee6.tar.xz pcitool-867bddcf7be374221a04b7ae89f93a5f5d703ee6.zip |
Resolve user-space addresses to physical addresses in the driver
Diffstat (limited to 'driver/rdma.c')
-rw-r--r-- | driver/rdma.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/driver/rdma.c b/driver/rdma.c new file mode 100644 index 0000000..22a4a5e --- /dev/null +++ b/driver/rdma.c @@ -0,0 +1,53 @@ +#include <linux/version.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/list.h> +#include <linux/pci.h> +#include <linux/wait.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/hugetlb.h> + +#include "rdma.h" + +static unsigned long pcidriver_follow_pte(struct mm_struct *mm, unsigned long address) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + spinlock_t *ptl; + unsigned long pfn = 0; + + + pgd = pgd_offset(mm, address); + if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) + return 0; + + pud = pud_offset(pgd, address); + if (pud_none(*pud) || unlikely(pud_bad(*pud))) + return 0; + + pmd = pmd_offset(pud, address); + if (pmd_none(*pmd)) + return 0; + + pte = pte_offset_map_lock(mm, pmd, address, &ptl); + if (!pte_none(*pte)) + pfn = (pte_pfn(*pte) << PAGE_SHIFT); + pte_unmap_unlock(pte, ptl); + + return pfn; +} + +unsigned long pcidriver_resolve_bar(unsigned long address) { + unsigned long pfn; + + address = (address >> PAGE_SHIFT) << PAGE_SHIFT; + pfn = pcidriver_follow_pte(current->mm, address); + + return pfn; +} + +EXPORT_SYMBOL(pcidriver_resolve_bar); |