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;
}