in thunderx_edac.c [1945:2079]
static int thunderx_l2c_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct thunderx_l2c *l2c;
struct edac_device_ctl_info *edac_dev;
struct debugfs_entry **l2c_devattr;
size_t dfs_entries;
irqreturn_t (*thunderx_l2c_isr)(int, void *) = NULL;
char name[32];
const char *fmt;
u64 reg_en_offs, reg_en_mask;
int idx;
int ret;
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_l2c");
if (ret) {
dev_err(&pdev->dev, "Cannot map PCI resources: %d\n", ret);
return ret;
}
switch (pdev->device) {
case PCI_DEVICE_ID_THUNDER_L2C_TAD:
thunderx_l2c_isr = thunderx_l2c_tad_isr;
l2c_devattr = l2c_tad_dfs_ents;
dfs_entries = ARRAY_SIZE(l2c_tad_dfs_ents);
fmt = "L2C-TAD%d";
reg_en_offs = L2C_TAD_INT_ENA_W1S;
reg_en_mask = L2C_TAD_INT_ENA_ALL;
break;
case PCI_DEVICE_ID_THUNDER_L2C_CBC:
thunderx_l2c_isr = thunderx_l2c_cbc_isr;
l2c_devattr = l2c_cbc_dfs_ents;
dfs_entries = ARRAY_SIZE(l2c_cbc_dfs_ents);
fmt = "L2C-CBC%d";
reg_en_offs = L2C_CBC_INT_ENA_W1S;
reg_en_mask = L2C_CBC_INT_ENA_ALL;
break;
case PCI_DEVICE_ID_THUNDER_L2C_MCI:
thunderx_l2c_isr = thunderx_l2c_mci_isr;
l2c_devattr = l2c_mci_dfs_ents;
dfs_entries = ARRAY_SIZE(l2c_mci_dfs_ents);
fmt = "L2C-MCI%d";
reg_en_offs = L2C_MCI_INT_ENA_W1S;
reg_en_mask = L2C_MCI_INT_ENA_ALL;
break;
default:
//Should never ever get here
dev_err(&pdev->dev, "Unsupported PCI device: %04x\n",
pdev->device);
return -EINVAL;
}
idx = edac_device_alloc_index();
snprintf(name, sizeof(name), fmt, idx);
edac_dev = edac_device_alloc_ctl_info(sizeof(struct thunderx_l2c),
name, 1, "L2C", 1, 0,
NULL, 0, idx);
if (!edac_dev) {
dev_err(&pdev->dev, "Cannot allocate EDAC device\n");
return -ENOMEM;
}
l2c = edac_dev->pvt_info;
l2c->edac_dev = edac_dev;
l2c->regs = pcim_iomap_table(pdev)[0];
if (!l2c->regs) {
dev_err(&pdev->dev, "Cannot map PCI resources\n");
ret = -ENODEV;
goto err_free;
}
l2c->pdev = pdev;
l2c->ring_head = 0;
l2c->ring_tail = 0;
l2c->msix_ent.entry = 0;
l2c->msix_ent.vector = 0;
ret = pci_enable_msix_exact(pdev, &l2c->msix_ent, 1);
if (ret) {
dev_err(&pdev->dev, "Cannot enable interrupt: %d\n", ret);
goto err_free;
}
ret = devm_request_threaded_irq(&pdev->dev, l2c->msix_ent.vector,
thunderx_l2c_isr,
thunderx_l2c_threaded_isr,
0, "[EDAC] ThunderX L2C",
&l2c->msix_ent);
if (ret)
goto err_free;
edac_dev->dev = &pdev->dev;
edac_dev->dev_name = dev_name(&pdev->dev);
edac_dev->mod_name = "thunderx-l2c";
edac_dev->ctl_name = "thunderx-l2c";
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)) {
l2c->debugfs = edac_debugfs_create_dir(pdev->dev.kobj.name);
ret = thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr,
l2c, dfs_entries);
if (ret != dfs_entries) {
dev_warn(&pdev->dev, "Error creating debugfs entries: %d%s\n",
ret, ret >= 0 ? " created" : "");
}
}
pci_set_drvdata(pdev, edac_dev);
writeq(reg_en_mask, l2c->regs + reg_en_offs);
return 0;
err_free:
edac_device_free_ctl_info(edac_dev);
return ret;
}