rdma.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include <linux/version.h>
  2. #include <linux/string.h>
  3. #include <linux/types.h>
  4. #include <linux/list.h>
  5. #include <linux/pci.h>
  6. #include <linux/wait.h>
  7. #include <linux/mm.h>
  8. #include <linux/pagemap.h>
  9. #include <linux/hugetlb.h>
  10. #include <linux/cdev.h>
  11. #include "base.h"
  12. static unsigned long pcidriver_follow_pte(struct mm_struct *mm, unsigned long address)
  13. {
  14. pgd_t *pgd;
  15. pud_t *pud;
  16. pmd_t *pmd;
  17. pte_t *pte;
  18. spinlock_t *ptl;
  19. unsigned long pfn = 0;
  20. pgd = pgd_offset(mm, address);
  21. if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
  22. return 0;
  23. pud = pud_offset(pgd, address);
  24. if (pud_none(*pud) || unlikely(pud_bad(*pud)))
  25. return 0;
  26. pmd = pmd_offset(pud, address);
  27. if (pmd_none(*pmd))
  28. return 0;
  29. pte = pte_offset_map_lock(mm, pmd, address, &ptl);
  30. if (!pte_none(*pte))
  31. pfn = (pte_pfn(*pte) << PAGE_SHIFT);
  32. pte_unmap_unlock(pte, ptl);
  33. return pfn;
  34. }
  35. unsigned long pcidriver_resolve_bar(unsigned long bar_address) {
  36. int dev, bar;
  37. unsigned long pfn;
  38. unsigned long address;
  39. address = (bar_address >> PAGE_SHIFT) << PAGE_SHIFT;
  40. offset = bar_address - address;
  41. pfn = pcidriver_follow_pte(current->mm, address);
  42. for (dev = 0; dev < MAXDEVICES; dev++)
  43. {
  44. pcidriver_privdata_t *privdata = pcidriver_get_privdata(dev);
  45. if (!privdata) continue;
  46. for (bar = 0; bar < 6; bar++)
  47. {
  48. unsigned long start = pci_resource_start(privdata->pdev, bar);
  49. unsigned long end = start + pci_resource_len(privdata->pdev, bar);
  50. if ((pfn >= start)&&(pfn < end))
  51. return pfn + offset;
  52. }
  53. pcidriver_put_privdata(privdata);
  54. }
  55. return 0;
  56. }
  57. EXPORT_SYMBOL(pcidriver_resolve_bar);