sPAPR allows only page_shift from VFIO_IOMMU_SPAPR_TCE_GET_INFO ioctl. However, Linux 4.17 or before returns incorrect page_shift for Power9. I added the code for retrying creation of sPAPR DMA window.
Signed-off-by: Takeshi Yoshimura <[email protected]> --- lib/librte_eal/linux/eal/eal_vfio.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c index 6892a2c14..f16c5c3c0 100644 --- a/lib/librte_eal/linux/eal/eal_vfio.c +++ b/lib/librte_eal/linux/eal/eal_vfio.c @@ -1448,9 +1448,29 @@ vfio_spapr_create_new_dma_window(int vfio_container_fd, /* create new DMA window */ ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_CREATE, create); if (ret) { - RTE_LOG(ERR, EAL, " cannot create new DMA window, " - "error %i (%s)\n", errno, strerror(errno)); - return -1; + /* try possible page_shift and levels for workaround */ + uint32_t levels; + + for (levels = 1; levels <= info.ddw.levels; levels++) { + uint32_t pgsizes = info.ddw.pgsizes; + + while (pgsizes != 0) { + create->page_shift = 31 - __builtin_clz(pgsizes); + create->levels = levels; + ret = ioctl(vfio_container_fd, + VFIO_IOMMU_SPAPR_TCE_CREATE, create); + if (!ret) + break; + pgsizes &= ~(1 << create->page_shift); + } + if (!ret) + break; + } + if (ret) { + RTE_LOG(ERR, EAL, " cannot create new DMA window, " + "error %i (%s)\n", errno, strerror(errno)); + return -1; + } } if (create->start_addr != 0) { -- 2.17.1

