summaryrefslogtreecommitdiff
path: root/drivers/dma/idxd/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/idxd/init.c')
-rw-r--r--drivers/dma/idxd/init.c119
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);