* [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand
@ 2015-06-02 2:49 Jiang Liu
2015-06-02 2:49 ` [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver Jiang Liu
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Jiang Liu @ 2015-06-02 2:49 UTC (permalink / raw)
To: Thomas Gleixner, Rafael J . Wysocki, Bjorn Helgaas
Cc: Jiang Liu, LKML, linux-pci, linux-acpi, x86 @ kernel . org
This patch set introduces a mechanism to allocate PCI IRQ on demand and
free it when not used anymore by hooking pci_device_probe() and
pci_device_remove().
It will be used to track IOAPIC pin usage on x86 so we could support
IOAPIC hot-removal.
The patch set passes Fengguang's 0day test suite.
V1->V2:
1) Refine pci_device_probe() to optimize for mainline code as suggested
by Bjorn
2) Reorder patch set to put optional patch as the last (Patch 4)
Thanks!
Gerry
Jiang Liu (4):
PCI: Add hooks to allocate/free IRQ resources when binding/unbinding
driver
PCI, x86: Allocate PCI IRQ on demand and free it when not used
anymore
PCI: Introduce helpers to manage pci_dev->irq and
pci_dev->irq_managed
PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X
arch/x86/include/asm/pci_x86.h | 2 --
arch/x86/pci/common.c | 20 +++++++++-----------
arch/x86/pci/intel_mid_pci.c | 9 ++++++---
arch/x86/pci/irq.c | 23 ++++-------------------
drivers/acpi/pci_irq.c | 17 ++++-------------
drivers/pci/msi.c | 6 +++++-
drivers/pci/pci-driver.c | 26 ++++++++++++++++++++------
include/linux/pci.h | 19 +++++++++++++++++++
8 files changed, 67 insertions(+), 55 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver
2015-06-02 2:49 [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Jiang Liu
@ 2015-06-02 2:49 ` Jiang Liu
2015-06-05 21:17 ` Bjorn Helgaas
2015-06-02 2:49 ` [Patch v2 2/4] PCI, x86: Allocate PCI IRQ on demand and free it when not used anymore Jiang Liu
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Jiang Liu @ 2015-06-02 2:49 UTC (permalink / raw)
To: Thomas Gleixner, Rafael J . Wysocki, Bjorn Helgaas
Cc: Jiang Liu, LKML, linux-pci, linux-acpi, x86 @ kernel . org
Add two hook points pcibios_{alloc|free}_irq() into PCI core, which will
be called when binding/unbinding PCI device drivers. Then PCI arch code
may hook into these two points to allocate IRQ resources on demand and
free them when not used anymore.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
drivers/pci/pci-driver.c | 26 ++++++++++++++++++++------
include/linux/pci.h | 2 ++
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3cb2210de553..450ad36ffc77 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -388,18 +388,31 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
return error;
}
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+ return dev->irq;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
+
static int pci_device_probe(struct device *dev)
{
- int error = 0;
- struct pci_driver *drv;
- struct pci_dev *pci_dev;
+ int error;
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct pci_driver *drv = to_pci_driver(dev->driver);
+
+ error = pcibios_alloc_irq(pci_dev);
+ if (error < 0)
+ return error;
- drv = to_pci_driver(dev->driver);
- pci_dev = to_pci_dev(dev);
pci_dev_get(pci_dev);
error = __pci_device_probe(drv, pci_dev);
- if (error)
+ if (error) {
+ pcibios_free_irq(pci_dev);
pci_dev_put(pci_dev);
+ }
return error;
}
@@ -415,6 +428,7 @@ static int pci_device_remove(struct device *dev)
drv->remove(pci_dev);
pm_runtime_put_noidle(dev);
}
+ pcibios_free_irq(pci_dev);
pci_dev->driver = NULL;
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 353db8dc4c6e..f50d16a04abc 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1656,6 +1656,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
int pcibios_add_device(struct pci_dev *dev);
void pcibios_release_device(struct pci_dev *dev);
void pcibios_penalize_isa_irq(int irq, int active);
+int pcibios_alloc_irq(struct pci_dev *dev);
+void pcibios_free_irq(struct pci_dev *dev);
#ifdef CONFIG_HIBERNATE_CALLBACKS
extern struct dev_pm_ops pcibios_pm_ops;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Patch v2 2/4] PCI, x86: Allocate PCI IRQ on demand and free it when not used anymore
2015-06-02 2:49 [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Jiang Liu
2015-06-02 2:49 ` [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver Jiang Liu
@ 2015-06-02 2:49 ` Jiang Liu
2015-06-02 2:49 ` [Patch v2 3/4] PCI: Introduce helpers to manage pci_dev->irq and pci_dev->irq_managed Jiang Liu
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Jiang Liu @ 2015-06-02 2:49 UTC (permalink / raw)
To: Thomas Gleixner, Rafael J . Wysocki, Bjorn Helgaas, Ingo Molnar,
H. Peter Anvin, x86, Len Brown, Jiang Liu
Cc: LKML, linux-pci, linux-acpi
To support IOAPIC hotplug, we need to correctly manage IOAPIC pin usage,
which is to allocate IRQs on demand and free them when not used anymore.
So use pcibios_alloc_irq() and pcibios_free_irq() to dynamically allocate
and free PCI IRQs.
Also remove obseleted code mp_should_keep_irq().
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/pci_x86.h | 2 --
arch/x86/pci/common.c | 20 +++++++++-----------
arch/x86/pci/intel_mid_pci.c | 7 +++++--
arch/x86/pci/irq.c | 15 +--------------
drivers/acpi/pci_irq.c | 9 +--------
5 files changed, 16 insertions(+), 37 deletions(-)
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 164e3f8d3c3d..fa1195dae425 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -93,8 +93,6 @@ extern raw_spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
-extern bool mp_should_keep_irq(struct device *dev);
-
struct pci_raw_ops {
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val);
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 8fd6f44aee83..dc78a4a9a466 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -673,24 +673,22 @@ int pcibios_add_device(struct pci_dev *dev)
return 0;
}
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+int pcibios_alloc_irq(struct pci_dev *dev)
{
- int err;
-
- if ((err = pci_enable_resources(dev, mask)) < 0)
- return err;
-
- if (!pci_dev_msi_enabled(dev))
- return pcibios_enable_irq(dev);
- return 0;
+ return pcibios_enable_irq(dev);
}
-void pcibios_disable_device (struct pci_dev *dev)
+void pcibios_free_irq(struct pci_dev *dev)
{
- if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+ if (pcibios_disable_irq)
pcibios_disable_irq(dev);
}
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ return pci_enable_resources(dev, mask);
+}
+
int pci_ext_cfg_avail(void)
{
if (raw_pci_ext_ops)
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 27062303c881..fb7a1f96d80c 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -234,10 +234,13 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
{
- if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
- dev->irq > 0) {
+ if (dev->irq_managed && dev->irq > 0) {
mp_unmap_irq(dev->irq);
dev->irq_managed = 0;
+ /*
+ * Don't reset dev->irq here, otherwise
+ * intel_mid_pci_irq_enable() will fail on next call.
+ */
}
}
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 9bd115484745..72108f0b66b1 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1257,22 +1257,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
return 0;
}
-bool mp_should_keep_irq(struct device *dev)
-{
- if (dev->power.is_prepared)
- return true;
-#ifdef CONFIG_PM
- if (dev->power.runtime_status == RPM_SUSPENDING)
- return true;
-#endif
-
- return false;
-}
-
static void pirq_disable_irq(struct pci_dev *dev)
{
- if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
- dev->irq_managed && dev->irq) {
+ if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
mp_unmap_irq(dev->irq);
dev->irq = 0;
dev->irq_managed = 0;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index b1def411c0b8..e7f718d6918a 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -485,14 +485,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (!pin || !dev->irq_managed || dev->irq <= 0)
return;
- /* Keep IOAPIC pin configuration when suspending */
- if (dev->dev.power.is_prepared)
- return;
-#ifdef CONFIG_PM
- if (dev->dev.power.runtime_status == RPM_SUSPENDING)
- return;
-#endif
-
entry = acpi_pci_irq_lookup(dev, pin);
if (!entry)
return;
@@ -513,5 +505,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (gsi >= 0) {
acpi_unregister_gsi(gsi);
dev->irq_managed = 0;
+ dev->irq = 0;
}
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Patch v2 3/4] PCI: Introduce helpers to manage pci_dev->irq and pci_dev->irq_managed
2015-06-02 2:49 [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Jiang Liu
2015-06-02 2:49 ` [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver Jiang Liu
2015-06-02 2:49 ` [Patch v2 2/4] PCI, x86: Allocate PCI IRQ on demand and free it when not used anymore Jiang Liu
@ 2015-06-02 2:49 ` Jiang Liu
2015-06-05 21:20 ` Bjorn Helgaas
2015-06-02 2:49 ` [Patch v2 4/4] PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X Jiang Liu
2015-06-05 21:24 ` [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Bjorn Helgaas
4 siblings, 1 reply; 9+ messages in thread
From: Jiang Liu @ 2015-06-02 2:49 UTC (permalink / raw)
To: Thomas Gleixner, Rafael J . Wysocki, Bjorn Helgaas, Ingo Molnar,
H. Peter Anvin, x86, Len Brown
Cc: Jiang Liu, LKML, linux-pci, linux-acpi
Introduce three helpers to manage pci_dev->irq and pci_dev->irq_managed,
which helps to improve maintenance.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/pci/intel_mid_pci.c | 4 ++--
arch/x86/pci/irq.c | 10 ++++------
drivers/acpi/pci_irq.c | 10 ++++------
include/linux/pci.h | 17 +++++++++++++++++
4 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index fb7a1f96d80c..22aaefb4f1ca 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -211,7 +211,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
struct irq_alloc_info info;
int polarity;
- if (dev->irq_managed && dev->irq > 0)
+ if (pci_has_managed_irq(dev))
return 0;
if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
@@ -234,7 +234,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
{
- if (dev->irq_managed && dev->irq > 0) {
+ if (pci_has_managed_irq(dev)) {
mp_unmap_irq(dev->irq);
dev->irq_managed = 0;
/*
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 72108f0b66b1..32e70343e6fd 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
struct pci_dev *temp_dev;
int irq;
- if (dev->irq_managed && dev->irq > 0)
+ if (pci_has_managed_irq(dev))
return 0;
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
@@ -1230,8 +1230,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
dev = temp_dev;
if (irq >= 0) {
- dev->irq_managed = 1;
- dev->irq = irq;
+ pci_set_managed_irq(dev, irq);
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
return 0;
@@ -1259,9 +1258,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
static void pirq_disable_irq(struct pci_dev *dev)
{
- if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
+ if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
mp_unmap_irq(dev->irq);
- dev->irq = 0;
- dev->irq_managed = 0;
+ pci_reset_managed_irq(dev);
}
}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index e7f718d6918a..9d6343d02f7e 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -413,7 +413,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
return 0;
}
- if (dev->irq_managed && dev->irq > 0)
+ if (pci_has_managed_irq(dev))
return 0;
entry = acpi_pci_irq_lookup(dev, pin);
@@ -458,8 +458,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
kfree(entry);
return rc;
}
- dev->irq = rc;
- dev->irq_managed = 1;
+ pci_set_managed_irq(dev, rc);
if (link)
snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -482,7 +481,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
u8 pin;
pin = dev->pin;
- if (!pin || !dev->irq_managed || dev->irq <= 0)
+ if (!pin || !pci_has_managed_irq(dev))
return;
entry = acpi_pci_irq_lookup(dev, pin);
@@ -504,7 +503,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
if (gsi >= 0) {
acpi_unregister_gsi(gsi);
- dev->irq_managed = 0;
- dev->irq = 0;
+ pci_reset_managed_irq(dev);
}
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f50d16a04abc..4bc640eef76f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -958,6 +958,23 @@ static inline int pci_is_managed(struct pci_dev *pdev)
return pdev->is_managed;
}
+static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq)
+{
+ pdev->irq = irq;
+ pdev->irq_managed = 1;
+}
+
+static inline void pci_reset_managed_irq(struct pci_dev *pdev)
+{
+ pdev->irq = 0;
+ pdev->irq_managed = 0;
+}
+
+static inline bool pci_has_managed_irq(struct pci_dev *pdev)
+{
+ return pdev->irq_managed && pdev->irq > 0;
+}
+
void pci_disable_device(struct pci_dev *dev);
extern unsigned int pcibios_max_latency;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Patch v2 4/4] PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X
2015-06-02 2:49 [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Jiang Liu
` (2 preceding siblings ...)
2015-06-02 2:49 ` [Patch v2 3/4] PCI: Introduce helpers to manage pci_dev->irq and pci_dev->irq_managed Jiang Liu
@ 2015-06-02 2:49 ` Jiang Liu
2015-06-05 21:22 ` Bjorn Helgaas
2015-06-05 21:24 ` [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Bjorn Helgaas
4 siblings, 1 reply; 9+ messages in thread
From: Jiang Liu @ 2015-06-02 2:49 UTC (permalink / raw)
To: Thomas Gleixner, Rafael J . Wysocki, Bjorn Helgaas
Cc: Jiang Liu, LKML, linux-pci, linux-acpi, x86 @ kernel . org
Once PCI MSI/MSI-X is enabled by the device driver, PCI device won't
make use of legacy PCI IRQ until PCI MSI/MSI-X is disabled again.
So optionally free legacy PCI IRQ when enabling MSI/MSI-X and reallocate
when disabling MSI/MSI-X.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
drivers/pci/msi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index c3e7dfcf9ff5..47cf72c669f0 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -686,6 +686,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
msi_set_enable(dev, 1);
dev->msi_enabled = 1;
+ pcibios_free_irq(dev);
dev->irq = entry->irq;
return 0;
}
@@ -813,9 +814,10 @@ static int msix_capability_init(struct pci_dev *dev,
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
dev->msix_enabled = 1;
-
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
+ pcibios_free_irq(dev);
+
return 0;
out_avail:
@@ -930,6 +932,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
/* Restore dev->irq to its default pin-assertion irq */
dev->irq = desc->msi_attrib.default_irq;
+ pcibios_alloc_irq(dev);
}
void pci_disable_msi(struct pci_dev *dev)
@@ -1030,6 +1033,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
+ pcibios_alloc_irq(dev);
}
void pci_disable_msix(struct pci_dev *dev)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver
2015-06-02 2:49 ` [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver Jiang Liu
@ 2015-06-05 21:17 ` Bjorn Helgaas
0 siblings, 0 replies; 9+ messages in thread
From: Bjorn Helgaas @ 2015-06-05 21:17 UTC (permalink / raw)
To: Jiang Liu
Cc: Thomas Gleixner, Rafael J . Wysocki, LKML, linux-pci, linux-acpi,
x86 @ kernel . org
On Tue, Jun 02, 2015 at 10:49:16AM +0800, Jiang Liu wrote:
> Add two hook points pcibios_{alloc|free}_irq() into PCI core, which will
> be called when binding/unbinding PCI device drivers. Then PCI arch code
> may hook into these two points to allocate IRQ resources on demand and
> free them when not used anymore.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
> drivers/pci/pci-driver.c | 26 ++++++++++++++++++++------
> include/linux/pci.h | 2 ++
> 2 files changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
> index 3cb2210de553..450ad36ffc77 100644
> --- a/drivers/pci/pci-driver.c
> +++ b/drivers/pci/pci-driver.c
> @@ -388,18 +388,31 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
> return error;
> }
>
> +int __weak pcibios_alloc_irq(struct pci_dev *dev)
> +{
> + return dev->irq;
Based on your usage, pcibios_alloc_irq() returns either zero or a negative
errno. So I think you should return 0 here.
> +}
> +
> +void __weak pcibios_free_irq(struct pci_dev *dev)
> +{
> +}
> +
> static int pci_device_probe(struct device *dev)
> {
> - int error = 0;
> - struct pci_driver *drv;
> - struct pci_dev *pci_dev;
> + int error;
> + struct pci_dev *pci_dev = to_pci_dev(dev);
> + struct pci_driver *drv = to_pci_driver(dev->driver);
> +
> + error = pcibios_alloc_irq(pci_dev);
> + if (error < 0)
> + return error;
>
> - drv = to_pci_driver(dev->driver);
> - pci_dev = to_pci_dev(dev);
> pci_dev_get(pci_dev);
> error = __pci_device_probe(drv, pci_dev);
> - if (error)
> + if (error) {
> + pcibios_free_irq(pci_dev);
> pci_dev_put(pci_dev);
> + }
>
> return error;
> }
> @@ -415,6 +428,7 @@ static int pci_device_remove(struct device *dev)
> drv->remove(pci_dev);
> pm_runtime_put_noidle(dev);
> }
> + pcibios_free_irq(pci_dev);
> pci_dev->driver = NULL;
> }
>
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 353db8dc4c6e..f50d16a04abc 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1656,6 +1656,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
> int pcibios_add_device(struct pci_dev *dev);
> void pcibios_release_device(struct pci_dev *dev);
> void pcibios_penalize_isa_irq(int irq, int active);
> +int pcibios_alloc_irq(struct pci_dev *dev);
> +void pcibios_free_irq(struct pci_dev *dev);
>
> #ifdef CONFIG_HIBERNATE_CALLBACKS
> extern struct dev_pm_ops pcibios_pm_ops;
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Patch v2 3/4] PCI: Introduce helpers to manage pci_dev->irq and pci_dev->irq_managed
2015-06-02 2:49 ` [Patch v2 3/4] PCI: Introduce helpers to manage pci_dev->irq and pci_dev->irq_managed Jiang Liu
@ 2015-06-05 21:20 ` Bjorn Helgaas
0 siblings, 0 replies; 9+ messages in thread
From: Bjorn Helgaas @ 2015-06-05 21:20 UTC (permalink / raw)
To: Jiang Liu
Cc: Thomas Gleixner, Rafael J . Wysocki, Ingo Molnar, H. Peter Anvin,
x86, Len Brown, LKML, linux-pci, linux-acpi
I'm on a campaign to squeeze more useful information into changelog
subjects. "Add" means the same as "Introduce" but leaves more space for
other useful information.
On Tue, Jun 02, 2015 at 10:49:18AM +0800, Jiang Liu wrote:
> Introduce three helpers to manage pci_dev->irq and pci_dev->irq_managed,
> which helps to improve maintenance.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
> arch/x86/pci/intel_mid_pci.c | 4 ++--
> arch/x86/pci/irq.c | 10 ++++------
> drivers/acpi/pci_irq.c | 10 ++++------
> include/linux/pci.h | 17 +++++++++++++++++
> 4 files changed, 27 insertions(+), 14 deletions(-)
>
> diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
> index fb7a1f96d80c..22aaefb4f1ca 100644
> --- a/arch/x86/pci/intel_mid_pci.c
> +++ b/arch/x86/pci/intel_mid_pci.c
> @@ -211,7 +211,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
> struct irq_alloc_info info;
> int polarity;
>
> - if (dev->irq_managed && dev->irq > 0)
> + if (pci_has_managed_irq(dev))
> return 0;
>
> if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
> @@ -234,7 +234,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
>
> static void intel_mid_pci_irq_disable(struct pci_dev *dev)
> {
> - if (dev->irq_managed && dev->irq > 0) {
> + if (pci_has_managed_irq(dev)) {
> mp_unmap_irq(dev->irq);
> dev->irq_managed = 0;
> /*
> diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
> index 72108f0b66b1..32e70343e6fd 100644
> --- a/arch/x86/pci/irq.c
> +++ b/arch/x86/pci/irq.c
> @@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
> struct pci_dev *temp_dev;
> int irq;
>
> - if (dev->irq_managed && dev->irq > 0)
> + if (pci_has_managed_irq(dev))
> return 0;
>
> irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
> @@ -1230,8 +1230,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
> }
> dev = temp_dev;
> if (irq >= 0) {
> - dev->irq_managed = 1;
> - dev->irq = irq;
> + pci_set_managed_irq(dev, irq);
> dev_info(&dev->dev, "PCI->APIC IRQ transform: "
> "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
> return 0;
> @@ -1259,9 +1258,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
>
> static void pirq_disable_irq(struct pci_dev *dev)
> {
> - if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
> + if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
> mp_unmap_irq(dev->irq);
> - dev->irq = 0;
> - dev->irq_managed = 0;
> + pci_reset_managed_irq(dev);
> }
> }
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index e7f718d6918a..9d6343d02f7e 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -413,7 +413,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> return 0;
> }
>
> - if (dev->irq_managed && dev->irq > 0)
> + if (pci_has_managed_irq(dev))
> return 0;
>
> entry = acpi_pci_irq_lookup(dev, pin);
> @@ -458,8 +458,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> kfree(entry);
> return rc;
> }
> - dev->irq = rc;
> - dev->irq_managed = 1;
> + pci_set_managed_irq(dev, rc);
>
> if (link)
> snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
> @@ -482,7 +481,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
> u8 pin;
>
> pin = dev->pin;
> - if (!pin || !dev->irq_managed || dev->irq <= 0)
> + if (!pin || !pci_has_managed_irq(dev))
> return;
>
> entry = acpi_pci_irq_lookup(dev, pin);
> @@ -504,7 +503,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
> dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
> if (gsi >= 0) {
> acpi_unregister_gsi(gsi);
> - dev->irq_managed = 0;
> - dev->irq = 0;
> + pci_reset_managed_irq(dev);
> }
> }
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index f50d16a04abc..4bc640eef76f 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -958,6 +958,23 @@ static inline int pci_is_managed(struct pci_dev *pdev)
> return pdev->is_managed;
> }
>
> +static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq)
> +{
> + pdev->irq = irq;
> + pdev->irq_managed = 1;
> +}
> +
> +static inline void pci_reset_managed_irq(struct pci_dev *pdev)
> +{
> + pdev->irq = 0;
> + pdev->irq_managed = 0;
> +}
> +
> +static inline bool pci_has_managed_irq(struct pci_dev *pdev)
> +{
> + return pdev->irq_managed && pdev->irq > 0;
> +}
> +
> void pci_disable_device(struct pci_dev *dev);
>
> extern unsigned int pcibios_max_latency;
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Patch v2 4/4] PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X
2015-06-02 2:49 ` [Patch v2 4/4] PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X Jiang Liu
@ 2015-06-05 21:22 ` Bjorn Helgaas
0 siblings, 0 replies; 9+ messages in thread
From: Bjorn Helgaas @ 2015-06-05 21:22 UTC (permalink / raw)
To: Jiang Liu
Cc: Thomas Gleixner, Rafael J . Wysocki, LKML, linux-pci, linux-acpi,
x86 @ kernel . org
>From the point of view of the generic code in this patch, freeing the IRQ
isn't optional -- there's no "if" in this this patch.
It's true that the default pcibios_free_irq() implementation does nothing,
but the changelog of this patch should describe what this patch does.
On Tue, Jun 02, 2015 at 10:49:19AM +0800, Jiang Liu wrote:
> Once PCI MSI/MSI-X is enabled by the device driver, PCI device won't
> make use of legacy PCI IRQ until PCI MSI/MSI-X is disabled again.
> So optionally free legacy PCI IRQ when enabling MSI/MSI-X and reallocate
> when disabling MSI/MSI-X.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
> drivers/pci/msi.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index c3e7dfcf9ff5..47cf72c669f0 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -686,6 +686,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
> msi_set_enable(dev, 1);
> dev->msi_enabled = 1;
>
> + pcibios_free_irq(dev);
> dev->irq = entry->irq;
> return 0;
> }
> @@ -813,9 +814,10 @@ static int msix_capability_init(struct pci_dev *dev,
> /* Set MSI-X enabled bits and unmask the function */
> pci_intx_for_msi(dev, 0);
> dev->msix_enabled = 1;
> -
> msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
>
> + pcibios_free_irq(dev);
> +
> return 0;
>
> out_avail:
> @@ -930,6 +932,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
>
> /* Restore dev->irq to its default pin-assertion irq */
> dev->irq = desc->msi_attrib.default_irq;
> + pcibios_alloc_irq(dev);
> }
>
> void pci_disable_msi(struct pci_dev *dev)
> @@ -1030,6 +1033,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
> msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
> pci_intx_for_msi(dev, 1);
> dev->msix_enabled = 0;
> + pcibios_alloc_irq(dev);
> }
>
> void pci_disable_msix(struct pci_dev *dev)
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand
2015-06-02 2:49 [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Jiang Liu
` (3 preceding siblings ...)
2015-06-02 2:49 ` [Patch v2 4/4] PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X Jiang Liu
@ 2015-06-05 21:24 ` Bjorn Helgaas
4 siblings, 0 replies; 9+ messages in thread
From: Bjorn Helgaas @ 2015-06-05 21:24 UTC (permalink / raw)
To: Jiang Liu
Cc: Thomas Gleixner, Rafael J . Wysocki, LKML, linux-pci, linux-acpi,
x86 @ kernel . org
On Tue, Jun 02, 2015 at 10:49:15AM +0800, Jiang Liu wrote:
> This patch set introduces a mechanism to allocate PCI IRQ on demand and
> free it when not used anymore by hooking pci_device_probe() and
> pci_device_remove().
>
> It will be used to track IOAPIC pin usage on x86 so we could support
> IOAPIC hot-removal.
>
> The patch set passes Fengguang's 0day test suite.
>
> V1->V2:
> 1) Refine pci_device_probe() to optimize for mainline code as suggested
> by Bjorn
> 2) Reorder patch set to put optional patch as the last (Patch 4)
>
> Thanks!
> Gerry
>
>
> Jiang Liu (4):
> PCI: Add hooks to allocate/free IRQ resources when binding/unbinding
> driver
> PCI, x86: Allocate PCI IRQ on demand and free it when not used
> anymore
> PCI: Introduce helpers to manage pci_dev->irq and
> pci_dev->irq_managed
> PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X
>
> arch/x86/include/asm/pci_x86.h | 2 --
> arch/x86/pci/common.c | 20 +++++++++-----------
> arch/x86/pci/intel_mid_pci.c | 9 ++++++---
> arch/x86/pci/irq.c | 23 ++++-------------------
> drivers/acpi/pci_irq.c | 17 ++++-------------
> drivers/pci/msi.c | 6 +++++-
> drivers/pci/pci-driver.c | 26 ++++++++++++++++++++------
> include/linux/pci.h | 19 +++++++++++++++++++
> 8 files changed, 67 insertions(+), 55 deletions(-)
I'm fine with these patches, and I can merge them, but I would like an ack
from Thomas.
Or, if it makes more sense to route these along with other related patches
through Thomas, here's my ack:
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-06-05 21:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-02 2:49 [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Jiang Liu
2015-06-02 2:49 ` [Patch v2 1/4] PCI: Add hooks to allocate/free IRQ resources when binding/unbinding driver Jiang Liu
2015-06-05 21:17 ` Bjorn Helgaas
2015-06-02 2:49 ` [Patch v2 2/4] PCI, x86: Allocate PCI IRQ on demand and free it when not used anymore Jiang Liu
2015-06-02 2:49 ` [Patch v2 3/4] PCI: Introduce helpers to manage pci_dev->irq and pci_dev->irq_managed Jiang Liu
2015-06-05 21:20 ` Bjorn Helgaas
2015-06-02 2:49 ` [Patch v2 4/4] PCI, MSI: Optionally free legacy PCI IRQ when enabling MSI/MSI-X Jiang Liu
2015-06-05 21:22 ` Bjorn Helgaas
2015-06-05 21:24 ` [Patch v2 0/4] Introduce a mechanism to allocate PCI IRQ on demand Bjorn Helgaas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).