diff options
Diffstat (limited to 'drivers/dma/idxd/init.c')
-rw-r--r-- | drivers/dma/idxd/init.c | 119 |
1 files changed, 47 insertions, 72 deletions
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 8b3afce9ea67..29c732a94027 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -72,7 +72,7 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) { struct pci_dev *pdev = idxd->pdev; struct device *dev = &pdev->dev; - struct idxd_irq_entry *irq_entry; + struct idxd_irq_entry *ie; int i, msixcnt; int rc = 0; @@ -90,72 +90,54 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) } dev_dbg(dev, "Enabled %d msix vectors\n", msixcnt); - /* - * We implement 1 completion list per MSI-X entry except for - * entry 0, which is for errors and others. - */ - idxd->irq_entries = kcalloc_node(msixcnt, sizeof(struct idxd_irq_entry), - GFP_KERNEL, dev_to_node(dev)); - if (!idxd->irq_entries) { - rc = -ENOMEM; - goto err_irq_entries; - } - - for (i = 0; i < msixcnt; i++) { - idxd->irq_entries[i].id = i; - idxd->irq_entries[i].idxd = idxd; - /* - * Association of WQ should be assigned starting with irq_entry 1. - * irq_entry 0 is for misc interrupts and has no wq association - */ - if (i > 0) - idxd->irq_entries[i].wq = idxd->wqs[i - 1]; - idxd->irq_entries[i].vector = pci_irq_vector(pdev, i); - idxd->irq_entries[i].int_handle = INVALID_INT_HANDLE; - if (device_pasid_enabled(idxd) && i > 0) - idxd->irq_entries[i].pasid = idxd->pasid; - else - idxd->irq_entries[i].pasid = INVALID_IOASID; - spin_lock_init(&idxd->irq_entries[i].list_lock); - } - idxd_msix_perm_setup(idxd); - irq_entry = &idxd->irq_entries[0]; - rc = request_threaded_irq(irq_entry->vector, NULL, idxd_misc_thread, - 0, "idxd-misc", irq_entry); + ie = idxd_get_ie(idxd, 0); + ie->vector = pci_irq_vector(pdev, 0); + rc = request_threaded_irq(ie->vector, NULL, idxd_misc_thread, 0, "idxd-misc", ie); if (rc < 0) { dev_err(dev, "Failed to allocate misc interrupt.\n"); goto err_misc_irq; } - dev_dbg(dev, "Allocated idxd-misc handler on msix vector %d\n", irq_entry->vector); + dev_dbg(dev, "Allocated idxd-misc handler on msix vector %d\n", ie->vector); - /* first MSI-X entry is not for wq interrupts */ - idxd->num_wq_irqs = msixcnt - 1; + for (i = 0; i < idxd->max_wqs; i++) { + int msix_idx = i + 1; + + ie = idxd_get_ie(idxd, msix_idx); - for (i = 1; i < msixcnt; i++) { - irq_entry = &idxd->irq_entries[i]; + /* MSIX vector 0 special, wq irq entry starts at 1 */ + ie->id = msix_idx; + ie->vector = pci_irq_vector(pdev, msix_idx); + ie->int_handle = INVALID_INT_HANDLE; + if (device_pasid_enabled(idxd) && i > 0) + ie->pasid = idxd->pasid; + else + ie->pasid = INVALID_IOASID; + spin_lock_init(&ie->list_lock); + init_llist_head(&ie->pending_llist); + INIT_LIST_HEAD(&ie->work_list); - init_llist_head(&idxd->irq_entries[i].pending_llist); - INIT_LIST_HEAD(&idxd->irq_entries[i].work_list); - rc = request_threaded_irq(irq_entry->vector, NULL, - idxd_wq_thread, 0, "idxd-portal", irq_entry); + rc = request_threaded_irq(ie->vector, NULL, idxd_wq_thread, 0, "idxd-portal", ie); if (rc < 0) { - dev_err(dev, "Failed to allocate irq %d.\n", irq_entry->vector); + dev_err(dev, "Failed to allocate irq %d.\n", ie->vector); goto err_wq_irqs; } - dev_dbg(dev, "Allocated idxd-msix %d for vector %d\n", i, irq_entry->vector); + dev_dbg(dev, "Allocated idxd-msix %d for vector %d\n", i, ie->vector); if (idxd->request_int_handles) { - rc = idxd_device_request_int_handle(idxd, i, &irq_entry->int_handle, + rc = idxd_device_request_int_handle(idxd, i, &ie->int_handle, IDXD_IRQ_MSIX); if (rc < 0) { - free_irq(irq_entry->vector, irq_entry); + free_irq(ie->vector, ie); goto err_wq_irqs; } - dev_dbg(dev, "int handle requested: %u\n", irq_entry->int_handle); + dev_dbg(dev, "int handle requested: %u\n", ie->int_handle); + } else { + ie->int_handle = msix_idx; } + } idxd_unmask_error_interrupts(idxd); @@ -163,23 +145,19 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) err_wq_irqs: while (--i >= 0) { - irq_entry = &idxd->irq_entries[i]; - free_irq(irq_entry->vector, irq_entry); - if (irq_entry->int_handle != INVALID_INT_HANDLE) { - idxd_device_release_int_handle(idxd, irq_entry->int_handle, - IDXD_IRQ_MSIX); - irq_entry->int_handle = INVALID_INT_HANDLE; - irq_entry->pasid = INVALID_IOASID; + ie = &idxd->wqs[i]->ie; + free_irq(ie->vector, ie); + if (ie->int_handle != INVALID_INT_HANDLE) { + idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX); + ie->int_handle = INVALID_INT_HANDLE; + ie->pasid = INVALID_IOASID; } - irq_entry->vector = -1; - irq_entry->wq = NULL; - irq_entry->idxd = NULL; + ie->vector = -1; } err_misc_irq: /* Disable error interrupt generation */ idxd_mask_error_interrupts(idxd); idxd_msix_perm_clear(idxd); - err_irq_entries: pci_free_irq_vectors(pdev); dev_err(dev, "No usable interrupts\n"); return rc; @@ -188,21 +166,18 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) static void idxd_cleanup_interrupts(struct idxd_device *idxd) { struct pci_dev *pdev = idxd->pdev; - struct idxd_irq_entry *irq_entry; + struct idxd_irq_entry *ie; int i; for (i = 0; i < idxd->irq_cnt; i++) { - irq_entry = &idxd->irq_entries[i]; - if (irq_entry->int_handle != INVALID_INT_HANDLE) { - idxd_device_release_int_handle(idxd, irq_entry->int_handle, - IDXD_IRQ_MSIX); - irq_entry->int_handle = INVALID_INT_HANDLE; - irq_entry->pasid = INVALID_IOASID; + ie = idxd_get_ie(idxd, i); + if (ie->int_handle != INVALID_INT_HANDLE) { + idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX); + ie->int_handle = INVALID_INT_HANDLE; + ie->pasid = INVALID_IOASID; } - irq_entry->vector = -1; - irq_entry->wq = NULL; - irq_entry->idxd = NULL; - free_irq(irq_entry->vector, irq_entry); + free_irq(ie->vector, ie); + ie->vector = -1; } idxd_mask_error_interrupts(idxd); @@ -755,7 +730,7 @@ static void idxd_release_int_handles(struct idxd_device *idxd) int i, rc; for (i = 1; i < idxd->irq_cnt; i++) { - struct idxd_irq_entry *ie = &idxd->irq_entries[i]; + struct idxd_irq_entry *ie = idxd_get_ie(idxd, i); if (ie->int_handle != INVALID_INT_HANDLE) { rc = idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX); @@ -783,7 +758,7 @@ static void idxd_shutdown(struct pci_dev *pdev) idxd_mask_error_interrupts(idxd); for (i = 0; i < msixcnt; i++) { - irq_entry = &idxd->irq_entries[i]; + irq_entry = idxd_get_ie(idxd, i); synchronize_irq(irq_entry->vector); if (i == 0) continue; @@ -815,7 +790,7 @@ static void idxd_remove(struct pci_dev *pdev) idxd_disable_system_pasid(idxd); for (i = 0; i < msixcnt; i++) { - irq_entry = &idxd->irq_entries[i]; + irq_entry = idxd_get_ie(idxd, i); free_irq(irq_entry->vector, irq_entry); } idxd_msix_perm_clear(idxd); |