···8282has to request that the PCI layer set up the MSI capability for this8383device.84848585-4.2.1 pci_enable_msi8585+4.2.1 pci_enable_msi_range86868787-int pci_enable_msi(struct pci_dev *dev)8787+int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)88888989-A successful call allocates ONE interrupt to the device, regardless9090-of how many MSIs the device supports. The device is switched from9191-pin-based interrupt mode to MSI mode. The dev->irq number is changed9292-to a new number which represents the message signaled interrupt;9393-consequently, this function should be called before the driver calls9494-request_irq(), because an MSI is delivered via a vector that is9595-different from the vector of a pin-based interrupt.8989+This function allows a device driver to request any number of MSI9090+interrupts within specified range from 'minvec' to 'maxvec'.96919797-4.2.2 pci_enable_msi_block9898-9999-int pci_enable_msi_block(struct pci_dev *dev, int count)100100-101101-This variation on the above call allows a device driver to request multiple102102-MSIs. The MSI specification only allows interrupts to be allocated in103103-powers of two, up to a maximum of 2^5 (32).104104-105105-If this function returns 0, it has succeeded in allocating at least as many106106-interrupts as the driver requested (it may have allocated more in order107107-to satisfy the power-of-two requirement). In this case, the function108108-enables MSI on this device and updates dev->irq to be the lowest of109109-the new interrupts assigned to it. The other interrupts assigned to110110-the device are in the range dev->irq to dev->irq + count - 1.111111-112112-If this function returns a negative number, it indicates an error and113113-the driver should not attempt to request any more MSI interrupts for114114-this device. If this function returns a positive number, it is115115-less than 'count' and indicates the number of interrupts that could have116116-been allocated. In neither case is the irq value updated or the device117117-switched into MSI mode.118118-119119-The device driver must decide what action to take if120120-pci_enable_msi_block() returns a value less than the number requested.121121-For instance, the driver could still make use of fewer interrupts;122122-in this case the driver should call pci_enable_msi_block()123123-again. Note that it is not guaranteed to succeed, even when the124124-'count' has been reduced to the value returned from a previous call to125125-pci_enable_msi_block(). This is because there are multiple constraints126126-on the number of vectors that can be allocated; pci_enable_msi_block()127127-returns as soon as it finds any constraint that doesn't allow the128128-call to succeed.129129-130130-4.2.3 pci_enable_msi_block_auto131131-132132-int pci_enable_msi_block_auto(struct pci_dev *dev, int *count)133133-134134-This variation on pci_enable_msi() call allows a device driver to request135135-the maximum possible number of MSIs. The MSI specification only allows136136-interrupts to be allocated in powers of two, up to a maximum of 2^5 (32).137137-138138-If this function returns a positive number, it indicates that it has139139-succeeded and the returned value is the number of allocated interrupts. In140140-this case, the function enables MSI on this device and updates dev->irq to141141-be the lowest of the new interrupts assigned to it. The other interrupts142142-assigned to the device are in the range dev->irq to dev->irq + returned143143-value - 1.9292+If this function returns a positive number it indicates the number of9393+MSI interrupts that have been successfully allocated. In this case9494+the device is switched from pin-based interrupt mode to MSI mode and9595+updates dev->irq to be the lowest of the new interrupts assigned to it.9696+The other interrupts assigned to the device are in the range dev->irq9797+to dev->irq + returned value - 1. Device driver can use the returned9898+number of successfully allocated MSI interrupts to further allocate9999+and initialize device resources.144100145101If this function returns a negative number, it indicates an error and146102the driver should not attempt to request any more MSI interrupts for147103this device.148104149149-If the device driver needs to know the number of interrupts the device150150-supports it can pass the pointer count where that number is stored. The151151-device driver must decide what action to take if pci_enable_msi_block_auto()152152-succeeds, but returns a value less than the number of interrupts supported.153153-If the device driver does not need to know the number of interrupts154154-supported, it can set the pointer count to NULL.105105+This function should be called before the driver calls request_irq(),106106+because MSI interrupts are delivered via vectors that are different107107+from the vector of a pin-based interrupt.155108156156-4.2.4 pci_disable_msi109109+It is ideal if drivers can cope with a variable number of MSI interrupts;110110+there are many reasons why the platform may not be able to provide the111111+exact number that a driver asks for.112112+113113+There could be devices that can not operate with just any number of MSI114114+interrupts within a range. See chapter 4.3.1.3 to get the idea how to115115+handle such devices for MSI-X - the same logic applies to MSI.116116+117117+4.2.1.1 Maximum possible number of MSI interrupts118118+119119+The typical usage of MSI interrupts is to allocate as many vectors as120120+possible, likely up to the limit returned by pci_msi_vec_count() function:121121+122122+static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec)123123+{124124+ return pci_enable_msi_range(pdev, 1, nvec);125125+}126126+127127+Note the value of 'minvec' parameter is 1. As 'minvec' is inclusive,128128+the value of 0 would be meaningless and could result in error.129129+130130+Some devices have a minimal limit on number of MSI interrupts.131131+In this case the function could look like this:132132+133133+static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec)134134+{135135+ return pci_enable_msi_range(pdev, FOO_DRIVER_MINIMUM_NVEC, nvec);136136+}137137+138138+4.2.1.2 Exact number of MSI interrupts139139+140140+If a driver is unable or unwilling to deal with a variable number of MSI141141+interrupts it could request a particular number of interrupts by passing142142+that number to pci_enable_msi_range() function as both 'minvec' and 'maxvec'143143+parameters:144144+145145+static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec)146146+{147147+ return pci_enable_msi_range(pdev, nvec, nvec);148148+}149149+150150+4.2.1.3 Single MSI mode151151+152152+The most notorious example of the request type described above is153153+enabling the single MSI mode for a device. It could be done by passing154154+two 1s as 'minvec' and 'maxvec':155155+156156+static int foo_driver_enable_single_msi(struct pci_dev *pdev)157157+{158158+ return pci_enable_msi_range(pdev, 1, 1);159159+}160160+161161+4.2.2 pci_disable_msi157162158163void pci_disable_msi(struct pci_dev *dev)159164160160-This function should be used to undo the effect of pci_enable_msi() or161161-pci_enable_msi_block() or pci_enable_msi_block_auto(). Calling it restores162162-dev->irq to the pin-based interrupt number and frees the previously163163-allocated message signaled interrupt(s). The interrupt may subsequently be164164-assigned to another device, so drivers should not cache the value of165165-dev->irq.165165+This function should be used to undo the effect of pci_enable_msi_range().166166+Calling it restores dev->irq to the pin-based interrupt number and frees167167+the previously allocated MSIs. The interrupts may subsequently be assigned168168+to another device, so drivers should not cache the value of dev->irq.166169167170Before calling this function, a device driver must always call free_irq()168171on any interrupt for which it previously called request_irq().169172Failure to do so results in a BUG_ON(), leaving the device with170173MSI enabled and thus leaking its vector.174174+175175+4.2.3 pci_msi_vec_count176176+177177+int pci_msi_vec_count(struct pci_dev *dev)178178+179179+This function could be used to retrieve the number of MSI vectors the180180+device requested (via the Multiple Message Capable register). The MSI181181+specification only allows the returned value to be a power of two,182182+up to a maximum of 2^5 (32).183183+184184+If this function returns a negative number, it indicates the device is185185+not capable of sending MSIs.186186+187187+If this function returns a positive number, it indicates the maximum188188+number of MSI interrupt vectors that could be allocated.1711891721904.3 Using MSI-X173191···206188should assign interrupts; it is invalid to fill in two entries with the207189same number.208190209209-4.3.1 pci_enable_msix191191+4.3.1 pci_enable_msix_range210192211211-int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)193193+int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,194194+ int minvec, int maxvec)212195213213-Calling this function asks the PCI subsystem to allocate 'nvec' MSIs.196196+Calling this function asks the PCI subsystem to allocate any number of197197+MSI-X interrupts within specified range from 'minvec' to 'maxvec'.214198The 'entries' argument is a pointer to an array of msix_entry structs215215-which should be at least 'nvec' entries in size. On success, the216216-device is switched into MSI-X mode and the function returns 0.217217-The 'vector' member in each entry is populated with the interrupt number;199199+which should be at least 'maxvec' entries in size.200200+201201+On success, the device is switched into MSI-X mode and the function202202+returns the number of MSI-X interrupts that have been successfully203203+allocated. In this case the 'vector' member in entries numbered from204204+0 to the returned value - 1 is populated with the interrupt number;218205the driver should then call request_irq() for each 'vector' that it219206decides to use. The device driver is responsible for keeping track of the220207interrupts assigned to the MSI-X vectors so it can free them again later.208208+Device driver can use the returned number of successfully allocated MSI-X209209+interrupts to further allocate and initialize device resources.221210222211If this function returns a negative number, it indicates an error and223212the driver should not attempt to allocate any more MSI-X interrupts for224224-this device. If it returns a positive number, it indicates the maximum225225-number of interrupt vectors that could have been allocated. See example226226-below.213213+this device.227214228228-This function, in contrast with pci_enable_msi(), does not adjust215215+This function, in contrast with pci_enable_msi_range(), does not adjust229216dev->irq. The device will not generate interrupts for this interrupt230217number once MSI-X is enabled.231218···241218there are many reasons why the platform may not be able to provide the242219exact number that a driver asks for.243220244244-A request loop to achieve that might look like:221221+There could be devices that can not operate with just any number of MSI-X222222+interrupts within a range. E.g., an network adapter might need let's say223223+four vectors per each queue it provides. Therefore, a number of MSI-X224224+interrupts allocated should be a multiple of four. In this case interface225225+pci_enable_msix_range() can not be used alone to request MSI-X interrupts226226+(since it can allocate any number within the range, without any notion of227227+the multiple of four) and the device driver should master a custom logic228228+to request the required number of MSI-X interrupts.229229+230230+4.3.1.1 Maximum possible number of MSI-X interrupts231231+232232+The typical usage of MSI-X interrupts is to allocate as many vectors as233233+possible, likely up to the limit returned by pci_msix_vec_count() function:245234246235static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)247236{248248- while (nvec >= FOO_DRIVER_MINIMUM_NVEC) {249249- rc = pci_enable_msix(adapter->pdev,250250- adapter->msix_entries, nvec);251251- if (rc > 0)252252- nvec = rc;253253- else254254- return rc;237237+ return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,238238+ 1, nvec);239239+}240240+241241+Note the value of 'minvec' parameter is 1. As 'minvec' is inclusive,242242+the value of 0 would be meaningless and could result in error.243243+244244+Some devices have a minimal limit on number of MSI-X interrupts.245245+In this case the function could look like this:246246+247247+static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)248248+{249249+ return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,250250+ FOO_DRIVER_MINIMUM_NVEC, nvec);251251+}252252+253253+4.3.1.2 Exact number of MSI-X interrupts254254+255255+If a driver is unable or unwilling to deal with a variable number of MSI-X256256+interrupts it could request a particular number of interrupts by passing257257+that number to pci_enable_msix_range() function as both 'minvec' and 'maxvec'258258+parameters:259259+260260+static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)261261+{262262+ return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,263263+ nvec, nvec);264264+}265265+266266+4.3.1.3 Specific requirements to the number of MSI-X interrupts267267+268268+As noted above, there could be devices that can not operate with just any269269+number of MSI-X interrupts within a range. E.g., let's assume a device that270270+is only capable sending the number of MSI-X interrupts which is a power of271271+two. A routine that enables MSI-X mode for such device might look like this:272272+273273+/*274274+ * Assume 'minvec' and 'maxvec' are non-zero275275+ */276276+static int foo_driver_enable_msix(struct foo_adapter *adapter,277277+ int minvec, int maxvec)278278+{279279+ int rc;280280+281281+ minvec = roundup_pow_of_two(minvec);282282+ maxvec = rounddown_pow_of_two(maxvec);283283+284284+ if (minvec > maxvec)285285+ return -ERANGE;286286+287287+retry:288288+ rc = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,289289+ maxvec, maxvec);290290+ /*291291+ * -ENOSPC is the only error code allowed to be analized292292+ */293293+ if (rc == -ENOSPC) {294294+ if (maxvec == 1)295295+ return -ENOSPC;296296+297297+ maxvec /= 2;298298+299299+ if (minvec > maxvec)300300+ return -ENOSPC;301301+302302+ goto retry;255303 }256304257257- return -ENOSPC;305305+ return rc;258306}307307+308308+Note how pci_enable_msix_range() return value is analized for a fallback -309309+any error code other than -ENOSPC indicates a fatal error and should not310310+be retried.2593112603124.3.2 pci_disable_msix261313262314void pci_disable_msix(struct pci_dev *dev)263315264264-This function should be used to undo the effect of pci_enable_msix(). It frees265265-the previously allocated message signaled interrupts. The interrupts may316316+This function should be used to undo the effect of pci_enable_msix_range().317317+It frees the previously allocated MSI-X interrupts. The interrupts may266318subsequently be assigned to another device, so drivers should not cache267319the value of the 'vector' elements over a call to pci_disable_msix().268320···353255be accessed directly by the device driver. If the driver wishes to354256mask or unmask an interrupt, it should call disable_irq() / enable_irq().355257258258+4.3.4 pci_msix_vec_count259259+260260+int pci_msix_vec_count(struct pci_dev *dev)261261+262262+This function could be used to retrieve number of entries in the device263263+MSI-X table.264264+265265+If this function returns a negative number, it indicates the device is266266+not capable of sending MSI-Xs.267267+268268+If this function returns a positive number, it indicates the maximum269269+number of MSI-X interrupt vectors that could be allocated.270270+3562714.4 Handling devices implementing both MSI and MSI-X capabilities357272358273If a device implements both MSI and MSI-X capabilities, it can359274run in either MSI mode or MSI-X mode, but not both simultaneously.360275This is a requirement of the PCI spec, and it is enforced by the361361-PCI layer. Calling pci_enable_msi() when MSI-X is already enabled or362362-pci_enable_msix() when MSI is already enabled results in an error.363363-If a device driver wishes to switch between MSI and MSI-X at runtime,364364-it must first quiesce the device, then switch it back to pin-interrupt365365-mode, before calling pci_enable_msi() or pci_enable_msix() and resuming366366-operation. This is not expected to be a common operation but may be367367-useful for debugging or testing during development.276276+PCI layer. Calling pci_enable_msi_range() when MSI-X is already277277+enabled or pci_enable_msix_range() when MSI is already enabled278278+results in an error. If a device driver wishes to switch between MSI279279+and MSI-X at runtime, it must first quiesce the device, then switch280280+it back to pin-interrupt mode, before calling pci_enable_msi_range()281281+or pci_enable_msix_range() and resuming operation. This is not expected282282+to be a common operation but may be useful for debugging or testing283283+during development.3682843692854.5 Considerations when using MSIs370286···493381to bridges between the PCI root and the device, MSIs are disabled.494382495383It is also worth checking the device driver to see whether it supports MSIs.496496-For example, it may contain calls to pci_enable_msi(), pci_enable_msix() or497497-pci_enable_msi_block().384384+For example, it may contain calls to pci_enable_msi_range() or385385+pci_enable_msix_range().
+35-21
drivers/ata/ahci.c
···10951095{}10961096#endif1097109710981098-int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)10981098+int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,10991099+ struct ahci_host_priv *hpriv)10991100{11001100- int rc;11011101- unsigned int maxvec;11011101+ int rc, nvec;1102110211031103- if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) {11041104- rc = pci_enable_msi_block_auto(pdev, &maxvec);11051105- if (rc > 0) {11061106- if ((rc == maxvec) || (rc == 1))11071107- return rc;11081108- /*11091109- * Assume that advantage of multipe MSIs is negated,11101110- * so fallback to single MSI mode to save resources11111111- */11121112- pci_disable_msi(pdev);11131113- if (!pci_enable_msi(pdev))11141114- return 1;11151115- }11161116- }11031103+ if (hpriv->flags & AHCI_HFLAG_NO_MSI)11041104+ goto intx;1117110511061106+ rc = pci_msi_vec_count(pdev);11071107+ if (rc < 0)11081108+ goto intx;11091109+11101110+ /*11111111+ * If number of MSIs is less than number of ports then Sharing Last11121112+ * Message mode could be enforced. In this case assume that advantage11131113+ * of multipe MSIs is negated and use single MSI mode instead.11141114+ */11151115+ if (rc < n_ports)11161116+ goto single_msi;11171117+11181118+ nvec = rc;11191119+ rc = pci_enable_msi_block(pdev, nvec);11201120+ if (rc)11211121+ goto intx;11221122+11231123+ return nvec;11241124+11251125+single_msi:11261126+ rc = pci_enable_msi(pdev);11271127+ if (rc)11281128+ goto intx;11291129+ return 1;11301130+11311131+intx:11181132 pci_intx(pdev, 1);11191133 return 0;11201134}···1295128112961282 hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];1297128312981298- n_msis = ahci_init_interrupts(pdev, hpriv);12991299- if (n_msis > 1)13001300- hpriv->flags |= AHCI_HFLAG_MULTI_MSI;13011301-13021284 /* save initial config */13031285 ahci_pci_save_initial_config(pdev, hpriv);13041286···13481338 * both CAP.NP and port_map.13491339 */13501340 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));13411341+13421342+ n_msis = ahci_init_interrupts(pdev, n_ports, hpriv);13431343+ if (n_msis > 1)13441344+ hpriv->flags |= AHCI_HFLAG_MULTI_MSI;1351134513521346 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);13531347 if (!host)
+116-34
drivers/pci/msi.c
···852852}853853854854/**855855+ * pci_msi_vec_count - Return the number of MSI vectors a device can send856856+ * @dev: device to report about857857+ *858858+ * This function returns the number of MSI vectors a device requested via859859+ * Multiple Message Capable register. It returns a negative errno if the860860+ * device is not capable sending MSI interrupts. Otherwise, the call succeeds861861+ * and returns a power of two, up to a maximum of 2^5 (32), according to the862862+ * MSI specification.863863+ **/864864+int pci_msi_vec_count(struct pci_dev *dev)865865+{866866+ int ret;867867+ u16 msgctl;868868+869869+ if (!dev->msi_cap)870870+ return -EINVAL;871871+872872+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);873873+ ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);874874+875875+ return ret;876876+}877877+EXPORT_SYMBOL(pci_msi_vec_count);878878+879879+/**855880 * pci_enable_msi_block - configure device's MSI capability structure856881 * @dev: device to configure857882 * @nvec: number of interrupts to configure···892867int pci_enable_msi_block(struct pci_dev *dev, int nvec)893868{894869 int status, maxvec;895895- u16 msgctl;896870897897- if (!dev->msi_cap || dev->current_state != PCI_D0)871871+ if (dev->current_state != PCI_D0)898872 return -EINVAL;899873900900- pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);901901- maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);874874+ maxvec = pci_msi_vec_count(dev);875875+ if (maxvec < 0)876876+ return maxvec;902877 if (nvec > maxvec)903878 return maxvec;904879···919894 return status;920895}921896EXPORT_SYMBOL(pci_enable_msi_block);922922-923923-int pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec)924924-{925925- int ret, nvec;926926- u16 msgctl;927927-928928- if (!dev->msi_cap || dev->current_state != PCI_D0)929929- return -EINVAL;930930-931931- pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);932932- ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);933933-934934- if (maxvec)935935- *maxvec = ret;936936-937937- do {938938- nvec = ret;939939- ret = pci_enable_msi_block(dev, nvec);940940- } while (ret > 0);941941-942942- if (ret < 0)943943- return ret;944944- return nvec;945945-}946946-EXPORT_SYMBOL(pci_enable_msi_block_auto);947897948898void pci_msi_shutdown(struct pci_dev *dev)949899{···957957EXPORT_SYMBOL(pci_disable_msi);958958959959/**960960- * pci_msix_table_size - return the number of device's MSI-X table entries960960+ * pci_msix_vec_count - return the number of device's MSI-X table entries961961 * @dev: pointer to the pci_dev data structure of MSI-X device function962962- */963963-int pci_msix_table_size(struct pci_dev *dev)962962+963963+ * This function returns the number of device's MSI-X table entries and964964+ * therefore the number of MSI-X vectors device is capable of sending.965965+ * It returns a negative errno if the device is not capable of sending MSI-X966966+ * interrupts.967967+ **/968968+int pci_msix_vec_count(struct pci_dev *dev)964969{965970 u16 control;966971967972 if (!dev->msix_cap)968968- return 0;973973+ return -EINVAL;969974970975 pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);971976 return msix_table_size(control);972977}978978+EXPORT_SYMBOL(pci_msix_vec_count);973979974980/**975981 * pci_enable_msix - configure device's MSI-X capability structure···1004998 if (status)1005999 return status;1006100010071007- nr_entries = pci_msix_table_size(dev);10011001+ nr_entries = pci_msix_vec_count(dev);10021002+ if (nr_entries < 0)10031003+ return nr_entries;10081004 if (nvec > nr_entries)10091005 return nr_entries;10101006···11111103 if (dev->msix_cap)11121104 msix_set_enable(dev, 0);11131105}11061106+11071107+/**11081108+ * pci_enable_msi_range - configure device's MSI capability structure11091109+ * @dev: device to configure11101110+ * @minvec: minimal number of interrupts to configure11111111+ * @maxvec: maximum number of interrupts to configure11121112+ *11131113+ * This function tries to allocate a maximum possible number of interrupts in a11141114+ * range between @minvec and @maxvec. It returns a negative errno if an error11151115+ * occurs. If it succeeds, it returns the actual number of interrupts allocated11161116+ * and updates the @dev's irq member to the lowest new interrupt number;11171117+ * the other interrupt numbers allocated to this device are consecutive.11181118+ **/11191119+int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)11201120+{11211121+ int nvec = maxvec;11221122+ int rc;11231123+11241124+ if (maxvec < minvec)11251125+ return -ERANGE;11261126+11271127+ do {11281128+ rc = pci_enable_msi_block(dev, nvec);11291129+ if (rc < 0) {11301130+ return rc;11311131+ } else if (rc > 0) {11321132+ if (rc < minvec)11331133+ return -ENOSPC;11341134+ nvec = rc;11351135+ }11361136+ } while (rc);11371137+11381138+ return nvec;11391139+}11401140+EXPORT_SYMBOL(pci_enable_msi_range);11411141+11421142+/**11431143+ * pci_enable_msix_range - configure device's MSI-X capability structure11441144+ * @dev: pointer to the pci_dev data structure of MSI-X device function11451145+ * @entries: pointer to an array of MSI-X entries11461146+ * @minvec: minimum number of MSI-X irqs requested11471147+ * @maxvec: maximum number of MSI-X irqs requested11481148+ *11491149+ * Setup the MSI-X capability structure of device function with a maximum11501150+ * possible number of interrupts in the range between @minvec and @maxvec11511151+ * upon its software driver call to request for MSI-X mode enabled on its11521152+ * hardware device function. It returns a negative errno if an error occurs.11531153+ * If it succeeds, it returns the actual number of interrupts allocated and11541154+ * indicates the successful configuration of MSI-X capability structure11551155+ * with new allocated MSI-X interrupts.11561156+ **/11571157+int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,11581158+ int minvec, int maxvec)11591159+{11601160+ int nvec = maxvec;11611161+ int rc;11621162+11631163+ if (maxvec < minvec)11641164+ return -ERANGE;11651165+11661166+ do {11671167+ rc = pci_enable_msix(dev, entries, nvec);11681168+ if (rc < 0) {11691169+ return rc;11701170+ } else if (rc > 0) {11711171+ if (rc < minvec)11721172+ return -ENOSPC;11731173+ nvec = rc;11741174+ }11751175+ } while (rc);11761176+11771177+ return nvec;11781178+}11791179+EXPORT_SYMBOL(pci_enable_msix_range);
+4-3
drivers/pci/pcie/portdrv_core.c
···7979 u16 reg16;8080 u32 reg32;81818282- nr_entries = pci_msix_table_size(dev);8383- if (!nr_entries)8484- return -EINVAL;8282+ nr_entries = pci_msix_vec_count(dev);8383+ if (nr_entries < 0)8484+ return nr_entries;8585+ BUG_ON(!nr_entries);8586 if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES)8687 nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES;8788
+20-7
include/linux/pci.h
···116611661167116711681168#ifndef CONFIG_PCI_MSI11691169-static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)11691169+static inline int pci_msi_vec_count(struct pci_dev *dev)11701170{11711171 return -ENOSYS;11721172}1173117311741174-static inline int11751175-pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec)11741174+static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)11761175{11771176 return -ENOSYS;11781177}···11811182static inline void pci_disable_msi(struct pci_dev *dev)11821183{ }1183118411841184-static inline int pci_msix_table_size(struct pci_dev *dev)11851185+static inline int pci_msix_vec_count(struct pci_dev *dev)11851186{11861186- return 0;11871187+ return -ENOSYS;11871188}11881189static inline int pci_enable_msix(struct pci_dev *dev,11891190 struct msix_entry *entries, int nvec)···12051206{12061207 return 0;12071208}12091209+12101210+static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec,12111211+ int maxvec)12121212+{12131213+ return -ENOSYS;12141214+}12151215+static inline int pci_enable_msix_range(struct pci_dev *dev,12161216+ struct msix_entry *entries, int minvec, int maxvec)12171217+{12181218+ return -ENOSYS;12191219+}12081220#else12211221+int pci_msi_vec_count(struct pci_dev *dev);12091222int pci_enable_msi_block(struct pci_dev *dev, int nvec);12101210-int pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec);12111223void pci_msi_shutdown(struct pci_dev *dev);12121224void pci_disable_msi(struct pci_dev *dev);12131213-int pci_msix_table_size(struct pci_dev *dev);12251225+int pci_msix_vec_count(struct pci_dev *dev);12141226int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);12151227void pci_msix_shutdown(struct pci_dev *dev);12161228void pci_disable_msix(struct pci_dev *dev);12171229void msi_remove_pci_irq_vectors(struct pci_dev *dev);12181230void pci_restore_msi_state(struct pci_dev *dev);12191231int pci_msi_enabled(void);12321232+int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);12331233+int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,12341234+ int minvec, int maxvec);12201235#endif1221123612221237#ifdef CONFIG_PCIEPORTBUS