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

Commit b60b869d authored by Alexander Gordeev's avatar Alexander Gordeev Committed by David S. Miller
Browse files

vmxnet3: Fix MSI-X/MSI enablement code



This update cleans up the MSI-X/MSI enablement code, fixes
vmxnet3_acquire_msix_vectors() invalid return values and
enables a dead code in case VMXNET3_LINUX_MIN_MSIX_VECT
MSI-X vectors were allocated.

Signed-off-by: default avatarAlexander Gordeev <agordeev@redhat.com>
Cc: Shreyas Bhatewara <sbhatewara@vmware.com>
Cc: pv-drivers@vmware.com
Cc: netdev@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9e7df17e
Loading
Loading
Loading
Loading
+46 −55
Original line number Original line Diff line number Diff line
@@ -2729,47 +2729,44 @@ vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)
/*
/*
 * Enable MSIx vectors.
 * Enable MSIx vectors.
 * Returns :
 * Returns :
 *	0 on successful enabling of required vectors,
 *	VMXNET3_LINUX_MIN_MSIX_VECT when only minimum number of vectors required
 *	VMXNET3_LINUX_MIN_MSIX_VECT when only minimum number of vectors required
 *	 could be enabled.
 *	 were enabled.
 *	number of vectors which can be enabled otherwise (this number is smaller
 *	number of vectors which were enabled otherwise (this number is greater
 *	 than VMXNET3_LINUX_MIN_MSIX_VECT)
 *	 than VMXNET3_LINUX_MIN_MSIX_VECT)
 */
 */


static int
static int
vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter,
vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter, int nvec)
			     int vectors)
{
{
	int err = 0, vector_threshold;
	do {
	vector_threshold = VMXNET3_LINUX_MIN_MSIX_VECT;
		int err = pci_enable_msix(adapter->pdev,

					  adapter->intr.msix_entries, nvec);
	while (vectors >= vector_threshold) {
		err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries,
				      vectors);
		if (!err) {
		if (!err) {
			adapter->intr.num_intrs = vectors;
			return nvec;
			return 0;
		} else if (err < 0) {
		} else if (err < 0) {
			dev_err(&adapter->netdev->dev,
			dev_err(&adapter->netdev->dev,
				"Failed to enable MSI-X, error: %d\n", err);
				"Failed to enable MSI-X, error: %d\n", err);
			vectors = 0;
			return err;
		} else if (err < vector_threshold) {
		} else if (err < VMXNET3_LINUX_MIN_MSIX_VECT) {
			break;
			dev_info(&adapter->pdev->dev,
				 "Number of MSI-X which can be allocated "
				 "is lower than min threshold required.\n");
			return -ENOSPC;
		} else {
		} else {
			/* If fails to enable required number of MSI-x vectors
			/* If fails to enable required number of MSI-x vectors
			 * try enabling minimum number of vectors required.
			 * try enabling minimum number of vectors required.
			 */
			 */
			dev_err(&adapter->netdev->dev,
			dev_err(&adapter->netdev->dev,
				"Failed to enable %d MSI-X, trying %d instead\n",
				"Failed to enable %d MSI-X, trying %d\n",
				    vectors, vector_threshold);
				nvec, VMXNET3_LINUX_MIN_MSIX_VECT);
			vectors = vector_threshold;
			nvec = VMXNET3_LINUX_MIN_MSIX_VECT;
		}
		}
		}
	} while (nvec >= VMXNET3_LINUX_MIN_MSIX_VECT);


	dev_info(&adapter->pdev->dev,
	/*
		 "Number of MSI-X interrupts which can be allocated "
	 * Should never get here
		 "is lower than min threshold required.\n");
	 */
	return err;
	return -ENOSPC;
}
}




@@ -2796,56 +2793,50 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)


#ifdef CONFIG_PCI_MSI
#ifdef CONFIG_PCI_MSI
	if (adapter->intr.type == VMXNET3_IT_MSIX) {
	if (adapter->intr.type == VMXNET3_IT_MSIX) {
		int vector, err = 0;
		int i, nvec;


		adapter->intr.num_intrs = (adapter->share_intr ==
		nvec  = adapter->share_intr == VMXNET3_INTR_TXSHARE ?
					   VMXNET3_INTR_TXSHARE) ? 1 :
			1 : adapter->num_tx_queues;
					   adapter->num_tx_queues;
		nvec += adapter->share_intr == VMXNET3_INTR_BUDDYSHARE ?
		adapter->intr.num_intrs += (adapter->share_intr ==
			0 : adapter->num_rx_queues;
					   VMXNET3_INTR_BUDDYSHARE) ? 0 :
		nvec += 1;	/* for link event */
					   adapter->num_rx_queues;
		nvec = nvec > VMXNET3_LINUX_MIN_MSIX_VECT ?
		adapter->intr.num_intrs += 1;		/* for link event */
		       nvec : VMXNET3_LINUX_MIN_MSIX_VECT;


		adapter->intr.num_intrs = (adapter->intr.num_intrs >
		for (i = 0; i < nvec; i++)
					   VMXNET3_LINUX_MIN_MSIX_VECT
			adapter->intr.msix_entries[i].entry = i;
					   ? adapter->intr.num_intrs :

					   VMXNET3_LINUX_MIN_MSIX_VECT);
		nvec = vmxnet3_acquire_msix_vectors(adapter, nvec);

		if (nvec < 0)
		for (vector = 0; vector < adapter->intr.num_intrs; vector++)
			goto msix_err;
			adapter->intr.msix_entries[vector].entry = vector;


		err = vmxnet3_acquire_msix_vectors(adapter,
						   adapter->intr.num_intrs);
		/* If we cannot allocate one MSIx vector per queue
		/* If we cannot allocate one MSIx vector per queue
		 * then limit the number of rx queues to 1
		 * then limit the number of rx queues to 1
		 */
		 */
		if (err == VMXNET3_LINUX_MIN_MSIX_VECT) {
		if (nvec == VMXNET3_LINUX_MIN_MSIX_VECT) {
			if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE
			if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE
			    || adapter->num_rx_queues != 1) {
			    || adapter->num_rx_queues != 1) {
				adapter->share_intr = VMXNET3_INTR_TXSHARE;
				adapter->share_intr = VMXNET3_INTR_TXSHARE;
				netdev_err(adapter->netdev,
				netdev_err(adapter->netdev,
					   "Number of rx queues : 1\n");
					   "Number of rx queues : 1\n");
				adapter->num_rx_queues = 1;
				adapter->num_rx_queues = 1;
				adapter->intr.num_intrs =
						VMXNET3_LINUX_MIN_MSIX_VECT;
			}
			}
			return;
		}
		}
		if (!err)

		adapter->intr.num_intrs = nvec;
		return;
		return;


msix_err:
		/* If we cannot allocate MSIx vectors use only one rx queue */
		/* If we cannot allocate MSIx vectors use only one rx queue */
		dev_info(&adapter->pdev->dev,
		dev_info(&adapter->pdev->dev,
			 "Failed to enable MSI-X, error %d. "
			 "Failed to enable MSI-X, error %d. "
			 "Limiting #rx queues to 1, try MSI.\n", err);
			 "Limiting #rx queues to 1, try MSI.\n", nvec);


		adapter->intr.type = VMXNET3_IT_MSI;
		adapter->intr.type = VMXNET3_IT_MSI;
	}
	}


	if (adapter->intr.type == VMXNET3_IT_MSI) {
	if (adapter->intr.type == VMXNET3_IT_MSI) {
		int err;
		if (!pci_enable_msi(adapter->pdev)) {
		err = pci_enable_msi(adapter->pdev);
		if (!err) {
			adapter->num_rx_queues = 1;
			adapter->num_rx_queues = 1;
			adapter->intr.num_intrs = 1;
			adapter->intr.num_intrs = 1;
			return;
			return;