diff options
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_pcie.c')
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_pcie.c | 55 | 
1 files changed, 28 insertions, 27 deletions
| diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index c8d9c4ab142b..61a0046efb76 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt,  			   struct qib_msix_entry *qib_msix_entry)  {  	int ret; -	u32 tabsize = 0; -	u16 msix_flags; +	int nvec = *msixcnt;  	struct msix_entry *msix_entry;  	int i; +	ret = pci_msix_vec_count(dd->pcidev); +	if (ret < 0) +		goto do_intx; + +	nvec = min(nvec, ret); +  	/* We can't pass qib_msix_entry array to qib_msix_setup  	 * so use a dummy msix_entry array and copy the allocated  	 * irq back to the qib_msix_entry array. */ -	msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL); -	if (!msix_entry) { -		ret = -ENOMEM; +	msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL); +	if (!msix_entry)  		goto do_intx; -	} -	for (i = 0; i < *msixcnt; i++) + +	for (i = 0; i < nvec; i++)  		msix_entry[i] = qib_msix_entry[i].msix; -	pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags); -	tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE); -	if (tabsize > *msixcnt) -		tabsize = *msixcnt; -	ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); -	if (ret > 0) { -		tabsize = ret; -		ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); -	} -do_intx: -	if (ret) { -		qib_dev_err(dd, -			"pci_enable_msix %d vectors failed: %d, falling back to INTx\n", -			tabsize, ret); -		tabsize = 0; -	} -	for (i = 0; i < tabsize; i++) +	ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); +	if (ret < 0) +		goto free_msix_entry; +	else +		nvec = ret; + +	for (i = 0; i < nvec; i++)  		qib_msix_entry[i].msix = msix_entry[i]; +  	kfree(msix_entry); -	*msixcnt = tabsize; +	*msixcnt = nvec; +	return; -	if (ret) -		qib_enable_intx(dd->pcidev); +free_msix_entry: +	kfree(msix_entry); +do_intx: +	qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, " +			"falling back to INTx\n", nvec, ret); +	*msixcnt = 0; +	qib_enable_intx(dd->pcidev);  }  /** | 

