static int amd_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx, resource_size_t *addr_align, resource_size_t *size_align, resource_size_t *size_max) { struct amd_ntb_dev *ndev = ntb_ndev(ntb); int bar; if (pidx != NTB_DEF_PEER_IDX) return -EINVAL; bar = ndev_mw_to_bar(ndev, idx); if (bar < 0) return bar; if (addr_align) *addr_align = SZ_4K; if (size_align) *size_align = 1; if (size_max) *size_max = pci_resource_len(ndev->ntb.pdev, bar); return 0; }
static int amd_ntb_mw_get_range(struct ntb_dev *ntb, int idx, phys_addr_t *base, resource_size_t *size, resource_size_t *align, resource_size_t *align_size) { struct amd_ntb_dev *ndev = ntb_ndev(ntb); int bar; bar = ndev_mw_to_bar(ndev, idx); if (bar < 0) return bar; if (base) *base = pci_resource_start(ndev->ntb.pdev, bar); if (size) *size = pci_resource_len(ndev->ntb.pdev, bar); if (align) *align = SZ_4K; if (align_size) *align_size = 1; return 0; }
static int amd_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx, phys_addr_t *base, resource_size_t *size) { struct amd_ntb_dev *ndev = ntb_ndev(ntb); int bar; bar = ndev_mw_to_bar(ndev, idx); if (bar < 0) return bar; if (base) *base = pci_resource_start(ndev->ntb.pdev, bar); if (size) *size = pci_resource_len(ndev->ntb.pdev, bar); return 0; }
static int amd_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx, dma_addr_t addr, resource_size_t size) { struct amd_ntb_dev *ndev = ntb_ndev(ntb); unsigned long xlat_reg, limit_reg = 0; resource_size_t mw_size; void __iomem *mmio, *peer_mmio; u64 base_addr, limit, reg_val; int bar; if (pidx != NTB_DEF_PEER_IDX) return -EINVAL; bar = ndev_mw_to_bar(ndev, idx); if (bar < 0) return bar; mw_size = pci_resource_len(ntb->pdev, bar); /* make sure the range fits in the usable mw size */ if (size > mw_size) return -EINVAL; mmio = ndev->self_mmio; peer_mmio = ndev->peer_mmio; base_addr = pci_resource_start(ntb->pdev, bar); if (bar != 1) { xlat_reg = AMD_BAR23XLAT_OFFSET + ((bar - 2) << 2); limit_reg = AMD_BAR23LMT_OFFSET + ((bar - 2) << 2); /* Set the limit if supported */ limit = size; /* set and verify setting the translation address */ write64(addr, peer_mmio + xlat_reg); reg_val = read64(peer_mmio + xlat_reg); if (reg_val != addr) { write64(0, peer_mmio + xlat_reg); return -EIO; } /* set and verify setting the limit */ write64(limit, peer_mmio + limit_reg); reg_val = read64(peer_mmio + limit_reg); if (reg_val != limit) { write64(base_addr, mmio + limit_reg); write64(0, peer_mmio + xlat_reg); return -EIO; } } else { xlat_reg = AMD_BAR1XLAT_OFFSET; limit_reg = AMD_BAR1LMT_OFFSET; /* Set the limit if supported */ limit = size; /* set and verify setting the translation address */ write64(addr, peer_mmio + xlat_reg); reg_val = read64(peer_mmio + xlat_reg); if (reg_val != addr) { write64(0, peer_mmio + xlat_reg); return -EIO; } /* set and verify setting the limit */ writel(limit, peer_mmio + limit_reg); reg_val = readl(peer_mmio + limit_reg); if (reg_val != limit) { writel(base_addr, mmio + limit_reg); writel(0, peer_mmio + xlat_reg); return -EIO; } } return 0; }