static int crosslink_setup_mws()

in hw/mscc/ntb_hw_switchtec.c [996:1060]


static int crosslink_setup_mws(struct switchtec_ntb *sndev, int ntb_lut_idx,
			       u64 *mw_addrs, int mw_count)
{
	int rc, i;
	struct ntb_ctrl_regs __iomem *ctl = sndev->mmio_self_ctrl;
	u64 addr;
	size_t size, offset;
	int bar;
	int xlate_pos;
	u32 ctl_val;

	rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_LOCK,
				   NTB_CTRL_PART_STATUS_LOCKED);
	if (rc)
		return rc;

	for (i = 0; i < sndev->nr_lut_mw; i++) {
		if (i == ntb_lut_idx)
			continue;

		addr = mw_addrs[0] + LUT_SIZE * i;

		iowrite64((NTB_CTRL_LUT_EN | (sndev->peer_partition << 1) |
			   addr),
			  &ctl->lut_entry[i]);
	}

	sndev->nr_direct_mw = min_t(int, sndev->nr_direct_mw, mw_count);

	for (i = 0; i < sndev->nr_direct_mw; i++) {
		bar = sndev->direct_mw_to_bar[i];
		offset = (i == 0) ? LUT_SIZE * sndev->nr_lut_mw : 0;
		addr = mw_addrs[i] + offset;
		size = pci_resource_len(sndev->ntb.pdev, bar) - offset;
		xlate_pos = ilog2(size);

		if (offset && size > offset)
			size = offset;

		ctl_val = ioread32(&ctl->bar_entry[bar].ctl);
		ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN;

		iowrite32(ctl_val, &ctl->bar_entry[bar].ctl);
		iowrite32(xlate_pos | (lower_32_bits(size) & 0xFFFFF000),
			  &ctl->bar_entry[bar].win_size);
		iowrite32(upper_32_bits(size), &ctl->bar_ext_entry[bar].win_size);
		iowrite64(sndev->peer_partition | addr,
			  &ctl->bar_entry[bar].xlate_addr);
	}

	rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_CFG,
				   NTB_CTRL_PART_STATUS_NORMAL);
	if (rc) {
		u32 bar_error, lut_error;

		bar_error = ioread32(&ctl->bar_error);
		lut_error = ioread32(&ctl->lut_error);
		dev_err(&sndev->stdev->dev,
			"Error setting up cross link windows: %08x / %08x\n",
			bar_error, lut_error);
		return rc;
	}

	return 0;
}