in hw/amd/ntb_hw_amd.c [119:196]
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;
}