2021-08-20 13:54:26

by Jan Kiszka

[permalink] [raw]
Subject: [PATCH] PCI/portdrv: Do not setup up IRQs if there are no users

From: Jan Kiszka <[email protected]>

Avoid registering service IRQs if there is no service that offers them
or no driver to register a handler against them. This saves IRQ vectors
when they are limited (e.g. on x86) and also avoids that spurious events
could hit a missing handler. Such spurious events need to be generated
by the Jailhouse hypervisor for active MSI vectors when enabling or
disabling itself.

Signed-off-by: Jan Kiszka <[email protected]>
---
drivers/pci/pcie/portdrv_core.c | 40 ++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index e1fed6649c41..2a702ccffaac 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -312,7 +312,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
*/
int pcie_port_device_register(struct pci_dev *dev)
{
- int status, capabilities, i, nr_service;
+ int status, capabilities, irq_services, i, nr_service;
int irqs[PCIE_PORT_DEVICE_MAXSERVICES];

/* Enable PCI Express port device */
@@ -326,18 +326,32 @@ int pcie_port_device_register(struct pci_dev *dev)
return 0;

pci_set_master(dev);
- /*
- * Initialize service irqs. Don't use service devices that
- * require interrupts if there is no way to generate them.
- * However, some drivers may have a polling mode (e.g. pciehp_poll_mode)
- * that can be used in the absence of irqs. Allow them to determine
- * if that is to be used.
- */
- status = pcie_init_service_irqs(dev, irqs, capabilities);
- if (status) {
- capabilities &= PCIE_PORT_SERVICE_HP;
- if (!capabilities)
- goto error_disable;
+
+ irq_services = 0;
+ if (IS_ENABLED(CONFIG_PCIE_PME))
+ irq_services |= PCIE_PORT_SERVICE_PME;
+ if (IS_ENABLED(CONFIG_PCIEAER))
+ irq_services |= PCIE_PORT_SERVICE_AER;
+ if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
+ irq_services |= PCIE_PORT_SERVICE_HP;
+ if (IS_ENABLED(CONFIG_PCIE_DPC))
+ irq_services |= PCIE_PORT_SERVICE_DPC;
+ irq_services &= capabilities;
+
+ if (irq_services) {
+ /*
+ * Initialize service irqs. Don't use service devices that
+ * require interrupts if there is no way to generate them.
+ * However, some drivers may have a polling mode (e.g.
+ * pciehp_poll_mode) that can be used in the absence of irqs.
+ * Allow them to determine if that is to be used.
+ */
+ status = pcie_init_service_irqs(dev, irqs, irq_services);
+ if (status) {
+ irq_services &= PCIE_PORT_SERVICE_HP;
+ if (!irq_services)
+ goto error_disable;
+ }
}

/* Allocate child services if any */
--
2.31.1


2021-08-20 14:46:42

by Lukas Wunner

[permalink] [raw]
Subject: Re: [PATCH] PCI/portdrv: Do not setup up IRQs if there are no users

On Fri, Aug 20, 2021 at 03:52:18PM +0200, Jan Kiszka wrote:
> --- a/drivers/pci/pcie/portdrv_core.c
> +++ b/drivers/pci/pcie/portdrv_core.c
> @@ -312,7 +312,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
> */
> int pcie_port_device_register(struct pci_dev *dev)
> {
> - int status, capabilities, i, nr_service;
> + int status, capabilities, irq_services, i, nr_service;
> int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
>
> /* Enable PCI Express port device */
> @@ -326,18 +326,32 @@ int pcie_port_device_register(struct pci_dev *dev)
> return 0;
>
> pci_set_master(dev);
> - /*
> - * Initialize service irqs. Don't use service devices that
> - * require interrupts if there is no way to generate them.
> - * However, some drivers may have a polling mode (e.g. pciehp_poll_mode)
> - * that can be used in the absence of irqs. Allow them to determine
> - * if that is to be used.
> - */
> - status = pcie_init_service_irqs(dev, irqs, capabilities);
> - if (status) {
> - capabilities &= PCIE_PORT_SERVICE_HP;
> - if (!capabilities)
> - goto error_disable;
> +
> + irq_services = 0;
> + if (IS_ENABLED(CONFIG_PCIE_PME))
> + irq_services |= PCIE_PORT_SERVICE_PME;
> + if (IS_ENABLED(CONFIG_PCIEAER))
> + irq_services |= PCIE_PORT_SERVICE_AER;
> + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
> + irq_services |= PCIE_PORT_SERVICE_HP;
> + if (IS_ENABLED(CONFIG_PCIE_DPC))
> + irq_services |= PCIE_PORT_SERVICE_DPC;
> + irq_services &= capabilities;

get_port_device_capability() would seem like a more natural place
to put these checks.

Note that your check for CONFIG_PCIEAER is superfluous due to
the "#ifdef CONFIG_PCIEAER" in get_port_device_capability().

Thanks,

Lukas

2021-08-20 14:49:43

by Jan Kiszka

[permalink] [raw]
Subject: Re: [PATCH] PCI/portdrv: Do not setup up IRQs if there are no users

On 20.08.21 16:45, Lukas Wunner wrote:
> On Fri, Aug 20, 2021 at 03:52:18PM +0200, Jan Kiszka wrote:
>> --- a/drivers/pci/pcie/portdrv_core.c
>> +++ b/drivers/pci/pcie/portdrv_core.c
>> @@ -312,7 +312,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
>> */
>> int pcie_port_device_register(struct pci_dev *dev)
>> {
>> - int status, capabilities, i, nr_service;
>> + int status, capabilities, irq_services, i, nr_service;
>> int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
>>
>> /* Enable PCI Express port device */
>> @@ -326,18 +326,32 @@ int pcie_port_device_register(struct pci_dev *dev)
>> return 0;
>>
>> pci_set_master(dev);
>> - /*
>> - * Initialize service irqs. Don't use service devices that
>> - * require interrupts if there is no way to generate them.
>> - * However, some drivers may have a polling mode (e.g. pciehp_poll_mode)
>> - * that can be used in the absence of irqs. Allow them to determine
>> - * if that is to be used.
>> - */
>> - status = pcie_init_service_irqs(dev, irqs, capabilities);
>> - if (status) {
>> - capabilities &= PCIE_PORT_SERVICE_HP;
>> - if (!capabilities)
>> - goto error_disable;
>> +
>> + irq_services = 0;
>> + if (IS_ENABLED(CONFIG_PCIE_PME))
>> + irq_services |= PCIE_PORT_SERVICE_PME;
>> + if (IS_ENABLED(CONFIG_PCIEAER))
>> + irq_services |= PCIE_PORT_SERVICE_AER;
>> + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
>> + irq_services |= PCIE_PORT_SERVICE_HP;
>> + if (IS_ENABLED(CONFIG_PCIE_DPC))
>> + irq_services |= PCIE_PORT_SERVICE_DPC;
>> + irq_services &= capabilities;
>
> get_port_device_capability() would seem like a more natural place
> to put these checks.
>
> Note that your check for CONFIG_PCIEAER is superfluous due to
> the "#ifdef CONFIG_PCIEAER" in get_port_device_capability().
>

Not all service drivers need IRQs. That's why the test is separate. See
also the comment I shuffled around.

Jan

--
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux

2021-08-29 08:30:55

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] PCI/portdrv: Do not setup up IRQs if there are no users

Hi Jan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on pci/next]
[also build test WARNING on v5.14-rc6 next-20210820]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Jan-Kiszka/PCI-portdrv-Do-not-setup-up-IRQs-if-there-are-no-users/20210820-215311
base: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
:::::: branch date: 2 days ago
:::::: commit date: 2 days ago
config: arm-randconfig-c002-20210822 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9e9d70591e72fc6762b4b9a226b68ed1307419bf)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install binutils-arm-linux-gnueabi
# https://github.com/0day-ci/linux/commit/30b9aea30a820b153bb866daf79d1738628934d8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Jan-Kiszka/PCI-portdrv-Do-not-setup-up-IRQs-if-there-are-no-users/20210820-215311
git checkout 30b9aea30a820b153bb866daf79d1738628934d8
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm clang-analyzer

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>


clang-analyzer warnings: (new ones prefixed by >>)

>> drivers/pci/pcie/portdrv_core.c:364:8: warning: 3rd function call argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
if (!pcie_device_init(dev, service, irqs[i]))
^ ~~~~~~~
drivers/pci/pcie/portdrv_core.c:341:6: note: 'irq_services' is 0
if (irq_services) {
^~~~~~~~~~~~
drivers/pci/pcie/portdrv_core.c:341:2: note: Taking false branch
if (irq_services) {
^
drivers/pci/pcie/portdrv_core.c:360:2: note: Loop condition is true. Entering loop body
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
^
drivers/pci/pcie/portdrv_core.c:362:3: note: Taking false branch
if (!(capabilities & service))
^
drivers/pci/pcie/portdrv_core.c:364:8: warning: 3rd function call argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
if (!pcie_device_init(dev, service, irqs[i]))
^ ~~~~~~~

vim +364 drivers/pci/pcie/portdrv_core.c

8f3acca9acec15 Bjorn Helgaas 2013-12-19 305
facf6d1627a33b Rafael J. Wysocki 2009-01-01 306 /**
facf6d1627a33b Rafael J. Wysocki 2009-01-01 307 * pcie_port_device_register - register PCI Express port
facf6d1627a33b Rafael J. Wysocki 2009-01-01 308 * @dev: PCI Express port to register
facf6d1627a33b Rafael J. Wysocki 2009-01-01 309 *
facf6d1627a33b Rafael J. Wysocki 2009-01-01 310 * Allocate the port extension structure and register services associated with
facf6d1627a33b Rafael J. Wysocki 2009-01-01 311 * the port.
facf6d1627a33b Rafael J. Wysocki 2009-01-01 312 */
^1da177e4c3f41 Linus Torvalds 2005-04-16 313 int pcie_port_device_register(struct pci_dev *dev)
^1da177e4c3f41 Linus Torvalds 2005-04-16 314 {
30b9aea30a820b Jan Kiszka 2021-08-20 315 int status, capabilities, irq_services, i, nr_service;
dc5351784eb36f Kenji Kaneshige 2009-11-25 316 int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
^1da177e4c3f41 Linus Torvalds 2005-04-16 317
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 318 /* Enable PCI Express port device */
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 319 status = pci_enable_device(dev);
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 320 if (status)
694f88ef7ada0d Kenji Kaneshige 2009-11-25 321 return status;
fe31e69740eddc Rafael J. Wysocki 2010-12-19 322
fe31e69740eddc Rafael J. Wysocki 2010-12-19 323 /* Get and check PCI Express port services */
fe31e69740eddc Rafael J. Wysocki 2010-12-19 324 capabilities = get_port_device_capability(dev);
eca67315e0e0d5 Naga Chumbalkar 2011-03-21 325 if (!capabilities)
fe31e69740eddc Rafael J. Wysocki 2010-12-19 326 return 0;
fe31e69740eddc Rafael J. Wysocki 2010-12-19 327
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 328 pci_set_master(dev);
30b9aea30a820b Jan Kiszka 2021-08-20 329
30b9aea30a820b Jan Kiszka 2021-08-20 330 irq_services = 0;
30b9aea30a820b Jan Kiszka 2021-08-20 331 if (IS_ENABLED(CONFIG_PCIE_PME))
30b9aea30a820b Jan Kiszka 2021-08-20 332 irq_services |= PCIE_PORT_SERVICE_PME;
30b9aea30a820b Jan Kiszka 2021-08-20 333 if (IS_ENABLED(CONFIG_PCIEAER))
30b9aea30a820b Jan Kiszka 2021-08-20 334 irq_services |= PCIE_PORT_SERVICE_AER;
30b9aea30a820b Jan Kiszka 2021-08-20 335 if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
30b9aea30a820b Jan Kiszka 2021-08-20 336 irq_services |= PCIE_PORT_SERVICE_HP;
30b9aea30a820b Jan Kiszka 2021-08-20 337 if (IS_ENABLED(CONFIG_PCIE_DPC))
30b9aea30a820b Jan Kiszka 2021-08-20 338 irq_services |= PCIE_PORT_SERVICE_DPC;
30b9aea30a820b Jan Kiszka 2021-08-20 339 irq_services &= capabilities;
30b9aea30a820b Jan Kiszka 2021-08-20 340
30b9aea30a820b Jan Kiszka 2021-08-20 341 if (irq_services) {
f118c0c3cff4fe Rafael J. Wysocki 2009-01-13 342 /*
dc5351784eb36f Kenji Kaneshige 2009-11-25 343 * Initialize service irqs. Don't use service devices that
dc5351784eb36f Kenji Kaneshige 2009-11-25 344 * require interrupts if there is no way to generate them.
30b9aea30a820b Jan Kiszka 2021-08-20 345 * However, some drivers may have a polling mode (e.g.
30b9aea30a820b Jan Kiszka 2021-08-20 346 * pciehp_poll_mode) that can be used in the absence of irqs.
30b9aea30a820b Jan Kiszka 2021-08-20 347 * Allow them to determine if that is to be used.
f118c0c3cff4fe Rafael J. Wysocki 2009-01-13 348 */
30b9aea30a820b Jan Kiszka 2021-08-20 349 status = pcie_init_service_irqs(dev, irqs, irq_services);
dc5351784eb36f Kenji Kaneshige 2009-11-25 350 if (status) {
30b9aea30a820b Jan Kiszka 2021-08-20 351 irq_services &= PCIE_PORT_SERVICE_HP;
30b9aea30a820b Jan Kiszka 2021-08-20 352 if (!irq_services)
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 353 goto error_disable;
f118c0c3cff4fe Rafael J. Wysocki 2009-01-13 354 }
30b9aea30a820b Jan Kiszka 2021-08-20 355 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 356
^1da177e4c3f41 Linus Torvalds 2005-04-16 357 /* Allocate child services if any */
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 358 status = -ENODEV;
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 359 nr_service = 0;
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 360 for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
90e9cd50f7feed Rafael J. Wysocki 2009-01-13 361 int service = 1 << i;
90e9cd50f7feed Rafael J. Wysocki 2009-01-13 362 if (!(capabilities & service))
90e9cd50f7feed Rafael J. Wysocki 2009-01-13 363 continue;
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 @364 if (!pcie_device_init(dev, service, irqs[i]))
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 365 nr_service++;
f118c0c3cff4fe Rafael J. Wysocki 2009-01-13 366 }
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 367 if (!nr_service)
fbb5de70bbe13e Kenji Kaneshige 2009-11-25 368 goto error_cleanup_irqs;
40717c39b1e6c0 Kenji Kaneshige 2009-11-25 369
^1da177e4c3f41 Linus Torvalds 2005-04-16 370 return 0;
f118c0c3cff4fe Rafael J. Wysocki 2009-01-13 371
fbb5de70bbe13e Kenji Kaneshige 2009-11-25 372 error_cleanup_irqs:
3674cc49da9a8f Christoph Hellwig 2017-02-01 373 pci_free_irq_vectors(dev);
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 374 error_disable:
1ce5e83063bf38 Kenji Kaneshige 2009-11-25 375 pci_disable_device(dev);
f118c0c3cff4fe Rafael J. Wysocki 2009-01-13 376 return status;
^1da177e4c3f41 Linus Torvalds 2005-04-16 377 }
^1da177e4c3f41 Linus Torvalds 2005-04-16 378

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
.config.gz (36.45 kB)
Attached Message Part (154.00 B)
Download all attachments