in hw/intel/ntb_hw_gen1.c [1537:1641]
static int xeon_init_ntb(struct intel_ntb_dev *ndev)
{
struct device *dev = &ndev->ntb.pdev->dev;
int rc;
u32 ntb_ctl;
if (ndev->bar4_split)
ndev->mw_count = HSX_SPLIT_BAR_MW_COUNT;
else
ndev->mw_count = XEON_MW_COUNT;
ndev->spad_count = XEON_SPAD_COUNT;
ndev->db_count = XEON_DB_COUNT;
ndev->db_link_mask = XEON_DB_LINK_BIT;
switch (ndev->ntb.topo) {
case NTB_TOPO_PRI:
if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP) {
dev_err(dev, "NTB Primary config disabled\n");
return -EINVAL;
}
/* enable link to allow secondary side device to appear */
ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
ntb_ctl &= ~NTB_CTL_DISABLE;
iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
/* use half the spads for the peer */
ndev->spad_count >>= 1;
ndev->self_reg = &xeon_pri_reg;
ndev->peer_reg = &xeon_sec_reg;
ndev->xlat_reg = &xeon_sec_xlat;
break;
case NTB_TOPO_SEC:
if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP) {
dev_err(dev, "NTB Secondary config disabled\n");
return -EINVAL;
}
/* use half the spads for the peer */
ndev->spad_count >>= 1;
ndev->self_reg = &xeon_sec_reg;
ndev->peer_reg = &xeon_pri_reg;
ndev->xlat_reg = &xeon_pri_xlat;
break;
case NTB_TOPO_B2B_USD:
case NTB_TOPO_B2B_DSD:
ndev->self_reg = &xeon_pri_reg;
ndev->peer_reg = &xeon_b2b_reg;
ndev->xlat_reg = &xeon_sec_xlat;
if (ndev->hwerr_flags & NTB_HWERR_SDOORBELL_LOCKUP) {
ndev->peer_reg = &xeon_pri_reg;
if (b2b_mw_idx < 0)
ndev->b2b_idx = b2b_mw_idx + ndev->mw_count;
else
ndev->b2b_idx = b2b_mw_idx;
if (ndev->b2b_idx >= ndev->mw_count) {
dev_dbg(dev,
"b2b_mw_idx %d invalid for mw_count %u\n",
b2b_mw_idx, ndev->mw_count);
return -EINVAL;
}
dev_dbg(dev, "setting up b2b mw idx %d means %d\n",
b2b_mw_idx, ndev->b2b_idx);
} else if (ndev->hwerr_flags & NTB_HWERR_B2BDOORBELL_BIT14) {
dev_warn(dev, "Reduce doorbell count by 1\n");
ndev->db_count -= 1;
}
if (ndev->ntb.topo == NTB_TOPO_B2B_USD) {
rc = xeon_setup_b2b_mw(ndev,
&xeon_b2b_dsd_addr,
&xeon_b2b_usd_addr);
} else {
rc = xeon_setup_b2b_mw(ndev,
&xeon_b2b_usd_addr,
&xeon_b2b_dsd_addr);
}
if (rc)
return rc;
/* Enable Bus Master and Memory Space on the secondary side */
iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
ndev->self_mmio + XEON_SPCICMD_OFFSET);
break;
default:
return -EINVAL;
}
ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
ndev->reg->db_iowrite(ndev->db_valid_mask,
ndev->self_mmio +
ndev->self_reg->db_mask);
return 0;
}