diff mbox

[1/9] PCI: Add new helper for allocating irq domain for INTx

Message ID 1524817367-239076-1-git-send-email-shawn.lin@rock-chips.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Shawn Lin April 27, 2018, 8:22 a.m. UTC
It seems host drivers which allocate irq domain for INTx
and the related code block looks highly similar to each other.
Add a new helper, pci_alloc_intx_irqd(), to avoid code duplication
as much as possible.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---

 include/linux/pci.h | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

Comments

Bjorn Helgaas April 27, 2018, 5:18 p.m. UTC | #1
s/PCI: Add new helper for allocating irq domain for INTx/
  PCI: Add pci_alloc_intx_irqd() for allocating IRQ domain

On Fri, Apr 27, 2018 at 04:22:47PM +0800, Shawn Lin wrote:
> It seems host drivers which allocate irq domain for INTx

s/irq/IRQ/

> and the related code block looks highly similar to each other.
> Add a new helper, pci_alloc_intx_irqd(), to avoid code duplication
> as much as possible.
> 
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
> 
>  include/linux/pci.h | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 74 insertions(+)
> 
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 73178a2..68a1994 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -31,6 +31,8 @@
>  #include <linux/device.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/of_irq.h>
>  #include <linux/resource_ext.h>
>  #include <uapi/linux/pci.h>
>  
> @@ -1449,6 +1451,74 @@ static inline int pci_irqd_intx_xlate(struct irq_domain *d,
>  	return 0;
>  }
>  
> +static int pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> +				  irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> +	irq_set_chip_data(irq, domain->host_data);
> +
> +	return 0;
> +}
> +
> +static struct irq_domain_ops pci_intx_domain_ops = {
> +	.map = pcie_intx_map,
> +};
> +
> +/**
> + * pci_alloc_intx_irqd() - PCI helper for allocating INTx irq domain

s/PCI helper for allocating INTx irq domain/
  Allocate INTx IRQ domain

> + * @dev: device associated with the PCI controller.
> + * @host: pointer to host specific data struct
> + * @general_xlate: flag for whether use pci_irqd_intx_xlate() helper
> + * @intx_domain_ops: pointer to driver specific struct irq_domain_ops
> + * @local_intc: pointer to driver specific interrupt controller node
> + *
> + * A simple helper for drivers to allocate irq domain for INTx. If
> + * intx_domain_ops is NULL, use pci_intx_domain_ops by defalut. And if
> + * local_intc is present, then use it firstly, otherwise, fallback to get
> + * interrupt controller node from @dev.

s/irq/IRQ/
s/defalut/default/

> + * Returns valid pointer of struct irq_domain on success, or PTR_ERR(-EINVAL)
> + * if failure occurred.
> + */
> +static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
> +				void *host, bool general_xlate,
> +				const struct irq_domain_ops *intx_domain_ops,
> +				struct device_node *local_intc)

Why is this in the header file?  This is not a performance path and I
don't want to deal with this __maybe_unused stuff.

> +{
> +	struct device_node *intc = local_intc;
> +	struct irq_domain *domain;
> +	const struct irq_domain_ops *irqd_ops;
> +	bool need_put = false;
> +
> +	if (!intc) {
> +		intc = of_get_next_child(dev->of_node, NULL);
> +		if (!intc) {
> +			dev_err(dev, "missing child interrupt-controller node\n");
> +			return ERR_PTR(-EINVAL);
> +		}
> +		need_put = true;
> +	}
> +
> +	if (intx_domain_ops) {
> +		irqd_ops = intx_domain_ops;
> +	} else {
> +		if (general_xlate)
> +			pci_intx_domain_ops.xlate = &pci_irqd_intx_xlate;
> +		irqd_ops = &pci_intx_domain_ops;
> +	}
> +
> +	domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
> +				       irqd_ops, host);
> +	if (!domain) {
> +		dev_err(dev, "failed to get a INTx IRQ domain\n");
> +		if (need_put)
> +			of_node_put(intc);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	return domain;
> +}
> +
>  #ifdef CONFIG_PCIEPORTBUS
>  extern bool pcie_ports_disabled;
>  #else
> @@ -1683,6 +1753,10 @@ static inline int pci_irqd_intx_xlate(struct irq_domain *d,
>  				      unsigned long *out_hwirq,
>  				      unsigned int *out_type)
>  { return -EINVAL; }
> +
> +static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
> +	void *host, bool general_xlate, const struct irq_domain_ops *ops)
> +{ return ERR_PTR(-EINVAL); }
>  #endif /* CONFIG_PCI */
>  
>  /* Include architecture-dependent settings and functions */
> -- 
> 1.9.1
> 
>
Shawn Lin April 28, 2018, 12:44 a.m. UTC | #2
Hi Bjorn,

On 2018/4/28 1:18, Bjorn Helgaas wrote:
> s/PCI: Add new helper for allocating irq domain for INTx/
>    PCI: Add pci_alloc_intx_irqd() for allocating IRQ domain
> 
> On Fri, Apr 27, 2018 at 04:22:47PM +0800, Shawn Lin wrote:
>> It seems host drivers which allocate irq domain for INTx
> 
> s/irq/IRQ/
> 
>> and the related code block looks highly similar to each other.
>> Add a new helper, pci_alloc_intx_irqd(), to avoid code duplication
>> as much as possible.
>>
>> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
>> ---
>>
>>   include/linux/pci.h | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 74 insertions(+)
>>
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 73178a2..68a1994 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -31,6 +31,8 @@
>>   #include <linux/device.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/io.h>
>> +#include <linux/irq.h>
>> +#include <linux/of_irq.h>
>>   #include <linux/resource_ext.h>
>>   #include <uapi/linux/pci.h>
>>   
>> @@ -1449,6 +1451,74 @@ static inline int pci_irqd_intx_xlate(struct irq_domain *d,
>>   	return 0;
>>   }
>>   
>> +static int pcie_intx_map(struct irq_domain *domain, unsigned int irq,
>> +				  irq_hw_number_t hwirq)
>> +{
>> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
>> +	irq_set_chip_data(irq, domain->host_data);
>> +
>> +	return 0;
>> +}
>> +
>> +static struct irq_domain_ops pci_intx_domain_ops = {
>> +	.map = pcie_intx_map,
>> +};
>> +
>> +/**
>> + * pci_alloc_intx_irqd() - PCI helper for allocating INTx irq domain
> 
> s/PCI helper for allocating INTx irq domain/
>    Allocate INTx IRQ domain
> 
>> + * @dev: device associated with the PCI controller.
>> + * @host: pointer to host specific data struct
>> + * @general_xlate: flag for whether use pci_irqd_intx_xlate() helper
>> + * @intx_domain_ops: pointer to driver specific struct irq_domain_ops
>> + * @local_intc: pointer to driver specific interrupt controller node
>> + *
>> + * A simple helper for drivers to allocate irq domain for INTx. If
>> + * intx_domain_ops is NULL, use pci_intx_domain_ops by defalut. And if
>> + * local_intc is present, then use it firstly, otherwise, fallback to get
>> + * interrupt controller node from @dev.
> 
> s/irq/IRQ/
> s/defalut/default/
> 
>> + * Returns valid pointer of struct irq_domain on success, or PTR_ERR(-EINVAL)
>> + * if failure occurred.
>> + */
>> +static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
>> +				void *host, bool general_xlate,
>> +				const struct irq_domain_ops *intx_domain_ops,
>> +				struct device_node *local_intc)
> 
> Why is this in the header file?  This is not a performance path and I
> don't want to deal with this __maybe_unused stuff.

Ah, I saw pci_irqd_intx_xlate() was here, and instinctively keep the
code close to it. Will move it to C file in v2.

> 
>> +{
>> +	struct device_node *intc = local_intc;
>> +	struct irq_domain *domain;
>> +	const struct irq_domain_ops *irqd_ops;
>> +	bool need_put = false;
>> +
>> +	if (!intc) {
>> +		intc = of_get_next_child(dev->of_node, NULL);
>> +		if (!intc) {
>> +			dev_err(dev, "missing child interrupt-controller node\n");
>> +			return ERR_PTR(-EINVAL);
>> +		}
>> +		need_put = true;
>> +	}
>> +
>> +	if (intx_domain_ops) {
>> +		irqd_ops = intx_domain_ops;
>> +	} else {
>> +		if (general_xlate)
>> +			pci_intx_domain_ops.xlate = &pci_irqd_intx_xlate;
>> +		irqd_ops = &pci_intx_domain_ops;
>> +	}
>> +
>> +	domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
>> +				       irqd_ops, host);
>> +	if (!domain) {
>> +		dev_err(dev, "failed to get a INTx IRQ domain\n");
>> +		if (need_put)
>> +			of_node_put(intc);
>> +		return ERR_PTR(-EINVAL);
>> +	}
>> +
>> +	return domain;
>> +}
>> +
>>   #ifdef CONFIG_PCIEPORTBUS
>>   extern bool pcie_ports_disabled;
>>   #else
>> @@ -1683,6 +1753,10 @@ static inline int pci_irqd_intx_xlate(struct irq_domain *d,
>>   				      unsigned long *out_hwirq,
>>   				      unsigned int *out_type)
>>   { return -EINVAL; }
>> +
>> +static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
>> +	void *host, bool general_xlate, const struct irq_domain_ops *ops)
>> +{ return ERR_PTR(-EINVAL); }
>>   #endif /* CONFIG_PCI */
>>   
>>   /* Include architecture-dependent settings and functions */
>> -- 
>> 1.9.1
>>
>>
> 
> 
>
kernel test robot April 28, 2018, 10:52 p.m. UTC | #3
Hi Shawn,

I love your patch! Yet something to improve:

[auto build test ERROR on pci/next]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Shawn-Lin/Add-new-helper-to-allocate-irq-domain-for-hosts/20180429-053656
base:   https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: i386-alldefconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from arch/x86//kernel/cpu/mtrr/main.c:46:0:
   include/linux/pci.h: In function 'pci_alloc_intx_irqd':
>> include/linux/pci.h:1510:11: error: implicit declaration of function 'irq_domain_add_linear'; did you mean 'irq_domain_get_of_node'? [-Werror=implicit-function-declaration]
     domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
              ^~~~~~~~~~~~~~~~~~~~~
              irq_domain_get_of_node
>> include/linux/pci.h:1510:9: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
            ^
   cc1: some warnings being treated as errors

vim +1510 include/linux/pci.h

  1466	
  1467	/**
  1468	 * pci_alloc_intx_irqd() - PCI helper for allocating INTx irq domain
  1469	 * @dev: device associated with the PCI controller.
  1470	 * @host: pointer to host specific data struct
  1471	 * @general_xlate: flag for whether use pci_irqd_intx_xlate() helper
  1472	 * @intx_domain_ops: pointer to driver specific struct irq_domain_ops
  1473	 * @local_intc: pointer to driver specific interrupt controller node
  1474	 *
  1475	 * A simple helper for drivers to allocate irq domain for INTx. If
  1476	 * intx_domain_ops is NULL, use pci_intx_domain_ops by defalut. And if
  1477	 * local_intc is present, then use it firstly, otherwise, fallback to get
  1478	 * interrupt controller node from @dev.
  1479	 *
  1480	 * Returns valid pointer of struct irq_domain on success, or PTR_ERR(-EINVAL)
  1481	 * if failure occurred.
  1482	 */
  1483	static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
  1484					void *host, bool general_xlate,
  1485					const struct irq_domain_ops *intx_domain_ops,
  1486					struct device_node *local_intc)
  1487	{
  1488		struct device_node *intc = local_intc;
  1489		struct irq_domain *domain;
  1490		const struct irq_domain_ops *irqd_ops;
  1491		bool need_put = false;
  1492	
  1493		if (!intc) {
  1494			intc = of_get_next_child(dev->of_node, NULL);
  1495			if (!intc) {
  1496				dev_err(dev, "missing child interrupt-controller node\n");
  1497				return ERR_PTR(-EINVAL);
  1498			}
  1499			need_put = true;
  1500		}
  1501	
  1502		if (intx_domain_ops) {
  1503			irqd_ops = intx_domain_ops;
  1504		} else {
  1505			if (general_xlate)
  1506				pci_intx_domain_ops.xlate = &pci_irqd_intx_xlate;
  1507			irqd_ops = &pci_intx_domain_ops;
  1508		}
  1509	
> 1510		domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
  1511					       irqd_ops, host);
  1512		if (!domain) {
  1513			dev_err(dev, "failed to get a INTx IRQ domain\n");
  1514			if (need_put)
  1515				of_node_put(intc);
  1516			return ERR_PTR(-EINVAL);
  1517		}
  1518	
  1519		return domain;
  1520	}
  1521	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot April 28, 2018, 11:08 p.m. UTC | #4
Hi Shawn,

I love your patch! Yet something to improve:

[auto build test ERROR on pci/next]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Shawn-Lin/Add-new-helper-to-allocate-irq-domain-for-hosts/20180429-053656
base:   https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: sparc-defconfig (attached as .config)
compiler: sparc-linux-gcc (GCC) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc 

All errors (new ones prefixed by >>):

   In file included from arch/sparc/kernel/ioport.c:37:0:
   include/linux/pci.h: In function 'pci_alloc_intx_irqd':
   include/linux/pci.h:1510:11: error: implicit declaration of function 'irq_domain_add_linear'; did you mean 'irq_domain_get_of_node'? [-Werror=implicit-function-declaration]
     domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
              ^~~~~~~~~~~~~~~~~~~~~
              irq_domain_get_of_node
>> include/linux/pci.h:1510:9: error: assignment makes pointer from integer without a cast [-Werror=int-conversion]
     domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
            ^
   cc1: all warnings being treated as errors

vim +1510 include/linux/pci.h

  1466	
  1467	/**
  1468	 * pci_alloc_intx_irqd() - PCI helper for allocating INTx irq domain
  1469	 * @dev: device associated with the PCI controller.
  1470	 * @host: pointer to host specific data struct
  1471	 * @general_xlate: flag for whether use pci_irqd_intx_xlate() helper
  1472	 * @intx_domain_ops: pointer to driver specific struct irq_domain_ops
  1473	 * @local_intc: pointer to driver specific interrupt controller node
  1474	 *
  1475	 * A simple helper for drivers to allocate irq domain for INTx. If
  1476	 * intx_domain_ops is NULL, use pci_intx_domain_ops by defalut. And if
  1477	 * local_intc is present, then use it firstly, otherwise, fallback to get
  1478	 * interrupt controller node from @dev.
  1479	 *
  1480	 * Returns valid pointer of struct irq_domain on success, or PTR_ERR(-EINVAL)
  1481	 * if failure occurred.
  1482	 */
  1483	static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
  1484					void *host, bool general_xlate,
  1485					const struct irq_domain_ops *intx_domain_ops,
  1486					struct device_node *local_intc)
  1487	{
  1488		struct device_node *intc = local_intc;
  1489		struct irq_domain *domain;
  1490		const struct irq_domain_ops *irqd_ops;
  1491		bool need_put = false;
  1492	
  1493		if (!intc) {
  1494			intc = of_get_next_child(dev->of_node, NULL);
  1495			if (!intc) {
  1496				dev_err(dev, "missing child interrupt-controller node\n");
  1497				return ERR_PTR(-EINVAL);
  1498			}
  1499			need_put = true;
  1500		}
  1501	
  1502		if (intx_domain_ops) {
  1503			irqd_ops = intx_domain_ops;
  1504		} else {
  1505			if (general_xlate)
  1506				pci_intx_domain_ops.xlate = &pci_irqd_intx_xlate;
  1507			irqd_ops = &pci_intx_domain_ops;
  1508		}
  1509	
> 1510		domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
  1511					       irqd_ops, host);
  1512		if (!domain) {
  1513			dev_err(dev, "failed to get a INTx IRQ domain\n");
  1514			if (need_put)
  1515				of_node_put(intc);
  1516			return ERR_PTR(-EINVAL);
  1517		}
  1518	
  1519		return domain;
  1520	}
  1521	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 73178a2..68a1994 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -31,6 +31,8 @@ 
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
 #include <linux/resource_ext.h>
 #include <uapi/linux/pci.h>
 
@@ -1449,6 +1451,74 @@  static inline int pci_irqd_intx_xlate(struct irq_domain *d,
 	return 0;
 }
 
+static int pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+				  irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static struct irq_domain_ops pci_intx_domain_ops = {
+	.map = pcie_intx_map,
+};
+
+/**
+ * pci_alloc_intx_irqd() - PCI helper for allocating INTx irq domain
+ * @dev: device associated with the PCI controller.
+ * @host: pointer to host specific data struct
+ * @general_xlate: flag for whether use pci_irqd_intx_xlate() helper
+ * @intx_domain_ops: pointer to driver specific struct irq_domain_ops
+ * @local_intc: pointer to driver specific interrupt controller node
+ *
+ * A simple helper for drivers to allocate irq domain for INTx. If
+ * intx_domain_ops is NULL, use pci_intx_domain_ops by defalut. And if
+ * local_intc is present, then use it firstly, otherwise, fallback to get
+ * interrupt controller node from @dev.
+ *
+ * Returns valid pointer of struct irq_domain on success, or PTR_ERR(-EINVAL)
+ * if failure occurred.
+ */
+static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
+				void *host, bool general_xlate,
+				const struct irq_domain_ops *intx_domain_ops,
+				struct device_node *local_intc)
+{
+	struct device_node *intc = local_intc;
+	struct irq_domain *domain;
+	const struct irq_domain_ops *irqd_ops;
+	bool need_put = false;
+
+	if (!intc) {
+		intc = of_get_next_child(dev->of_node, NULL);
+		if (!intc) {
+			dev_err(dev, "missing child interrupt-controller node\n");
+			return ERR_PTR(-EINVAL);
+		}
+		need_put = true;
+	}
+
+	if (intx_domain_ops) {
+		irqd_ops = intx_domain_ops;
+	} else {
+		if (general_xlate)
+			pci_intx_domain_ops.xlate = &pci_irqd_intx_xlate;
+		irqd_ops = &pci_intx_domain_ops;
+	}
+
+	domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
+				       irqd_ops, host);
+	if (!domain) {
+		dev_err(dev, "failed to get a INTx IRQ domain\n");
+		if (need_put)
+			of_node_put(intc);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return domain;
+}
+
 #ifdef CONFIG_PCIEPORTBUS
 extern bool pcie_ports_disabled;
 #else
@@ -1683,6 +1753,10 @@  static inline int pci_irqd_intx_xlate(struct irq_domain *d,
 				      unsigned long *out_hwirq,
 				      unsigned int *out_type)
 { return -EINVAL; }
+
+static __maybe_unused struct irq_domain *pci_alloc_intx_irqd(struct device *dev,
+	void *host, bool general_xlate, const struct irq_domain_ops *ops)
+{ return ERR_PTR(-EINVAL); }
 #endif /* CONFIG_PCI */
 
 /* Include architecture-dependent settings and functions */