/** * aer_alloc_rpc - allocate Root Port data structure * @dev: pointer to the pcie_dev data structure * * Invoked when Root Port's AER service is loaded. **/ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) { struct aer_rpc *rpc; rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL); if (!rpc) return NULL; /* * Initialize Root lock access, e_lock, to Root Error Status Reg, * Root Error ID Reg, and Root error producer/consumer index. */ spin_lock_init(&rpc->e_lock); rpc->rpd = dev; INIT_WORK(&rpc->dpc_handler, aer_isr); rpc->prod_idx = rpc->cons_idx = 0; mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); /* Use PCIe bus function to store rpc into PCIe device */ set_service_data(dev, rpc); return rpc; }
/** * aer_remove - clean up resources * @dev: pointer to the pcie_dev data structure * * Invoked when PCI Express bus unloads or AER probe fails. **/ static void aer_remove(struct pcie_device *dev) { struct aer_rpc *rpc = get_service_data(dev); if (rpc) { /* If register interrupt service, it must be free. */ if (rpc->isr) free_irq(dev->irq, dev); wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx); aer_delete_rootport(rpc); set_service_data(dev, NULL); } }
static void aer_remove(struct pcie_device *dev) { struct aer_rpc *rpc = get_service_data(dev); if (rpc) { if (rpc->isr) free_irq(dev->irq, dev); wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx); aer_disable_rootport(rpc); kfree(rpc); set_service_data(dev, NULL); } }
static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) { struct aer_rpc *rpc; rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL); if (!rpc) return NULL; spin_lock_init(&rpc->e_lock); rpc->rpd = dev; INIT_WORK(&rpc->dpc_handler, aer_isr); mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); set_service_data(dev, rpc); return rpc; }
static int dpc_probe(struct pcie_device *dev) { struct dpc_dev *dpc; struct pci_dev *pdev = dev->port; struct device *device = &dev->device; int status; u16 ctl, cap; if (pcie_aer_get_firmware_first(pdev)) return -ENOTSUPP; dpc = devm_kzalloc(device, sizeof(*dpc), GFP_KERNEL); if (!dpc) return -ENOMEM; dpc->cap_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DPC); dpc->dev = dev; set_service_data(dev, dpc); status = devm_request_threaded_irq(device, dev->irq, dpc_irq, dpc_handler, IRQF_SHARED, "pcie-dpc", dpc); if (status) { dev_warn(device, "request IRQ%d failed: %d\n", dev->irq, status); return status; } pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CAP, &cap); pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, &ctl); dpc->rp_extensions = (cap & PCI_EXP_DPC_CAP_RP_EXT); if (dpc->rp_extensions) { dpc->rp_log_size = (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8; if (dpc->rp_log_size < 4 || dpc->rp_log_size > 9) { dev_err(device, "RP PIO log size %u is invalid\n", dpc->rp_log_size); dpc->rp_log_size = 0; } }