Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7bf3976d authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Doug Ledford
Browse files

vmw_pvrdma: switch to pci_alloc_irq_vectors



.. and greatly clean up the irq handling boilerplate code.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarAdit Ranadive <aditr@vmware.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 64b2ae74
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -196,13 +196,7 @@ struct pvrdma_dev {
	spinlock_t cmd_lock; /* Command lock. */
	struct semaphore cmd_sema;
	struct completion cmd_done;
	struct {
		enum pvrdma_intr_type type; /* Intr type */
		struct msix_entry msix_entry[PVRDMA_MAX_INTERRUPTS];
		irq_handler_t handler[PVRDMA_MAX_INTERRUPTS];
		u8 enabled[PVRDMA_MAX_INTERRUPTS];
		u8 size;
	} intr;
	unsigned int nr_vectors;

	/* RDMA-related device information. */
	union ib_gid *sgid_tbl;
+0 −6
Original line number Diff line number Diff line
@@ -149,12 +149,6 @@ enum pvrdma_intr_cause {
	PVRDMA_INTR_CAUSE_CQ		= (1 << PVRDMA_INTR_VECTOR_CQ),
};

enum pvrdma_intr_type {
	PVRDMA_INTR_TYPE_INTX,		/* Legacy. */
	PVRDMA_INTR_TYPE_MSI,		/* MSI. */
	PVRDMA_INTR_TYPE_MSIX,		/* MSI-X. */
};

enum pvrdma_gos_bits {
	PVRDMA_GOS_BITS_UNK,		/* Unknown. */
	PVRDMA_GOS_BITS_32,		/* 32-bit. */
+33 −129
Original line number Diff line number Diff line
@@ -282,7 +282,7 @@ static irqreturn_t pvrdma_intr0_handler(int irq, void *dev_id)

	dev_dbg(&dev->pdev->dev, "interrupt 0 (response) handler\n");

	if (dev->intr.type != PVRDMA_INTR_TYPE_MSIX) {
	if (!dev->pdev->msix_enabled) {
		/* Legacy intr */
		icr = pvrdma_read_reg(dev, PVRDMA_REG_ICR);
		if (icr == 0)
@@ -489,31 +489,13 @@ static irqreturn_t pvrdma_intrx_handler(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static void pvrdma_disable_msi_all(struct pvrdma_dev *dev)
{
	if (dev->intr.type == PVRDMA_INTR_TYPE_MSIX)
		pci_disable_msix(dev->pdev);
	else if (dev->intr.type == PVRDMA_INTR_TYPE_MSI)
		pci_disable_msi(dev->pdev);
}

static void pvrdma_free_irq(struct pvrdma_dev *dev)
{
	int i;

	dev_dbg(&dev->pdev->dev, "freeing interrupts\n");

	if (dev->intr.type == PVRDMA_INTR_TYPE_MSIX) {
		for (i = 0; i < dev->intr.size; i++) {
			if (dev->intr.enabled[i]) {
				free_irq(dev->intr.msix_entry[i].vector, dev);
				dev->intr.enabled[i] = 0;
			}
		}
	} else if (dev->intr.type == PVRDMA_INTR_TYPE_INTX ||
		   dev->intr.type == PVRDMA_INTR_TYPE_MSI) {
		free_irq(dev->pdev->irq, dev);
	}
	for (i = 0; i < dev->nr_vectors; i++)
		free_irq(pci_irq_vector(dev->pdev, i), dev);
}

static void pvrdma_enable_intrs(struct pvrdma_dev *dev)
@@ -528,126 +510,48 @@ static void pvrdma_disable_intrs(struct pvrdma_dev *dev)
	pvrdma_write_reg(dev, PVRDMA_REG_IMR, ~0);
}

static int pvrdma_enable_msix(struct pci_dev *pdev, struct pvrdma_dev *dev)
{
	int i;
	int ret;

	for (i = 0; i < PVRDMA_MAX_INTERRUPTS; i++) {
		dev->intr.msix_entry[i].entry = i;
		dev->intr.msix_entry[i].vector = i;

		switch (i) {
		case 0:
			/* CMD ring handler */
			dev->intr.handler[i] = pvrdma_intr0_handler;
			break;
		case 1:
			/* Async event ring handler */
			dev->intr.handler[i] = pvrdma_intr1_handler;
			break;
		default:
			/* Completion queue handler */
			dev->intr.handler[i] = pvrdma_intrx_handler;
			break;
		}
	}

	ret = pci_enable_msix(pdev, dev->intr.msix_entry,
			      PVRDMA_MAX_INTERRUPTS);
	if (!ret) {
		dev->intr.type = PVRDMA_INTR_TYPE_MSIX;
		dev->intr.size = PVRDMA_MAX_INTERRUPTS;
	} else if (ret > 0) {
		ret = pci_enable_msix(pdev, dev->intr.msix_entry, ret);
		if (!ret) {
			dev->intr.type = PVRDMA_INTR_TYPE_MSIX;
			dev->intr.size = ret;
		} else {
			dev->intr.size = 0;
		}
	}

	dev_dbg(&pdev->dev, "using interrupt type %d, size %d\n",
		dev->intr.type, dev->intr.size);

	return ret;
}

static int pvrdma_alloc_intrs(struct pvrdma_dev *dev)
{
	int ret = 0;
	int i;
	struct pci_dev *pdev = dev->pdev;
	int ret = 0, i;

	if (pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX) &&
	    pvrdma_enable_msix(dev->pdev, dev)) {
		/* Try MSI */
		ret = pci_enable_msi(dev->pdev);
		if (!ret) {
			dev->intr.type = PVRDMA_INTR_TYPE_MSI;
		} else {
			/* Legacy INTR */
			dev->intr.type = PVRDMA_INTR_TYPE_INTX;
		}
	ret = pci_alloc_irq_vectors(pdev, 1, PVRDMA_MAX_INTERRUPTS,
			PCI_IRQ_MSIX);
	if (ret < 0) {
		ret = pci_alloc_irq_vectors(pdev, 1, 1,
				PCI_IRQ_MSI | PCI_IRQ_LEGACY);
		if (ret < 0)
			return ret;
	}
	dev->nr_vectors = ret;

	/* Request First IRQ */
	switch (dev->intr.type) {
	case PVRDMA_INTR_TYPE_INTX:
	case PVRDMA_INTR_TYPE_MSI:
		ret = request_irq(dev->pdev->irq, pvrdma_intr0_handler,
				  IRQF_SHARED, DRV_NAME, dev);
		if (ret) {
			dev_err(&dev->pdev->dev,
				"failed to request interrupt\n");
			goto disable_msi;
		}
		break;
	case PVRDMA_INTR_TYPE_MSIX:
		ret = request_irq(dev->intr.msix_entry[0].vector,
				  pvrdma_intr0_handler, 0, DRV_NAME, dev);
	ret = request_irq(pci_irq_vector(dev->pdev, 0), pvrdma_intr0_handler,
			pdev->msix_enabled ? 0 : IRQF_SHARED, DRV_NAME, dev);
	if (ret) {
		dev_err(&dev->pdev->dev,
			"failed to request interrupt 0\n");
			goto disable_msi;
		}
		dev->intr.enabled[0] = 1;
		break;
	default:
		/* Not reached */
		break;
		goto out_free_vectors;
	}

	/* For MSIX: request intr for each vector */
	if (dev->intr.size > 1) {
		ret = request_irq(dev->intr.msix_entry[1].vector,
				  pvrdma_intr1_handler, 0, DRV_NAME, dev);
		if (ret) {
			dev_err(&dev->pdev->dev,
				"failed to request interrupt 1\n");
			goto free_irq;
		}
		dev->intr.enabled[1] = 1;

		for (i = 2; i < dev->intr.size; i++) {
			ret = request_irq(dev->intr.msix_entry[i].vector,
					  pvrdma_intrx_handler, 0,
					  DRV_NAME, dev);
	for (i = 1; i < dev->nr_vectors; i++) {
		ret = request_irq(pci_irq_vector(dev->pdev, i),
				i == 1 ? pvrdma_intr1_handler :
					 pvrdma_intrx_handler,
				0, DRV_NAME, dev);
		if (ret) {
			dev_err(&dev->pdev->dev,
				"failed to request interrupt %d\n", i);
				goto free_irq;
			}
			dev->intr.enabled[i] = 1;
			goto free_irqs;
		}
	}

	return 0;

free_irq:
	pvrdma_free_irq(dev);
disable_msi:
	pvrdma_disable_msi_all(dev);
free_irqs:
	while (--i >= 0)
		free_irq(pci_irq_vector(dev->pdev, i), dev);
out_free_vectors:
	pci_free_irq_vectors(pdev);
	return ret;
}

@@ -1091,7 +995,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
	pvrdma_uar_table_cleanup(dev);
err_free_intrs:
	pvrdma_free_irq(dev);
	pvrdma_disable_msi_all(dev);
	pci_free_irq_vectors(pdev);
err_free_cq_ring:
	pvrdma_page_dir_cleanup(dev, &dev->cq_pdir);
err_free_async_ring:
@@ -1141,7 +1045,7 @@ static void pvrdma_pci_remove(struct pci_dev *pdev)

	pvrdma_disable_intrs(dev);
	pvrdma_free_irq(dev);
	pvrdma_disable_msi_all(dev);
	pci_free_irq_vectors(pdev);

	/* Deactivate pvrdma device */
	pvrdma_write_reg(dev, PVRDMA_REG_CTL, PVRDMA_DEVICE_CTL_RESET);