static int switchtec_ntb_mw_set_trans()

in hw/mscc/ntb_hw_switchtec.c [270:339]


static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx,
				      dma_addr_t addr, resource_size_t size)
{
	struct switchtec_ntb *sndev = ntb_sndev(ntb);
	struct ntb_ctrl_regs __iomem *ctl = sndev->mmio_peer_ctrl;
	int xlate_pos = ilog2(size);
	int nr_direct_mw = sndev->peer_nr_direct_mw;
	int rc;

	if (pidx != NTB_DEF_PEER_IDX)
		return -EINVAL;

	dev_dbg(&sndev->stdev->dev, "MW %d: part %d addr %pad size %pap\n",
		widx, pidx, &addr, &size);

	if (widx >= switchtec_ntb_mw_count(ntb, pidx))
		return -EINVAL;

	if (size != 0 && xlate_pos < 12)
		return -EINVAL;

	if (!IS_ALIGNED(addr, BIT_ULL(xlate_pos))) {
		/*
		 * In certain circumstances we can get a buffer that is
		 * not aligned to its size. (Most of the time
		 * dma_alloc_coherent ensures this). This can happen when
		 * using large buffers allocated by the CMA
		 * (see CMA_CONFIG_ALIGNMENT)
		 */
		dev_err(&sndev->stdev->dev,
			"ERROR: Memory window address is not aligned to its size!\n");
		return -EINVAL;
	}

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

	if (size == 0) {
		if (widx < nr_direct_mw)
			switchtec_ntb_mw_clr_direct(sndev, widx);
		else
			switchtec_ntb_mw_clr_lut(sndev, widx);
	} else {
		if (widx < nr_direct_mw)
			switchtec_ntb_mw_set_direct(sndev, widx, addr, size);
		else
			switchtec_ntb_mw_set_lut(sndev, widx, addr, size);
	}

	rc = switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_CFG,
				   NTB_CTRL_PART_STATUS_NORMAL);

	if (rc == -EIO) {
		dev_err(&sndev->stdev->dev,
			"Hardware reported an error configuring mw %d: %08x\n",
			widx, ioread32(&ctl->bar_error));

		if (widx < nr_direct_mw)
			switchtec_ntb_mw_clr_direct(sndev, widx);
		else
			switchtec_ntb_mw_clr_lut(sndev, widx);

		switchtec_ntb_part_op(sndev, ctl, NTB_CTRL_PART_OP_CFG,
				      NTB_CTRL_PART_STATUS_NORMAL);
	}

	return rc;
}