in hw/idt/ntb_hw_idt.c [480:540]
static int idt_scan_ports(struct idt_ntb_dev *ndev)
{
unsigned char pidx, port, part;
u32 data, portsts, partsts;
/* Retrieve the local port number */
data = idt_nt_read(ndev, IDT_NT_PCIELCAP);
ndev->port = GET_FIELD(PCIELCAP_PORTNUM, data);
/* Retrieve the local partition number */
portsts = idt_sw_read(ndev, portdata_tbl[ndev->port].sts);
ndev->part = GET_FIELD(SWPORTxSTS_SWPART, portsts);
/* Initialize port/partition -> index tables with invalid values */
memset(ndev->port_idx_map, -EINVAL, sizeof(ndev->port_idx_map));
memset(ndev->part_idx_map, -EINVAL, sizeof(ndev->part_idx_map));
/*
* Walk over all the possible ports checking whether any of them has
* NT-function activated
*/
ndev->peer_cnt = 0;
for (pidx = 0; pidx < ndev->swcfg->port_cnt; pidx++) {
port = ndev->swcfg->ports[pidx];
/* Skip local port */
if (port == ndev->port)
continue;
/* Read the port status register to get it partition */
portsts = idt_sw_read(ndev, portdata_tbl[port].sts);
part = GET_FIELD(SWPORTxSTS_SWPART, portsts);
/* Retrieve the partition status */
partsts = idt_sw_read(ndev, partdata_tbl[part].sts);
/* Check if partition state is active and port has NTB */
if (IS_FLD_SET(SWPARTxSTS_STATE, partsts, ACT) &&
(IS_FLD_SET(SWPORTxSTS_MODE, portsts, NT) ||
IS_FLD_SET(SWPORTxSTS_MODE, portsts, USNT) ||
IS_FLD_SET(SWPORTxSTS_MODE, portsts, USNTDMA) ||
IS_FLD_SET(SWPORTxSTS_MODE, portsts, NTDMA))) {
/* Save the port and partition numbers */
ndev->peers[ndev->peer_cnt].port = port;
ndev->peers[ndev->peer_cnt].part = part;
/* Fill in the port/partition -> index tables */
ndev->port_idx_map[port] = ndev->peer_cnt;
ndev->part_idx_map[part] = ndev->peer_cnt;
ndev->peer_cnt++;
}
}
dev_dbg(&ndev->ntb.pdev->dev, "Local port: %hhu, num of peers: %hhu\n",
ndev->port, ndev->peer_cnt);
/* It's useless to have this driver loaded if there is no any peer */
if (ndev->peer_cnt == 0) {
dev_warn(&ndev->ntb.pdev->dev, "No active peer found\n");
return -ENODEV;
}
return 0;
}