static int intel_ntb3_mw_set_trans()

in hw/intel/ntb_hw_gen3.c [443:532]


static int intel_ntb3_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;
	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;

	/* hardware requires that addr is aligned to bar size */
	if (addr & (bar_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;
	else
		limit = base + 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 IMBARXBASE: %#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 IMBARXLMT: %#Lx\n", bar, reg_val);

	/* setup the EP */
	limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10) + 0x4000;
	base = ioread64(mmio + GEN3_EMBAR1_OFFSET + (8 * idx));
	base &= ~0xf;

	if (limit_reg && size != mw_size)
		limit = base + size;
	else
		limit = base + mw_size;

	/* 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 EMBARXLMT: %#Lx\n", bar, reg_val);

	return 0;
}