in thunderx_edac.c [1342:1471]
static int thunderx_ocx_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct thunderx_ocx *ocx;
struct edac_device_ctl_info *edac_dev;
char name[32];
int idx;
int i;
int ret;
u64 reg;
ret = pcim_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "Cannot enable PCI device: %d\n", ret);
return ret;
}
ret = pcim_iomap_regions(pdev, BIT(0), "thunderx_ocx");
if (ret) {
dev_err(&pdev->dev, "Cannot map PCI resources: %d\n", ret);
return ret;
}
idx = edac_device_alloc_index();
snprintf(name, sizeof(name), "OCX%d", idx);
edac_dev = edac_device_alloc_ctl_info(sizeof(struct thunderx_ocx),
name, 1, "CCPI", 1,
0, NULL, 0, idx);
if (!edac_dev) {
dev_err(&pdev->dev, "Cannot allocate EDAC device\n");
return -ENOMEM;
}
ocx = edac_dev->pvt_info;
ocx->edac_dev = edac_dev;
ocx->com_ring_head = 0;
ocx->com_ring_tail = 0;
ocx->link_ring_head = 0;
ocx->link_ring_tail = 0;
ocx->regs = pcim_iomap_table(pdev)[0];
if (!ocx->regs) {
dev_err(&pdev->dev, "Cannot map PCI resources\n");
ret = -ENODEV;
goto err_free;
}
ocx->pdev = pdev;
for (i = 0; i < OCX_INTS; i++) {
ocx->msix_ent[i].entry = i;
ocx->msix_ent[i].vector = 0;
}
ret = pci_enable_msix_exact(pdev, ocx->msix_ent, OCX_INTS);
if (ret) {
dev_err(&pdev->dev, "Cannot enable interrupt: %d\n", ret);
goto err_free;
}
for (i = 0; i < OCX_INTS; i++) {
ret = devm_request_threaded_irq(&pdev->dev,
ocx->msix_ent[i].vector,
(i == 3) ?
thunderx_ocx_com_isr :
thunderx_ocx_lnk_isr,
(i == 3) ?
thunderx_ocx_com_threaded_isr :
thunderx_ocx_lnk_threaded_isr,
0, "[EDAC] ThunderX OCX",
&ocx->msix_ent[i]);
if (ret)
goto err_free;
}
edac_dev->dev = &pdev->dev;
edac_dev->dev_name = dev_name(&pdev->dev);
edac_dev->mod_name = "thunderx-ocx";
edac_dev->ctl_name = "thunderx-ocx";
ret = edac_device_add_device(edac_dev);
if (ret) {
dev_err(&pdev->dev, "Cannot add EDAC device: %d\n", ret);
goto err_free;
}
if (IS_ENABLED(CONFIG_EDAC_DEBUG)) {
ocx->debugfs = edac_debugfs_create_dir(pdev->dev.kobj.name);
ret = thunderx_create_debugfs_nodes(ocx->debugfs,
ocx_dfs_ents,
ocx,
ARRAY_SIZE(ocx_dfs_ents));
if (ret != ARRAY_SIZE(ocx_dfs_ents)) {
dev_warn(&pdev->dev, "Error creating debugfs entries: %d%s\n",
ret, ret >= 0 ? " created" : "");
}
}
pci_set_drvdata(pdev, edac_dev);
thunderx_ocx_clearstats(ocx);
for (i = 0; i < OCX_RX_LANES; i++) {
writeq(OCX_LNE_INT_ENA_ALL,
ocx->regs + OCX_LNE_INT_EN(i));
reg = readq(ocx->regs + OCX_LNE_INT(i));
writeq(reg, ocx->regs + OCX_LNE_INT(i));
}
for (i = 0; i < OCX_LINK_INTS; i++) {
reg = readq(ocx->regs + OCX_COM_LINKX_INT(i));
writeq(reg, ocx->regs + OCX_COM_LINKX_INT(i));
writeq(OCX_COM_LINKX_INT_ENA_ALL,
ocx->regs + OCX_COM_LINKX_INT_ENA_W1S(i));
}
reg = readq(ocx->regs + OCX_COM_INT);
writeq(reg, ocx->regs + OCX_COM_INT);
writeq(OCX_COM_INT_ENA_ALL, ocx->regs + OCX_COM_INT_ENA_W1S);
return 0;
err_free:
edac_device_free_ctl_info(edac_dev);
return ret;
}