static int idt_ntb_peer_mw_set_trans()

in hw/idt/ntb_hw_idt.c [1287:1343]


static int idt_ntb_peer_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx,
				     u64 addr, resource_size_t size)
{
	struct idt_ntb_dev *ndev = to_ndev_ntb(ntb);
	struct idt_mw_cfg *mw_cfg;
	u32 data = 0, lutoff = 0;

	if (pidx < 0 || ndev->peer_cnt <= pidx)
		return -EINVAL;

	if (widx < 0 || ndev->mw_cnt <= widx)
		return -EINVAL;

	/*
	 * Retrieve the memory window config to make sure the passed arguments
	 * fit it restrictions
	 */
	mw_cfg = &ndev->mws[widx];
	if (!IS_ALIGNED(addr, mw_cfg->addr_align))
		return -EINVAL;
	if (!IS_ALIGNED(size, mw_cfg->size_align) || size > mw_cfg->size_max)
		return -EINVAL;

	/* DIR and LUT based translations are initialized differently */
	if (mw_cfg->type == IDT_MW_DIR) {
		const struct idt_ntb_bar *bar = &ntdata_tbl.bars[mw_cfg->bar];
		u64 limit;
		/* Set destination partition of translation */
		data = idt_nt_read(ndev, bar->setup);
		data = SET_FIELD(BARSETUP_TPART, data, ndev->peers[pidx].part);
		idt_nt_write(ndev, bar->setup, data);
		/* Set translation base address */
		idt_nt_write(ndev, bar->ltbase, (u32)addr);
		idt_nt_write(ndev, bar->utbase, (u32)(addr >> 32));
		/* Set the custom BAR aperture limit */
		limit = pci_bus_address(ntb->pdev, mw_cfg->bar) + size;
		idt_nt_write(ndev, bar->limit, (u32)limit);
		if (IS_FLD_SET(BARSETUP_TYPE, data, 64))
			idt_nt_write(ndev, (bar + 1)->limit, (limit >> 32));
	} else {
		unsigned long irqflags;
		/* Initialize corresponding LUT entry */
		lutoff = SET_FIELD(LUTOFFSET_INDEX, 0, mw_cfg->idx) |
			 SET_FIELD(LUTOFFSET_BAR, 0, mw_cfg->bar);
		data = SET_FIELD(LUTUDATA_PART, 0, ndev->peers[pidx].part) |
			IDT_LUTUDATA_VALID;
		spin_lock_irqsave(&ndev->lut_lock, irqflags);
		idt_nt_write(ndev, IDT_NT_LUTOFFSET, lutoff);
		idt_nt_write(ndev, IDT_NT_LUTLDATA, (u32)addr);
		idt_nt_write(ndev, IDT_NT_LUTMDATA, (u32)(addr >> 32));
		idt_nt_write(ndev, IDT_NT_LUTUDATA, data);
		spin_unlock_irqrestore(&ndev->lut_lock, irqflags);
		/* Limit address isn't specified since size is fixed for LUT */
	}

	return 0;
}