static int intel_ntb4_mw_set_trans()

in hw/intel/ntb_hw_gen4.c [322:414]


static int intel_ntb4_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
				   dma_addr_t addr, resource_size_t size)
{
	struct intel_ntb_dev *ndev = ntb_ndev(ntb);
	unsigned long xlat_reg, limit_reg, idx_reg;
	unsigned short base_idx, reg_val16;
	resource_size_t bar_size, mw_size;
	void __iomem *mmio;
	u64 base, limit, reg_val;
	int bar;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	if (idx >= ndev->b2b_idx && !ndev->b2b_off)
		idx += 1;

	bar = ndev_mw_to_bar(ndev, idx);
	if (bar < 0)
		return bar;

	bar_size = pci_resource_len(ndev->ntb.pdev, bar);

	if (idx == ndev->b2b_idx)
		mw_size = bar_size - ndev->b2b_off;
	else
		mw_size = bar_size;

	if (ndev->hwerr_flags & NTB_HWERR_BAR_ALIGN) {
		/* hardware requires that addr is aligned to bar size */
		if (addr & (bar_size - 1))
			return -EINVAL;
	} else {
		if (addr & (PAGE_SIZE - 1))
			return -EINVAL;
	}

	/* make sure the range fits in the usable mw size */
	if (size > mw_size)
		return -EINVAL;

	mmio = ndev->self_mmio;
	xlat_reg = ndev->xlat_reg->bar2_xlat + (idx * 0x10);
	limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10);
	base = pci_resource_start(ndev->ntb.pdev, bar);

	/* Set the limit if supported, if size is not mw_size */
	if (limit_reg && size != mw_size) {
		limit = base + size;
		base_idx = __ilog2_u64(size);
	} else {
		limit = base + mw_size;
		base_idx = __ilog2_u64(mw_size);
	}


	/* set and verify setting the translation address */
	iowrite64(addr, mmio + xlat_reg);
	reg_val = ioread64(mmio + xlat_reg);
	if (reg_val != addr) {
		iowrite64(0, mmio + xlat_reg);
		return -EIO;
	}

	dev_dbg(&ntb->pdev->dev, "BAR %d IMXBASE: %#Lx\n", bar, reg_val);

	/* set and verify setting the limit */
	iowrite64(limit, mmio + limit_reg);
	reg_val = ioread64(mmio + limit_reg);
	if (reg_val != limit) {
		iowrite64(base, mmio + limit_reg);
		iowrite64(0, mmio + xlat_reg);
		return -EIO;
	}

	dev_dbg(&ntb->pdev->dev, "BAR %d IMXLMT: %#Lx\n", bar, reg_val);

	if (ndev->hwerr_flags & NTB_HWERR_BAR_ALIGN) {
		idx_reg = ndev->xlat_reg->bar2_idx + (idx * 0x2);
		iowrite16(base_idx, mmio + idx_reg);
		reg_val16 = ioread16(mmio + idx_reg);
		if (reg_val16 != base_idx) {
			iowrite64(base, mmio + limit_reg);
			iowrite64(0, mmio + xlat_reg);
			iowrite16(0, mmio + idx_reg);
			return -EIO;
		}
		dev_dbg(&ntb->pdev->dev, "BAR %d IMBASEIDX: %#x\n", bar, reg_val16);
	}


	return 0;
}