LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] KVM: PPC: e500mc: Add support for single threaded vcpus on e6500 core
From: Scott Wood @ 2014-08-11 23:36 UTC (permalink / raw)
  To: Mihai Caraman; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1407342808-15987-1-git-send-email-mihai.caraman@freescale.com>

On Wed, 2014-08-06 at 19:33 +0300, Mihai Caraman wrote:
> @@ -390,19 +400,30 @@ static void kvmppc_core_vcpu_free_e500mc(struct kvm_vcpu *vcpu)
>  
>  static int kvmppc_core_init_vm_e500mc(struct kvm *kvm)
>  {
> -	int lpid;
> +	int i, lpid;
>  
> -	lpid = kvmppc_alloc_lpid();
> -	if (lpid < 0)
> -		return lpid;
> +	/* The lpid pool supports only 2 entries now */
> +	if (threads_per_core > 2)
> +		return -ENOMEM;
> +
> +	/* Each VM allocates one LPID per HW thread index */
> +	for (i = 0; i < threads_per_core; i++) {
> +		lpid = kvmppc_alloc_lpid();
> +		if (lpid < 0)
> +			return lpid;
> +
> +		kvm->arch.lpid_pool[i] = lpid;
> +	}

Wouldn't it be simpler to halve the size of the lpid pool that the
allocator sees, and just OR in the high bit based on the low bit of the
cpu number?

-Scott

^ permalink raw reply

* Re: [PATCH 2/2] powerpc: Add ppc64 hard lockup detector support
From: Paul E. McKenney @ 2014-08-11 23:42 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: mikey, paulus, linuxppc-dev
In-Reply-To: <20140812093137.404e8930@kryten>

On Tue, Aug 12, 2014 at 09:31:37AM +1000, Anton Blanchard wrote:
> The hard lockup detector uses a PMU event as a periodic NMI to
> detect if we are stuck (where stuck means no timer interrupts have
> occurred).
> 
> Ben's rework of the ppc64 soft disable code has made ppc64 PMU
> exceptions a partial NMI. They can get disabled if an external interrupt
> comes in, but otherwise PMU interrupts will fire in interrupt disabled
> regions.
> 
> I wrote a kernel module to test this patch and noticed we sometimes
> missed hard lockup warnings. The RCU code detected the stall first and
> issued an IPI to backtrace all CPUs. Unfortunately an IPI is an external
> interrupt and that will hard disable interrupts, preventing the hard
> lockup detector from going off.

If it helps, commit bc1dce514e9b (rcu: Don't use NMIs to dump other
CPUs' stacks) makes RCU avoid this behavior.  It instead reads the
stacks out remotely when this commit is applied.  It is in -tip, and
should make mainline this merge window.  Corresponding patch below.

						Thanx, Paul

------------------------------------------------------------------------

rcu: Don't use NMIs to dump other CPUs' stacks

Although NMI-based stack dumps are in principle more accurate, they are
also more likely to trigger deadlocks.  This commit therefore replaces
all uses of trigger_all_cpu_backtrace() with rcu_dump_cpu_stacks(), so
that the CPU detecting an RCU CPU stall does the stack dumping.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Lai Jiangshan <laijs@cn.fujitsu.com>

diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 3f93033d3c61..8f3e4d43d736 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1013,10 +1013,7 @@ static void record_gp_stall_check_time(struct rcu_state *rsp)
 }
 
 /*
- * Dump stacks of all tasks running on stalled CPUs.  This is a fallback
- * for architectures that do not implement trigger_all_cpu_backtrace().
- * The NMI-triggered stack traces are more accurate because they are
- * printed by the target CPU.
+ * Dump stacks of all tasks running on stalled CPUs.
  */
 static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
 {
@@ -1094,7 +1091,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
 	       (long)rsp->gpnum, (long)rsp->completed, totqlen);
 	if (ndetected == 0)
 		pr_err("INFO: Stall ended before state dump start\n");
-	else if (!trigger_all_cpu_backtrace())
+	else
 		rcu_dump_cpu_stacks(rsp);
 
 	/* Complain about tasks blocking the grace period. */
@@ -1125,8 +1122,7 @@ static void print_cpu_stall(struct rcu_state *rsp)
 	pr_cont(" (t=%lu jiffies g=%ld c=%ld q=%lu)\n",
 		jiffies - rsp->gp_start,
 		(long)rsp->gpnum, (long)rsp->completed, totqlen);
-	if (!trigger_all_cpu_backtrace())
-		dump_stack();
+	rcu_dump_cpu_stacks(rsp);
 
 	raw_spin_lock_irqsave(&rnp->lock, flags);
 	if (ULONG_CMP_GE(jiffies, ACCESS_ONCE(rsp->jiffies_stall)))

^ permalink raw reply related

* [PATCH] powerpc: remove duplicate definition of TEXASR_FS
From: Nishanth Aravamudan @ 2014-08-11 23:43 UTC (permalink / raw)
  To: Michael Neuling; +Cc: Paul Mackerras, linuxppc-dev

It appears that commits 7f06f21d40a6 ("powerpc/tm: Add checking to
treclaim/trechkpt") and e4e38121507a ("KVM: PPC: Book3S HV: Add
transactional memory support") both added definitions of TEXASR_FS.
Remove one of them. At the same time, fix the alignment of the remaining
definition (should be tab-separated like the rest of the #defines).

Signed-off-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1c987bf794ef..0c0505956a29 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -213,9 +213,8 @@
 #define SPRN_ACOP	0x1F	/* Available Coprocessor Register */
 #define SPRN_TFIAR	0x81	/* Transaction Failure Inst Addr   */
 #define SPRN_TEXASR	0x82	/* Transaction EXception & Summary */
-#define   TEXASR_FS	__MASK(63-36)	/* Transaction Failure Summary */
 #define SPRN_TEXASRU	0x83	/* ''	   ''	   ''	 Upper 32  */
-#define   TEXASR_FS     __MASK(63-36) /* TEXASR Failure Summary */
+#define   TEXASR_FS	__MASK(63-36) /* TEXASR Failure Summary */
 #define SPRN_TFHAR	0x80	/* Transaction Failure Handler Addr */
 #define SPRN_CTRLF	0x088
 #define SPRN_CTRLT	0x098

^ permalink raw reply related

* Re: [PATCH] KVM: PPC: e500mc: Add support for single threaded vcpus on e6500 core
From: Alexander Graf @ 2014-08-11 23:53 UTC (permalink / raw)
  To: Scott Wood
  Cc: Mihai Caraman, <linuxppc-dev@lists.ozlabs.org>,
	<kvm@vger.kernel.org>, <kvm-ppc@vger.kernel.org>
In-Reply-To: <1407800199.7427.108.camel@snotra.buserror.net>



> Am 12.08.2014 um 01:36 schrieb Scott Wood <scottwood@freescale.com>:
>=20
>> On Wed, 2014-08-06 at 19:33 +0300, Mihai Caraman wrote:
>> @@ -390,19 +400,30 @@ static void kvmppc_core_vcpu_free_e500mc(struct kvm=
_vcpu *vcpu)
>>=20
>> static int kvmppc_core_init_vm_e500mc(struct kvm *kvm)
>> {
>> -    int lpid;
>> +    int i, lpid;
>>=20
>> -    lpid =3D kvmppc_alloc_lpid();
>> -    if (lpid < 0)
>> -        return lpid;
>> +    /* The lpid pool supports only 2 entries now */
>> +    if (threads_per_core > 2)
>> +        return -ENOMEM;
>> +
>> +    /* Each VM allocates one LPID per HW thread index */
>> +    for (i =3D 0; i < threads_per_core; i++) {
>> +        lpid =3D kvmppc_alloc_lpid();
>> +        if (lpid < 0)
>> +            return lpid;
>> +
>> +        kvm->arch.lpid_pool[i] =3D lpid;
>> +    }
>=20
> Wouldn't it be simpler to halve the size of the lpid pool that the
> allocator sees, and just OR in the high bit based on the low bit of the
> cpu number?

Heh, I wrote the same and then removed the section from my reply again. It w=
ouldn't really make that much of a difference if you think it through comple=
tely.

But yes, it certainly would be quite a bit more natural. I'm ok either way.


Alex

^ permalink raw reply

* Re: [PATCH] KVM: PPC: e500mc: Add support for single threaded vcpus on e6500 core
From: Scott Wood @ 2014-08-11 23:56 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Mihai Caraman, <linuxppc-dev@lists.ozlabs.org>,
	<kvm@vger.kernel.org>, <kvm-ppc@vger.kernel.org>
In-Reply-To: <3CE03B7F-D9C3-4CD0-8215-9815494A19AF@suse.de>

On Tue, 2014-08-12 at 01:53 +0200, Alexander Graf wrote:
> 
> > Am 12.08.2014 um 01:36 schrieb Scott Wood <scottwood@freescale.com>:
> > 
> >> On Wed, 2014-08-06 at 19:33 +0300, Mihai Caraman wrote:
> >> @@ -390,19 +400,30 @@ static void kvmppc_core_vcpu_free_e500mc(struct kvm_vcpu *vcpu)
> >> 
> >> static int kvmppc_core_init_vm_e500mc(struct kvm *kvm)
> >> {
> >> -    int lpid;
> >> +    int i, lpid;
> >> 
> >> -    lpid = kvmppc_alloc_lpid();
> >> -    if (lpid < 0)
> >> -        return lpid;
> >> +    /* The lpid pool supports only 2 entries now */
> >> +    if (threads_per_core > 2)
> >> +        return -ENOMEM;
> >> +
> >> +    /* Each VM allocates one LPID per HW thread index */
> >> +    for (i = 0; i < threads_per_core; i++) {
> >> +        lpid = kvmppc_alloc_lpid();
> >> +        if (lpid < 0)
> >> +            return lpid;
> >> +
> >> +        kvm->arch.lpid_pool[i] = lpid;
> >> +    }
> > 
> > Wouldn't it be simpler to halve the size of the lpid pool that the
> > allocator sees, and just OR in the high bit based on the low bit of the
> > cpu number?
> 
> Heh, I wrote the same and then removed the section from my reply again. It wouldn't really make that much of a difference if you think it through completely.
> 
> But yes, it certainly would be quite a bit more natural. I'm ok either way.

It's not a huge difference, but it would at least get rid of some of the
ifdeffing in the headers.  It'd also be nicer when debugging to have the
LPIDs correlated.

-Scott

^ permalink raw reply

* Re: [PATCH 1/2] powerpc/pseries: Failure on removing device node
From: Gavin Shan @ 2014-08-12  1:47 UTC (permalink / raw)
  To: Nathan Fontenot; +Cc: linuxppc-dev, Gavin Shan
In-Reply-To: <53E8D021.1010908@linux.vnet.ibm.com>

On Mon, Aug 11, 2014 at 09:16:01AM -0500, Nathan Fontenot wrote:
>On 08/11/2014 04:16 AM, Gavin Shan wrote:

[Removing stable from cc list to avoid mail flooding]

>> While running command "drmgr -c phb -r -s 'PHB 528'", following
>> backtrace jumped out because the target device node isn't marked
>> with OF_DETACHED by of_detach_node(), which caused by error
>> returned from memory hotplug related reconfig notifier when
>> disabling CONFIG_MEMORY_HOTREMOVE. The patch fixes it.
>> 
>
>Could you provide some more context here.
>
>Your comment claims that you hit an error while trying to remove a PHB,
>but the fix you provided is for memory hotplug. This changes the
>rturn code to zero which usually inidcates success except that
>your comment states you disabled memory hotplug remove.
>

Yep, here's more information about it: The notification callbacks
are called in sequence as they are regsitered. For of_reconfig_notifier,
following callbacks would be called in sequence:

arch/powerpc/platforms/pseries/setup.c::pci_dn_reconfig_notifier()
                               iommu.c::iommu_reconfig_notifier()
                               hotplug-cpu.c::pseries_smp_notifier()
                               hotplug-memory.c::pseries_memory_notifier()

Writing "remove_node xxxx" to /proc/powerpc/ofdt will invoke of_detach_node()
which bails early without marking OF_DETACHED for the device node if any
error returned from of_reconfig_notifier callbacks. The error was contributed
by hotplug-memory.c::pseries_memory_notifier() with disabled CONFIG_MEMORY_HOTREMOVE.

int of_detach_node(struct device_node *np)
{
        struct device_node *parent;
        unsigned long flags;
        int rc = 0;

        rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
        if (rc)
                return rc;
        :
        :
        of_node_set_flag(np, OF_DETACHED);          <<< It's missed.
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        :
}

When releasing the device node, we run into warning as the device
node wasn't marked with flag OF_DETACHED.

static void of_node_release(struct kobject *kobj)
{
        struct device_node *node = kobj_to_device_node(kobj);
        struct property *prop = node->properties;

        /* We should never be releasing nodes that haven't been detached. */
        if (!of_node_check_flag(node, OF_DETACHED)) {
                pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
                dump_stack();
                return;
        }
        :
        :
}

>I think the fix we need to have here is to update the version of
>pseries_remove_mem_node() when CONFIG_MEMORY_HOTREMOVE is disabled
>to validate that the node is a memory node and return the proper value
>instead of just returning -EOPNOTSUPP in all cases. 
>

I guess you suggested to add following piece of code in pseries_remove_mem_node()
when CONFIG_MEMORY_HOTREMOVE is disabled? If so, we can't avoid the issue and it's
not helping anything. I think returning 0 might be enough here.

static inline int pseries_remove_mem_node(struct device_node *np)
{
        type = of_get_property(np, "device_type", NULL);
        if (type == NULL || strcmp(type, "memory") != 0)
                return 0;

        return -EOPNOTSUPP
}

>The pseries_remove_mem_node() routine when memory removed is enabled
>already does this.
>

Yes, we don't have problem for this case because PHB or PCI adapter
device nodes occasionally have "reg" property. Otherwise, it also
fails.

Thanks,
Gavin

>-Nathan
>
>> ERROR: Bad of_node_put() on /pci@800000020000210/ethernet@0
>> CPU: 14 PID: 2252 Comm: drmgr Tainted: G        W     3.16.0+ #427
>> Call Trace:
>> [c000000012a776a0] [c000000000013d9c] .show_stack+0x88/0x148 (unreliable)
>> [c000000012a77750] [c00000000083cd34] .dump_stack+0x7c/0x9c
>> [c000000012a777d0] [c0000000006807c4] .of_node_release+0x58/0xe0
>> [c000000012a77860] [c00000000038a7d0] .kobject_release+0x174/0x1b8
>> [c000000012a77900] [c00000000038a884] .kobject_put+0x70/0x78
>> [c000000012a77980] [c000000000681680] .of_node_put+0x28/0x34
>> [c000000012a77a00] [c000000000681ea8] .__of_get_next_child+0x64/0x70
>> [c000000012a77a90] [c000000000682138] .of_find_node_by_path+0x1b8/0x20c
>> [c000000012a77b40] [c000000000051840] .ofdt_write+0x308/0x688
>> [c000000012a77c20] [c000000000238430] .proc_reg_write+0xb8/0xd4
>> [c000000012a77cd0] [c0000000001cbeac] .vfs_write+0xec/0x1f8
>> [c000000012a77d70] [c0000000001cc3b0] .SyS_write+0x58/0xa0
>> [c000000012a77e30] [c00000000000a064] syscall_exit+0x0/0x98
>> 
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
>> ---
>>  arch/powerpc/platforms/pseries/hotplug-memory.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
>> index 7995135..24abc5c 100644
>> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
>> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
>> @@ -146,7 +146,7 @@ static inline int pseries_remove_memblock(unsigned long base,
>>  }
>>  static inline int pseries_remove_mem_node(struct device_node *np)
>>  {
>> -	return -EOPNOTSUPP;
>> +	return 0;
>>  }
>>  #endif /* CONFIG_MEMORY_HOTREMOVE */
>>  
>> 

^ permalink raw reply

* Re: [PATCH v3] powerpc/kvm: support to handle sw breakpoint
From: Madhavan Srinivasan @ 2014-08-12  5:17 UTC (permalink / raw)
  To: Alexander Graf, Benjamin Herrenschmidt; +Cc: linuxppc-dev, paulus, kvm-ppc, kvm
In-Reply-To: <53E889BA.40108@suse.de>

On Monday 11 August 2014 02:45 PM, Alexander Graf wrote:
> 
> On 11.08.14 10:51, Benjamin Herrenschmidt wrote:
>> On Mon, 2014-08-11 at 09:26 +0200, Alexander Graf wrote:
>>>> diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
>>>> index da86d9b..d95014e 100644
>>>> --- a/arch/powerpc/kvm/emulate.c
>>>> +++ b/arch/powerpc/kvm/emulate.c
>>> This should be book3s_emulate.c.
>> Any reason we can't make that 00dddd00 opcode as breakpoint common to
>> all powerpc variants ?
> 
> I can't think of a good reason. We use a hypercall on booke (which traps
> into an illegal instruction for pr) today, but I don't think it has to
> be that way.
> 
> Given that the user space API allows us to change it dynamically, there
> should be nothing blocking us from going with 00dddd00 always.
> 
Kindly correct me if i am wrong. So we can still have a common code in
emulate.c to set the env for both HV and pr incase of illegal
instruction (i will rebase latest src). But suggestion here to use
00dddd00, in that case current path in embed is kvmppc_handle_exit
(booke.c) -> BOOKE_INTERRUPT_HV_PRIV -> emulation_exit ->
kvmppc_emulate_instruction, will change to kvmppc_handle_exit (booke.c)
-> BOOKE_INTERRUPT_PROGRAM -> if debug instr call emulation_exit else
send to guest?

Thanks for review
regards
Maddy

> 
> Alex
> 

^ permalink raw reply

* [RFC PATCH 04/20] MSI: Remove the redundant irq_set_chip_data()
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Currently, pcie-designware, pcie-rcar, pci-tegra drivers
use irq chip_data to the msi_chip pointer. They already call
irq_set_chip_data() in their own MSI irq map functions.
So irq_set_chip_data() in arch_setup_msi_irq() is useless.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 drivers/pci/msi.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 782b242..242d775 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -41,8 +41,6 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	if (err < 0)
 		return err;
 
-	irq_set_chip_data(desc->irq, chip);
-
 	return 0;
 }
 
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 07/20] x86/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip apic_msi_chip instead of weak arch
functions to configure MSI/MSI-X in x86.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/x86/include/asm/pci.h     |    1 +
 arch/x86/kernel/apic/io_apic.c |   20 ++++++++++++++++----
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 0892ea0..878a06d 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -101,6 +101,7 @@ void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 		  unsigned int irq_base, unsigned int irq_offset);
+extern struct msi_chip *x86_msi_chip;
 #else
 #define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 2609dcd..eb8ab7c 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3077,24 +3077,25 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 	return 0;
 }
 
-int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+int native_setup_msi_irqs(struct device *dev, int nvec, int type)
 {
 	struct msi_desc *msidesc;
 	unsigned int irq;
 	int node, ret;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
 	/* Multiple MSI vectors only supported with interrupt remapping */
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
 		return 1;
 
-	node = dev_to_node(&dev->dev);
+	node = dev_to_node(dev);
 
-	list_for_each_entry(msidesc, &dev->msi_list, list) {
+	list_for_each_entry(msidesc, &pdev->msi_list, list) {
 		irq = irq_alloc_hwirq(node);
 		if (!irq)
 			return -ENOSPC;
 
-		ret = setup_msi_irq(dev, msidesc, irq, 0);
+		ret = setup_msi_irq(pdev, msidesc, irq, 0);
 		if (ret < 0) {
 			irq_free_hwirq(irq);
 			return ret;
@@ -3214,6 +3215,17 @@ int default_setup_hpet_msi(unsigned int irq, unsigned int id)
 }
 #endif
 
+struct msi_chip apic_msi_chip = {
+	.setup_irqs = native_setup_msi_irqs,
+	.teardown_irq = native_teardown_msi_irq,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return x86_msi_chip;
+}
+
+struct msi_chip *x86_msi_chip = &apic_msi_chip;
 #endif /* CONFIG_PCI_MSI */
 /*
  * Hypertransport interrupt support
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 01/20] x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Commit 0e4ccb150 added two __weak arch functions arch_msix_mask_irq()
and arch_msi_mask_irq() to fix a bug found when running xen in x86.
Introduced these two funcntions make MSI code complex. This patch
reverted commit 0e4ccb150 and add #ifdef for x86 msi_chip to fix this
bug for simplicity. Also this is preparation for using struct
msi_chip instead of weak arch MSI functions in all platforms.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 arch/x86/include/asm/x86_init.h |    3 ---
 arch/x86/kernel/apic/io_apic.c  |   15 +++++++++++++++
 arch/x86/kernel/x86_init.c      |   10 ----------
 arch/x86/pci/xen.c              |   13 +------------
 drivers/pci/msi.c               |   22 ++++++----------------
 include/linux/msi.h             |    2 --
 6 files changed, 22 insertions(+), 43 deletions(-)

diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index e45e4da..f58a9c7 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -172,7 +172,6 @@ struct x86_platform_ops {
 
 struct pci_dev;
 struct msi_msg;
-struct msi_desc;
 
 struct x86_msi_ops {
 	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
@@ -183,8 +182,6 @@ struct x86_msi_ops {
 	void (*teardown_msi_irqs)(struct pci_dev *dev);
 	void (*restore_msi_irqs)(struct pci_dev *dev);
 	int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
-	u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag);
-	u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag);
 };
 
 struct IO_APIC_route_entry;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 81e08ef..2609dcd 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3019,14 +3019,29 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
+#ifdef CONFIG_XEN
+static void nop_unmask_msi_irq(struct irq_data *data)
+{
+}
+
+static void nop_mask_msi_irq(struct irq_data *data)
+{
+}
+#endif
+
 /*
  * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
  * which implement the MSI or MSI-X Capability Structure.
  */
 static struct irq_chip msi_chip = {
 	.name			= "PCI-MSI",
+#ifdef CONFIG_XEN
+	.irq_unmask		= nop_unmask_msi_irq,
+	.irq_mask		= nop_mask_msi_irq,
+#else
 	.irq_unmask		= unmask_msi_irq,
 	.irq_mask		= mask_msi_irq,
+#endif
 	.irq_ack		= ack_apic_edge,
 	.irq_set_affinity	= msi_set_affinity,
 	.irq_retrigger		= ioapic_retrigger_irq,
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index e48b674..234b072 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -116,8 +116,6 @@ struct x86_msi_ops x86_msi = {
 	.teardown_msi_irqs	= default_teardown_msi_irqs,
 	.restore_msi_irqs	= default_restore_msi_irqs,
 	.setup_hpet_msi		= default_setup_hpet_msi,
-	.msi_mask_irq		= default_msi_mask_irq,
-	.msix_mask_irq		= default_msix_mask_irq,
 };
 
 /* MSI arch specific hooks */
@@ -140,14 +138,6 @@ void arch_restore_msi_irqs(struct pci_dev *dev)
 {
 	x86_msi.restore_msi_irqs(dev);
 }
-u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
-{
-	return x86_msi.msi_mask_irq(desc, mask, flag);
-}
-u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag)
-{
-	return x86_msi.msix_mask_irq(desc, flag);
-}
 #endif
 
 struct x86_io_apic_ops x86_io_apic_ops = {
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 905956f..55c7858 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -393,14 +393,7 @@ static void xen_teardown_msi_irq(unsigned int irq)
 {
 	xen_destroy_irq(irq);
 }
-static u32 xen_nop_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
-{
-	return 0;
-}
-static u32 xen_nop_msix_mask_irq(struct msi_desc *desc, u32 flag)
-{
-	return 0;
-}
+
 #endif
 
 int __init pci_xen_init(void)
@@ -424,8 +417,6 @@ int __init pci_xen_init(void)
 	x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
 	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
 	x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
-	x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
-	x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
 #endif
 	return 0;
 }
@@ -505,8 +496,6 @@ int __init pci_xen_initial_domain(void)
 	x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
 	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
 	x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs;
-	x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
-	x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
 #endif
 	xen_setup_acpi_sci();
 	__acpi_register_gsi = acpi_register_gsi_xen;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 5a40516..bff25df 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -173,7 +173,7 @@ static inline __attribute_const__ u32 msi_mask(unsigned x)
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
  */
-u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
 	u32 mask_bits = desc->masked;
 
@@ -187,14 +187,9 @@ u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 	return mask_bits;
 }
 
-__weak u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
-{
-	return default_msi_mask_irq(desc, mask, flag);
-}
-
 static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-	desc->masked = arch_msi_mask_irq(desc, mask, flag);
+	desc->masked = __msi_mask_irq(desc, mask, flag);
 }
 
 /*
@@ -204,7 +199,7 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
  * file.  This saves a few milliseconds when initialising devices with lots
  * of MSI-X interrupts.
  */
-u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag)
+static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag)
 {
 	u32 mask_bits = desc->masked;
 	unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
@@ -217,14 +212,9 @@ u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag)
 	return mask_bits;
 }
 
-__weak u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag)
-{
-	return default_msix_mask_irq(desc, flag);
-}
-
 static void msix_mask_irq(struct msi_desc *desc, u32 flag)
 {
-	desc->masked = arch_msix_mask_irq(desc, flag);
+	desc->masked = __msix_mask_irq(desc, flag);
 }
 
 static void msi_set_mask_bit(struct irq_data *data, u32 flag)
@@ -893,7 +883,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
 	/* Return the device with MSI unmasked as initial states */
 	mask = msi_mask(desc->msi_attrib.multi_cap);
 	/* Keep cached state to be restored */
-	arch_msi_mask_irq(desc, mask, ~mask);
+	__msi_mask_irq(desc, mask, ~mask);
 
 	/* Restore dev->irq to its default pin-assertion irq */
 	dev->irq = desc->msi_attrib.default_irq;
@@ -993,7 +983,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
 	/* Return the device with MSI-X masked as initial states */
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		/* Keep cached states to be restored */
-		arch_msix_mask_irq(entry, 1);
+		__msix_mask_irq(entry, 1);
 	}
 
 	msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 8103f32..78e6b6e 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -65,8 +65,6 @@ void arch_restore_msi_irqs(struct pci_dev *dev);
 
 void default_teardown_msi_irqs(struct pci_dev *dev);
 void default_restore_msi_irqs(struct pci_dev *dev);
-u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
-u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag);
 
 struct msi_chip {
 	struct module *owner;
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 00/20] Use msi_chip to configure MSI/MSI-X in all platforms
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller

This series is mainly to use msi_chip instead of currently weak arch functions
across all platforms. Also clean up current MSI code and make drivers support
MSI easier.  

Yijing Wang (20):
  x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()
  MSI: Clean up struct msi_chip argument
  PCI/MSI: Remove useless bus->msi assignment
  MSI: Remove the redundant irq_set_chip_data()
  MSI: Refactor struct msi_chip to become more common
  PCI/MSI: Introduce arch_get_match_msi_chip() to find the match
    msi_chip
  x86/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  x86/xen/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  irq_remapping/MSI: Use msi_chip instead of arch func to configure
    MSI/MSI-X
  x86/MSI: Remove unused MSI weak arch functions
  MIPS/Octeon/MSI: Use msi_chip instead of arch func to configure
    MSI/MSI-X
  MIPS/Xlp/MSI: Use msi_chip instead of arch func to configure
    MSI/MSI-X
  MIPS/xlr/MSI: Use msi_chip instead of arch func to configure
    MSI/MSI-X
  Powerpc/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  s390/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  arm/iop13xx/MSI: Use msi_chip instead of arch func to configure
    MSI/MSI-X
  IA64/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  Sparc/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  tile/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
  PCI/MSI: Clean up unused MSI arch functions

 arch/arm/mach-iop13xx/include/mach/pci.h |    2 +
 arch/arm/mach-iop13xx/iq81340mc.c        |    1 +
 arch/arm/mach-iop13xx/iq81340sc.c        |    1 +
 arch/arm/mach-iop13xx/msi.c              |   14 +++-
 arch/arm/mach-iop13xx/pci.c              |    6 ++
 arch/ia64/kernel/msi_ia64.c              |   18 +++-
 arch/mips/pci/msi-octeon.c               |   45 ++++------
 arch/mips/pci/msi-xlp.c                  |   15 +++-
 arch/mips/pci/pci-xlr.c                  |   19 +++-
 arch/powerpc/kernel/msi.c                |   23 ++++--
 arch/s390/pci/pci.c                      |   16 +++-
 arch/sparc/kernel/pci.c                  |   18 +++-
 arch/tile/kernel/pci_gx.c                |   20 +++-
 arch/x86/include/asm/pci.h               |    4 +-
 arch/x86/include/asm/x86_init.h          |    3 -
 arch/x86/kernel/apic/io_apic.c           |   35 +++++++-
 arch/x86/kernel/x86_init.c               |   34 -------
 arch/x86/pci/xen.c                       |  139 ++++++++++++++++--------------
 drivers/iommu/irq_remapping.c            |   13 ++-
 drivers/irqchip/irq-armada-370-xp.c      |   12 +--
 drivers/pci/host/pci-tegra.c             |    9 ++-
 drivers/pci/host/pcie-designware.c       |    6 +-
 drivers/pci/host/pcie-rcar.c             |    9 ++-
 drivers/pci/msi.c                        |  118 ++++++++++++--------------
 drivers/pci/probe.c                      |    1 -
 include/linux/msi.h                      |   13 ++--
 26 files changed, 338 insertions(+), 256 deletions(-)

^ permalink raw reply

* [RFC PATCH 06/20] PCI/MSI: Introduce arch_get_match_msi_chip() to find the match msi_chip
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce __weak arch_get_match_msi_chip() to find the match msi_chip.
We prepare to use struct msi_chip to eliminate arch_xxx functions
in all platforms. The MSI device and the msi_chip binding is platform
specific. For instance, in x86, LAPICs receive all MSI irq, but in
arm, PCI device usually deliver their MSI to PCI hostbridge, if more
than one msi_chip found in system, DTS file will report the binding
between MSI devices and target msi_chip. So we need a platform implemented
interface to do that.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 drivers/pci/msi.c |   30 ++++++++++++++++++++++++++----
 1 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7b7abe9..feba5dd 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -29,10 +29,22 @@ static int pci_msi_enable = 1;
 
 /* Arch hooks */
 
-int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+struct msi_chip * __weak arch_get_match_msi_chip(struct device *dev)
+{
+	if (dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		struct msi_chip *chip = pdev->bus->msi;
+
+		return chip;
+	}
+
+	return NULL;
+}
+
+int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-	struct msi_chip *chip = dev->bus->msi;
 	int err;
+	struct msi_chip *chip = arch_get_match_msi_chip(&dev->dev);
 
 	if (!chip || !chip->setup_irq)
 		return -EINVAL;
@@ -46,7 +58,8 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 
 void __weak arch_teardown_msi_irq(unsigned int irq)
 {
-	struct msi_chip *chip = irq_get_chip_data(irq);
+	struct msi_desc *entry = irq_get_msi_desc(irq);
+	struct msi_chip *chip = arch_get_match_msi_chip(&entry->dev->dev);
 
 	if (!chip || !chip->teardown_irq)
 		return;
@@ -56,7 +69,7 @@ void __weak arch_teardown_msi_irq(unsigned int irq)
 
 int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 {
-	struct msi_chip *chip = dev->bus->msi;
+	struct msi_chip *chip = arch_get_match_msi_chip(&dev->dev);
 
 	if (!chip || !chip->check_device)
 		return 0;
@@ -68,7 +81,12 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_desc *entry;
 	int ret;
+	struct msi_chip *chip;
 
+	chip = arch_get_match_msi_chip(&dev->dev);
+	if (chip && chip->setup_irqs)
+		return chip->setup_irqs(&dev->dev, nvec, type);
+
 	/*
 	 * If an architecture wants to support multiple MSI, it needs to
 	 * override arch_setup_msi_irqs()
@@ -133,6 +151,10 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq)
 
 void __weak arch_restore_msi_irqs(struct pci_dev *dev)
 {
+	struct msi_chip *chip = arch_get_msi_chip(&dev->dev);
+	if (chip && chip->restore_irqs)
+		return chip->restore_irqs(&dev->dev);
+
 	return default_restore_msi_irqs(dev);
 }
 
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 03/20] PCI/MSI: Remove useless bus->msi assignment
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Thierry Reding, Xinwei Hu,
	Yijing Wang, H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Thomas Petazzoni, Tony Luck,
	linux-kernel, iommu, Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Currently, PCI drivers will initialize bus->msi in
pcibios_add_bus(). pcibios_add_bus() will be called
in every pci bus initialization. So the bus->msi
assignment in pci_alloc_child_bus() is useless.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
CC: Thierry Reding <thierry.reding@avionic-design.de>
CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 drivers/pci/probe.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e3cf8a2..8296576 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -677,7 +677,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 
 	child->parent = parent;
 	child->ops = parent->ops;
-	child->msi = parent->msi;
 	child->sysdata = parent->sysdata;
 	child->bus_flags = parent->bus_flags;
 
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 02/20] MSI: Clean up struct msi_chip argument
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Thierry Reding, Xinwei Hu,
	Yijing Wang, H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Thomas Petazzoni, Tony Luck,
	linux-kernel, iommu, Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Msi_chip functions setup_irq/teardown_irq/check_device rarely
use msi_chip argument. We can get msi_chip pointer from the
device pointer or irq number, so clean up msi_chip arguments.
This patch is also preparation for using msi_chip in all
platforms to setup/teardown MSI irqs.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
CC: Thierry Reding <thierry.reding@avionic-design.de>
CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 drivers/irqchip/irq-armada-370-xp.c |   12 +++++-------
 drivers/pci/host/pci-tegra.c        |    8 +++++---
 drivers/pci/host/pcie-designware.c  |    4 ++--
 drivers/pci/host/pcie-rcar.c        |    8 +++++---
 drivers/pci/msi.c                   |    6 +++---
 include/linux/msi.h                 |    8 +++-----
 6 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index c887e6e..ee1f0ba 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -129,9 +129,8 @@ static void armada_370_xp_free_msi(int hwirq)
 	mutex_unlock(&msi_used_lock);
 }
 
-static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
-				       struct pci_dev *pdev,
-				       struct msi_desc *desc)
+static int armada_370_xp_setup_msi_irq(struct pci_dev *pdev,
+		struct msi_desc *desc)
 {
 	struct msi_msg msg;
 	int virq, hwirq;
@@ -156,8 +155,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
 	return 0;
 }
 
-static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
-					   unsigned int irq)
+static void armada_370_xp_teardown_msi_irq(unsigned int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
 	unsigned long hwirq = d->hwirq;
@@ -166,8 +164,8 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
 	armada_370_xp_free_msi(hwirq);
 }
 
-static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev,
-					  int nvec, int type)
+static int armada_370_xp_check_msi_device(struct pci_dev *dev,
+		int nvec, int type)
 {
 	/* We support MSI, but not MSI-X */
 	if (type == PCI_CAP_ID_MSI)
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 869a921..3872bc0 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1192,9 +1192,10 @@ static irqreturn_t tegra_pcie_msi_irq(int irq, void *data)
 	return processed > 0 ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int tegra_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
+static int tegra_msi_setup_irq(struct pci_dev *pdev,
 			       struct msi_desc *desc)
 {
+	struct msi_chip *chip = pdev->bus->msi;
 	struct tegra_msi *msi = to_tegra_msi(chip);
 	struct msi_msg msg;
 	unsigned int irq;
@@ -1220,10 +1221,11 @@ static int tegra_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
 	return 0;
 }
 
-static void tegra_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
+static void tegra_msi_teardown_irq(unsigned int irq)
 {
-	struct tegra_msi *msi = to_tegra_msi(chip);
 	struct irq_data *d = irq_get_irq_data(irq);
+	struct msi_chip *chip = irq_get_chip_data(irq);
+	struct tegra_msi *msi = to_tegra_msi(chip);
 
 	tegra_msi_free(msi, d->hwirq);
 }
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 52bd3a1..2204456 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -342,7 +342,7 @@ static void clear_irq(unsigned int irq)
 	msi->msi_attrib.multiple = 0;
 }
 
-static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
+static int dw_msi_setup_irq(struct pci_dev *pdev,
 			struct msi_desc *desc)
 {
 	int irq, pos, msgvec;
@@ -384,7 +384,7 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
 	return 0;
 }
 
-static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
+static void dw_msi_teardown_irq(unsigned int irq)
 {
 	clear_irq(irq);
 }
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 4884ee5..647bc9f 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -615,9 +615,10 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
+static int rcar_msi_setup_irq(struct pci_dev *pdev,
 			      struct msi_desc *desc)
 {
+	struct msi_chip *chip = pdev->bus->msi;
 	struct rcar_msi *msi = to_rcar_msi(chip);
 	struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip);
 	struct msi_msg msg;
@@ -645,10 +646,11 @@ static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
 	return 0;
 }
 
-static void rcar_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
+static void rcar_msi_teardown_irq(unsigned int irq)
 {
-	struct rcar_msi *msi = to_rcar_msi(chip);
 	struct irq_data *d = irq_get_irq_data(irq);
+	struct msi_chip *chip = irq_get_chip_data(irq);
+	struct rcar_msi *msi = to_rcar_msi(chip);
 
 	rcar_msi_free(msi, d->hwirq);
 }
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index bff25df..782b242 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -37,7 +37,7 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	if (!chip || !chip->setup_irq)
 		return -EINVAL;
 
-	err = chip->setup_irq(chip, dev, desc);
+	err = chip->setup_irq(dev, desc);
 	if (err < 0)
 		return err;
 
@@ -53,7 +53,7 @@ void __weak arch_teardown_msi_irq(unsigned int irq)
 	if (!chip || !chip->teardown_irq)
 		return;
 
-	chip->teardown_irq(chip, irq);
+	chip->teardown_irq(irq);
 }
 
 int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
@@ -63,7 +63,7 @@ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 	if (!chip || !chip->check_device)
 		return 0;
 
-	return chip->check_device(chip, dev, nvec, type);
+	return chip->check_device(dev, nvec, type);
 }
 
 int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 78e6b6e..a510d25 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -72,11 +72,9 @@ struct msi_chip {
 	struct device_node *of_node;
 	struct list_head list;
 
-	int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
-			 struct msi_desc *desc);
-	void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
-	int (*check_device)(struct msi_chip *chip, struct pci_dev *dev,
-			    int nvec, int type);
+	int (*setup_irq)(struct pci_dev *dev, struct msi_desc *desc);
+	void (*teardown_irq)(unsigned int irq);
+	int (*check_device)(struct pci_dev *dev, int nvec, int type);
 };
 
 #endif /* LINUX_MSI_H */
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 05/20] MSI: Refactor struct msi_chip to become more common
From: Yijing Wang @ 2014-08-12  7:25 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Thierry Reding, Xinwei Hu,
	Yijing Wang, H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Thomas Petazzoni, Tony Luck,
	linux-kernel, iommu, Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Now there are a lot of __weak arch functions in MSI code.
These functions make MSI driver complex, It's time to
refactor it. Add .restore_irq(), .setup_irqs(), .teardown_irqs()
to make msi_chip common across all platforms.
Also replace the argument "struct pci_dev" with "struct device"
to support future Non-PCI MSI device.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
CC: Thierry Reding <thierry.reding@avionic-design.de>
CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 drivers/irqchip/irq-armada-370-xp.c |    4 ++--
 drivers/pci/host/pci-tegra.c        |    3 ++-
 drivers/pci/host/pcie-designware.c  |    4 ++--
 drivers/pci/host/pcie-rcar.c        |    3 ++-
 drivers/pci/msi.c                   |    4 ++--
 include/linux/msi.h                 |    7 +++++--
 6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index ee1f0ba..3761e52 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -129,7 +129,7 @@ static void armada_370_xp_free_msi(int hwirq)
 	mutex_unlock(&msi_used_lock);
 }
 
-static int armada_370_xp_setup_msi_irq(struct pci_dev *pdev, 
+static int armada_370_xp_setup_msi_irq(struct device *dev,
 		struct msi_desc *desc)
 {
 	struct msi_msg msg;
@@ -164,7 +164,7 @@ static void armada_370_xp_teardown_msi_irq(unsigned int irq)
 	armada_370_xp_free_msi(hwirq);
 }
 
-static int armada_370_xp_check_msi_device(struct pci_dev *dev, 
+static int armada_370_xp_check_msi_device(struct device *dev,
 		int nvec, int type)
 {
 	/* We support MSI, but not MSI-X */
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 3872bc0..a2fa0ec 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1192,9 +1192,10 @@ static irqreturn_t tegra_pcie_msi_irq(int irq, void *data)
 	return processed > 0 ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int tegra_msi_setup_irq(struct pci_dev *pdev,
+static int tegra_msi_setup_irq(struct device *dev,
 			       struct msi_desc *desc)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct msi_chip *chip = pdev->bus->msi;
 	struct tegra_msi *msi = to_tegra_msi(chip);
 	struct msi_msg msg;
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2204456..9c3816d 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -342,12 +342,12 @@ static void clear_irq(unsigned int irq)
 	msi->msi_attrib.multiple = 0;
 }
 
-static int dw_msi_setup_irq(struct pci_dev *pdev,
-			struct msi_desc *desc)
+static int dw_msi_setup_irq(struct device *dev, struct msi_desc *desc)
 {
 	int irq, pos, msgvec;
 	u16 msg_ctr;
 	struct msi_msg msg;
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
 
 	if (!pp) {
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 647bc9f..fa33432 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -615,9 +615,10 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int rcar_msi_setup_irq(struct pci_dev *pdev,
+static int rcar_msi_setup_irq(struct device *dev,
 			      struct msi_desc *desc)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct msi_chip *chip = pdev->bus->msi;
 	struct rcar_msi *msi = to_rcar_msi(chip);
 	struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 242d775..7b7abe9 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -37,7 +37,7 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	if (!chip || !chip->setup_irq)
 		return -EINVAL;
 
-	err = chip->setup_irq(dev, desc);
+	err = chip->setup_irq(&dev->dev, desc);
 	if (err < 0)
 		return err;
 
@@ -61,7 +61,7 @@ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 	if (!chip || !chip->check_device)
 		return 0;
 
-	return chip->check_device(dev, nvec, type);
+	return chip->check_device(&dev->dev, nvec, type);
 }
 
 int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
diff --git a/include/linux/msi.h b/include/linux/msi.h
index a510d25..2068d25 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -72,9 +72,12 @@ struct msi_chip {
 	struct device_node *of_node;
 	struct list_head list;
 
-	int (*setup_irq)(struct pci_dev *dev, struct msi_desc *desc);
+	int (*check_device)(struct device *dev, int nvec, int type);
+	int (*setup_irq)(struct device *dev, struct msi_desc *desc);
+	int (*setup_irqs)(struct device *dev, int nvec, int type);
 	void (*teardown_irq)(unsigned int irq);
-	int (*check_device)(struct pci_dev *dev, int nvec, int type);
+	void (*teardown_irqs)(struct device *dev);
+	void (*restore_irqs)(struct device *dev);
 };
 
 #endif /* LINUX_MSI_H */
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 10/20] x86/MSI: Remove unused MSI weak arch functions
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Now we can clean up MSI weak arch functions in x86.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/x86/include/asm/pci.h     |    3 ---
 arch/x86/kernel/apic/io_apic.c |    2 +-
 arch/x86/kernel/x86_init.c     |   24 ------------------------
 3 files changed, 1 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 878a06d..34f9676 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -96,14 +96,11 @@ extern void pci_iommu_alloc(void);
 #ifdef CONFIG_PCI_MSI
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
-int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void native_teardown_msi_irq(unsigned int irq);
-void native_restore_msi_irqs(struct pci_dev *dev);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 		  unsigned int irq_base, unsigned int irq_offset);
 extern struct msi_chip *x86_msi_chip;
 #else
-#define native_setup_msi_irqs		NULL
 #define native_teardown_msi_irq		NULL
 #endif
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index eb8ab7c..e3326d9 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3077,7 +3077,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 	return 0;
 }
 
-int native_setup_msi_irqs(struct device *dev, int nvec, int type)
+static int native_setup_msi_irqs(struct device *dev, int nvec, int type)
 {
 	struct msi_desc *msidesc;
 	unsigned int irq;
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 234b072..cc32568 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -110,34 +110,10 @@ EXPORT_SYMBOL_GPL(x86_platform);
 
 #if defined(CONFIG_PCI_MSI)
 struct x86_msi_ops x86_msi = {
-	.setup_msi_irqs		= native_setup_msi_irqs,
 	.compose_msi_msg	= native_compose_msi_msg,
-	.teardown_msi_irq	= native_teardown_msi_irq,
-	.teardown_msi_irqs	= default_teardown_msi_irqs,
-	.restore_msi_irqs	= default_restore_msi_irqs,
 	.setup_hpet_msi		= default_setup_hpet_msi,
 };
 
-/* MSI arch specific hooks */
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	return x86_msi.setup_msi_irqs(dev, nvec, type);
-}
-
-void arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-	x86_msi.teardown_msi_irqs(dev);
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
-	x86_msi.teardown_msi_irq(irq);
-}
-
-void arch_restore_msi_irqs(struct pci_dev *dev)
-{
-	x86_msi.restore_msi_irqs(dev);
-}
 #endif
 
 struct x86_io_apic_ops x86_io_apic_ops = {
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 12/20] MIPS/Xlp/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip xlp_chip instead of weak arch
functions to configure MSI/MSI-X.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/mips/pci/msi-xlp.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index fa374fe..6c27346 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -245,7 +245,7 @@ static struct irq_chip xlp_msix_chip = {
 	.irq_unmask	= unmask_msi_irq,
 };
 
-void arch_teardown_msi_irq(unsigned int irq)
+void xlp_teardown_msi_irq(unsigned int irq)
 {
 }
 
@@ -452,11 +452,12 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
 	return 0;
 }
 
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+int xlp_setup_msi_irq(struct device *d, struct msi_desc *desc)
 {
 	struct pci_dev *lnkdev;
 	uint64_t lnkbase;
 	int node, link, slot;
+	struct pci_dev *dev = to_pci_dev(d);
 
 	lnkdev = xlp_get_pcie_link(dev);
 	if (lnkdev == NULL) {
@@ -474,6 +475,16 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 		return xlp_setup_msi(lnkbase, node, link, desc);
 }
 
+struct msi_chip xlp_chip = {
+	.setup_irq = xlp_setup_msi_irq,
+	.teardown_irq = xlp_teardown_msi_irq,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return &xlp_chip;
+}
+
 void __init xlp_init_node_msi_irqs(int node, int link)
 {
 	struct nlm_soc_info *nodep;
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 09/20] irq_remapping/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip remap_msi_chip instead of weak arch
functions to configure irq remapping MSI/MSI-X in x86.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 drivers/iommu/irq_remapping.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 33c4395..f494b51 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -139,15 +139,20 @@ error:
 	return ret;
 }
 
-static int irq_remapping_setup_msi_irqs(struct pci_dev *dev,
+static int irq_remapping_setup_msi_irqs(struct device *dev,
 					int nvec, int type)
 {
 	if (type == PCI_CAP_ID_MSI)
-		return do_setup_msi_irqs(dev, nvec);
+		return do_setup_msi_irqs(to_pci_dev(dev), nvec);
 	else
-		return do_setup_msix_irqs(dev, nvec);
+		return do_setup_msix_irqs(to_pci_dev(dev), nvec);
 }
 
+struct msi_chip remap_msi_chip = {
+	.setup_irqs = irq_remapping_setup_msi_irqs,
+	.teardown_irq = native_teardown_msi_irq,
+};
+
 static void eoi_ioapic_pin_remapped(int apic, int pin, int vector)
 {
 	/*
@@ -165,9 +170,9 @@ static void __init irq_remapping_modify_x86_ops(void)
 	x86_io_apic_ops.set_affinity	= set_remapped_irq_affinity;
 	x86_io_apic_ops.setup_entry	= setup_ioapic_remapped_entry;
 	x86_io_apic_ops.eoi_ioapic_pin	= eoi_ioapic_pin_remapped;
-	x86_msi.setup_msi_irqs		= irq_remapping_setup_msi_irqs;
 	x86_msi.setup_hpet_msi		= setup_hpet_msi_remapped;
 	x86_msi.compose_msi_msg		= compose_remapped_msi_msg;
+	x86_msi_chip = &remap_msi_chip;
 }
 
 static __init int setup_nointremap(char *str)
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 13/20] MIPS/xlr/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip xlr_msi_chip instead of weak arch
functions to configure MSI/MSI-X.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/mips/pci/pci-xlr.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
index 0dde803..6eef164 100644
--- a/arch/mips/pci/pci-xlr.c
+++ b/arch/mips/pci/pci-xlr.c
@@ -214,11 +214,11 @@ static int get_irq_vector(const struct pci_dev *dev)
 }
 
 #ifdef CONFIG_PCI_MSI
-void arch_teardown_msi_irq(unsigned int irq)
+void xlr_teardown_msi_irq(unsigned int irq)
 {
 }
 
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+int xlr_setup_msi_irq(struct device *dev, struct msi_desc *desc)
 {
 	struct msi_msg msg;
 	struct pci_dev *lnk;
@@ -233,7 +233,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	 * Enable MSI on the XLS PCIe controller bridge which was disabled
 	 * at enumeration, the bridge MSI capability is at 0x50
 	 */
-	lnk = xls_get_pcie_link(dev);
+	lnk = xls_get_pcie_link(to_pci_dev(dev));
 	if (lnk == NULL)
 		return 1;
 
@@ -243,7 +243,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 		pci_write_config_word(lnk, 0x50 + PCI_MSI_FLAGS, val);
 	}
 
-	irq = get_irq_vector(dev);
+	irq = get_irq_vector(to_pci_dev(dev));
 	if (irq <= 0)
 		return 1;
 
@@ -263,6 +263,17 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	write_msi_msg(irq, &msg);
 	return 0;
 }
+
+struct msi_chip xlr_msi_chip = {
+	.setup_irq = xlr_setup_msi_irq,
+	.teardown_irq = xlr_teardown_msi_irq,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return &xlr_msi_chip;
+}
+
 #endif
 
 /* Extra ACK needed for XLR on chip PCI controller */
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 08/20] x86/xen/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip xen_msi_chip instead of weak arch
functions to configure MSI/MSI-X.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 arch/x86/pci/xen.c |  128 +++++++++++++++++++++++++++++----------------------
 1 files changed, 73 insertions(+), 55 deletions(-)

diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 55c7858..0c4ed47 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -156,11 +156,12 @@ static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
 struct xen_pci_frontend_ops *xen_pci_frontend;
 EXPORT_SYMBOL_GPL(xen_pci_frontend);
 
-static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int xen_setup_msi_irqs(struct device *dev, int nvec, int type)
 {
 	int irq, ret, i;
 	struct msi_desc *msidesc;
 	int *v;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
 		return 1;
@@ -170,14 +171,14 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		return -ENOMEM;
 
 	if (type == PCI_CAP_ID_MSIX)
-		ret = xen_pci_frontend_enable_msix(dev, v, nvec);
+		ret = xen_pci_frontend_enable_msix(pdev, v, nvec);
 	else
-		ret = xen_pci_frontend_enable_msi(dev, v);
+		ret = xen_pci_frontend_enable_msi(pdev, v);
 	if (ret)
 		goto error;
 	i = 0;
-	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
+	list_for_each_entry(msidesc, &pdev->msi_list, list) {
+		irq = xen_bind_pirq_msi_to_irq(pdev, msidesc, v[i],
 					       (type == PCI_CAP_ID_MSI) ? nvec : 1,
 					       (type == PCI_CAP_ID_MSIX) ?
 					       "pcifront-msi-x" :
@@ -193,7 +194,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 	return 0;
 
 error:
-	dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
+	dev_err(dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
 free:
 	kfree(v);
 	return ret;
@@ -218,47 +219,48 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
 	msg->data = XEN_PIRQ_MSI_DATA;
 }
 
-static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int xen_hvm_setup_msi_irqs(struct device *dev, int nvec, int type)
 {
 	int irq, pirq;
 	struct msi_desc *msidesc;
 	struct msi_msg msg;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
 		return 1;
 
-	list_for_each_entry(msidesc, &dev->msi_list, list) {
+	list_for_each_entry(msidesc, &pdev->msi_list, list) {
 		__read_msi_msg(msidesc, &msg);
 		pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
 			((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
 		if (msg.data != XEN_PIRQ_MSI_DATA ||
 		    xen_irq_from_pirq(pirq) < 0) {
-			pirq = xen_allocate_pirq_msi(dev, msidesc);
+			pirq = xen_allocate_pirq_msi(pdev, msidesc);
 			if (pirq < 0) {
 				irq = -ENODEV;
 				goto error;
 			}
-			xen_msi_compose_msg(dev, pirq, &msg);
+			xen_msi_compose_msg(pdev, pirq, &msg);
 			__write_msi_msg(msidesc, &msg);
-			dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
+			dev_dbg(dev, "xen: msi bound to pirq=%d\n", pirq);
 		} else {
-			dev_dbg(&dev->dev,
+			dev_dbg(dev,
 				"xen: msi already bound to pirq=%d\n", pirq);
 		}
-		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
+		irq = xen_bind_pirq_msi_to_irq(pdev, msidesc, pirq,
 					       (type == PCI_CAP_ID_MSI) ? nvec : 1,
 					       (type == PCI_CAP_ID_MSIX) ?
 					       "msi-x" : "msi",
 					       DOMID_SELF);
 		if (irq < 0)
 			goto error;
-		dev_dbg(&dev->dev,
+		dev_dbg(dev,
 			"xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
 	}
 	return 0;
 
 error:
-	dev_err(&dev->dev,
+	dev_err(dev,
 		"Xen PCI frontend has not registered MSI/MSI-X support!\n");
 	return irq;
 }
@@ -266,16 +268,17 @@ error:
 #ifdef CONFIG_XEN_DOM0
 static bool __read_mostly pci_seg_supported = true;
 
-static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int xen_initdom_setup_msi_irqs(struct device *dev, int nvec, int type)
 {
 	int ret = 0;
 	struct msi_desc *msidesc;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
-	list_for_each_entry(msidesc, &dev->msi_list, list) {
+	list_for_each_entry(msidesc, &pdev->msi_list, list) {
 		struct physdev_map_pirq map_irq;
 		domid_t domid;
 
-		domid = ret = xen_find_device_domain_owner(dev);
+		domid = ret = xen_find_device_domain_owner(pdev);
 		/* N.B. Casting int's -ENODEV to uint16_t results in 0xFFED,
 		 * hence check ret value for < 0. */
 		if (ret < 0)
@@ -286,9 +289,9 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
 		map_irq.index = -1;
 		map_irq.pirq = -1;
-		map_irq.bus = dev->bus->number |
-			      (pci_domain_nr(dev->bus) << 16);
-		map_irq.devfn = dev->devfn;
+		map_irq.bus = pdev->bus->number |
+			      (pci_domain_nr(pdev->bus) << 16);
+		map_irq.devfn = pdev->devfn;
 
 		if (type == PCI_CAP_ID_MSI && nvec > 1) {
 			map_irq.type = MAP_PIRQ_TYPE_MULTI_MSI;
@@ -297,12 +300,12 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 			int pos;
 			u32 table_offset, bir;
 
-			pos = dev->msix_cap;
-			pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
+			pos = pdev->msix_cap;
+			pci_read_config_dword(pdev, pos + PCI_MSIX_TABLE,
 					      &table_offset);
 			bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR);
 
-			map_irq.table_base = pci_resource_start(dev, bir);
+			map_irq.table_base = pci_resource_start(pdev, bir);
 			map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
 		}
 
@@ -320,23 +323,23 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 			ret = 1;
 			goto out;
 		}
-		if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
+		if (ret == -EINVAL && !pci_domain_nr(pdev->bus)) {
 			map_irq.type = MAP_PIRQ_TYPE_MSI;
 			map_irq.index = -1;
 			map_irq.pirq = -1;
-			map_irq.bus = dev->bus->number;
+			map_irq.bus = pdev->bus->number;
 			ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
 						    &map_irq);
 			if (ret != -EINVAL)
 				pci_seg_supported = false;
 		}
 		if (ret) {
-			dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
+			dev_warn(dev, "xen map irq failed %d for %d domain\n",
 				 ret, domid);
 			goto out;
 		}
 
-		ret = xen_bind_pirq_msi_to_irq(dev, msidesc, map_irq.pirq,
+		ret = xen_bind_pirq_msi_to_irq(pdev, msidesc, map_irq.pirq,
 		                               (type == PCI_CAP_ID_MSI) ? nvec : 1,
 		                               (type == PCI_CAP_ID_MSIX) ? "msi-x" : "msi",
 		                               domid);
@@ -348,16 +351,17 @@ out:
 	return ret;
 }
 
-static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
+static void xen_initdom_restore_msi_irqs(struct device *dev)
 {
 	int ret = 0;
+	struct pci_dev *pdev = to_pci_dev(dev);
 
 	if (pci_seg_supported) {
 		struct physdev_pci_device restore_ext;
 
-		restore_ext.seg = pci_domain_nr(dev->bus);
-		restore_ext.bus = dev->bus->number;
-		restore_ext.devfn = dev->devfn;
+		restore_ext.seg = pci_domain_nr(pdev->bus);
+		restore_ext.bus = pdev->bus->number;
+		restore_ext.devfn = pdev->devfn;
 		ret = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi_ext,
 					&restore_ext);
 		if (ret == -ENOSYS)
@@ -367,33 +371,45 @@ static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
 	if (!pci_seg_supported) {
 		struct physdev_restore_msi restore;
 
-		restore.bus = dev->bus->number;
-		restore.devfn = dev->devfn;
+		restore.bus = pdev->bus->number;
+		restore.devfn = pdev->devfn;
 		ret = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore);
 		WARN(ret && ret != -ENOSYS, "restore_msi -> %d\n", ret);
 	}
 }
 #endif
 
-static void xen_teardown_msi_irqs(struct pci_dev *dev)
+static void xen_teardown_msi_irq(unsigned int irq)
 {
-	struct msi_desc *msidesc;
-
-	msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
-	if (msidesc->msi_attrib.is_msix)
-		xen_pci_frontend_disable_msix(dev);
-	else
-		xen_pci_frontend_disable_msi(dev);
-
-	/* Free the IRQ's and the msidesc using the generic code. */
-	default_teardown_msi_irqs(dev);
+	xen_destroy_irq(irq);
 }
 
-static void xen_teardown_msi_irq(unsigned int irq)
+static void xen_teardown_msi_irqs(struct device *dev)
 {
-	xen_destroy_irq(irq);
+	struct msi_desc *entry;
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	entry = list_entry(pdev->msi_list.next, struct msi_desc, list);
+	if (entry->msi_attrib.is_msix)
+		xen_pci_frontend_disable_msix(pdev);
+	else
+		xen_pci_frontend_disable_msi(pdev);
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		int i, nvec;
+		if (entry->irq == 0)
+			continue;
+		if (entry->nvec_used)
+			nvec = entry->nvec_used;
+		else
+			nvec = 1 << entry->msi_attrib.multiple;
+		for (i = 0; i < nvec; i++)
+			xen_teardown_msi_irq(entry->irq + i);
+	}
 }
 
+struct msi_chip xen_msi_chip;
+
 #endif
 
 int __init pci_xen_init(void)
@@ -414,9 +430,9 @@ int __init pci_xen_init(void)
 #endif
 
 #ifdef CONFIG_PCI_MSI
-	x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
-	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
-	x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
+	xen_msi_chip.setup_irqs = xen_setup_msi_irqs;
+	xen_msi_chip.teardown_irqs = xen_teardown_msi_irqs;
+	x86_msi_chip = &xen_msi_chip;
 #endif
 	return 0;
 }
@@ -435,8 +451,9 @@ int __init pci_xen_hvm_init(void)
 #endif
 
 #ifdef CONFIG_PCI_MSI
-	x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs;
-	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
+	xen_msi_chip.setup_irqs = xen_hvm_setup_msi_irqs;
+	xen_msi_chip.teardown_irq = xen_teardown_msi_irq;
+	x86_msi_chip = &xen_msi_chip;
 #endif
 	return 0;
 }
@@ -493,9 +510,10 @@ int __init pci_xen_initial_domain(void)
 	int irq;
 
 #ifdef CONFIG_PCI_MSI
-	x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
-	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
-	x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs;
+	xen_msi_chip.setup_irqs = xen_initdom_setup_msi_irqs;
+	xen_msi_chip.teardown_irq = xen_teardown_msi_irq;
+	xen_msi_chip.restore_irqs = xen_initdom_restore_msi_irqs;
+	x86_msi_chip = &xen_msi_chip;
 #endif
 	xen_setup_acpi_sci();
 	__acpi_register_gsi = acpi_register_gsi_xen;
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 20/20] PCI/MSI: Clean up unused MSI arch functions
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Now we use struct msi_chip in all platforms to configure
MSI/MSI-X. We can clean up the unused arch functions.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 drivers/pci/msi.c |   82 ++++++++++++++++++++--------------------------------
 1 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index feba5dd..2d2d4cd 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -41,33 +41,7 @@ struct msi_chip * __weak arch_get_match_msi_chip(struct device *dev)
 	return NULL;
 }
 
-int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) 
-{
-	int err;
-	struct msi_chip *chip = arch_get_match_msi_chip(&dev->dev);
-
-	if (!chip || !chip->setup_irq)
-		return -EINVAL;
-
-	err = chip->setup_irq(&dev->dev, desc);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-void __weak arch_teardown_msi_irq(unsigned int irq)
-{
-	struct msi_desc *entry = irq_get_msi_desc(irq);
-	struct msi_chip *chip = arch_get_match_msi_chip(&entry->dev->dev);
-
-	if (!chip || !chip->teardown_irq)
-		return;
-
-	chip->teardown_irq(irq);
-}
-
-int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+static int msi_check_device(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_chip *chip = arch_get_match_msi_chip(&dev->dev);
 
@@ -77,25 +51,31 @@ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
 	return chip->check_device(&dev->dev, nvec, type);
 }
 
-int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_desc *entry;
 	int ret;
 	struct msi_chip *chip;
 
 	chip = arch_get_match_msi_chip(&dev->dev);
-	if (chip && chip->setup_irqs)
+	if (!chip)
+		return -EINVAL;
+
+	if (chip->setup_irqs)
 		return chip->setup_irqs(&dev->dev, nvec, type);
 	
 	/*
 	 * If an architecture wants to support multiple MSI, it needs to
-	 * override arch_setup_msi_irqs()
+	 * provide chip->setup_irqs()
 	 */
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
 		return 1;
 
+	if (!chip->setup_irq)
+		return -EINVAL;
+
 	list_for_each_entry(entry, &dev->msi_list, list) {
-		ret = arch_setup_msi_irq(dev, entry);
+		ret = chip->setup_irq(&dev->dev, entry);
 		if (ret < 0)
 			return ret;
 		if (ret > 0)
@@ -105,13 +85,20 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 	return 0;
 }
 
-/*
- * We have a default implementation available as a separate non-weak
- * function, as it is used by the Xen x86 PCI code
- */
-void default_teardown_msi_irqs(struct pci_dev *dev)
+static void teardown_msi_irqs(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
+	struct msi_chip *chip;
+
+	chip = arch_get_match_msi_chip(&dev->dev);
+	if (!chip)
+		return;
+
+	if (chip->teardown_irqs)
+		return chip->teardown_irqs(&dev->dev);
+
+	if (!chip->teardown_irq)
+		return;
 
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		int i, nvec;
@@ -122,15 +109,10 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
 		else
 			nvec = 1 << entry->msi_attrib.multiple;
 		for (i = 0; i < nvec; i++)
-			arch_teardown_msi_irq(entry->irq + i);
+			chip->teardown_irq(entry->irq + i);
 	}
 }
 
-void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-	return default_teardown_msi_irqs(dev);
-}
-
 static void default_restore_msi_irq(struct pci_dev *dev, int irq)
 {
 	struct msi_desc *entry;
@@ -149,9 +131,9 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq)
 		write_msi_msg(irq, &entry->msg);
 }
 
-void __weak arch_restore_msi_irqs(struct pci_dev *dev)
+static void restore_msi_irqs(struct pci_dev *dev)
 {
-	struct msi_chip *chip = arch_get_msi_chip(&dev->dev);
+	struct msi_chip *chip = arch_get_match_msi_chip(&dev->dev);
 	if (chip && chip->restore_irqs)
 		return chip->restore_irqs(&dev->dev);
 
@@ -386,7 +368,7 @@ static void free_msi_irqs(struct pci_dev *dev)
 			BUG_ON(irq_has_action(entry->irq + i));
 	}
 
-	arch_teardown_msi_irqs(dev);
+	teardown_msi_irqs(dev);
 
 	list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
 		if (entry->msi_attrib.is_msix) {
@@ -456,7 +438,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
 
 	pci_intx_for_msi(dev, 0);
 	msi_set_enable(dev, 0);
-	arch_restore_msi_irqs(dev);
+	restore_msi_irqs(dev);
 
 	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
 	msi_mask_irq(entry, msi_mask(entry->msi_attrib.multi_cap),
@@ -479,7 +461,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
 	msix_clear_and_set_ctrl(dev, 0,
 				PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
 
-	arch_restore_msi_irqs(dev);
+	restore_msi_irqs(dev);
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		msix_mask_irq(entry, entry->masked);
 	}
@@ -650,7 +632,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
 	list_add_tail(&entry->list, &dev->msi_list);
 
 	/* Configure MSI capability structure */
-	ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
+	ret = setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
 	if (ret) {
 		msi_mask_irq(entry, mask, ~mask);
 		free_msi_irqs(dev);
@@ -766,7 +748,7 @@ static int msix_capability_init(struct pci_dev *dev,
 	if (ret)
 		return ret;
 
-	ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
+	ret = setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
 	if (ret)
 		goto out_avail;
 
@@ -853,7 +835,7 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
 		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
 			return -EINVAL;
 
-	ret = arch_msi_check_device(dev, nvec, type);
+	ret = msi_check_device(dev, nvec, type);
 	if (ret)
 		return ret;
 
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 11/20] MIPS/Octeon/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip octeon_msi_chip instead of weak arch
functions to configure MSI/MSI-X.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/mips/pci/msi-octeon.c |   45 ++++++++++++++++++-------------------------
 1 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
index ab0c5d1..8098066 100644
--- a/arch/mips/pci/msi-octeon.c
+++ b/arch/mips/pci/msi-octeon.c
@@ -57,7 +57,7 @@ static int msi_irq_size;
  *
  * Returns 0 on success.
  */
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+int octeon_setup_msi_irq(struct device *dev, struct msi_desc *desc)
 {
 	struct msi_msg msg;
 	u16 control;
@@ -73,7 +73,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	 * wants.  Most devices only want 1, which will give
 	 * configured_private_bits and request_private_bits equal 0.
 	 */
-	pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+	pci_read_config_word(to_pci_dev(dev), desc->msi_attrib.pos + PCI_MSI_FLAGS,
 			     &control);
 
 	/*
@@ -176,7 +176,7 @@ msi_irq_allocated:
 	/* Update the number of IRQs the device has available to it */
 	control &= ~PCI_MSI_FLAGS_QSIZE;
 	control |= request_private_bits << 4;
-	pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+	pci_write_config_word(to_pci_dev(dev), desc->msi_attrib.pos + PCI_MSI_FLAGS,
 			      control);
 
 	irq_set_msi_desc(irq, desc);
@@ -184,32 +184,14 @@ msi_irq_allocated:
 	return 0;
 }
 
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+int octeon_check_msi_device(struct device *dev, int nvec, int type)
 {
-	struct msi_desc *entry;
-	int ret;
-
 	/*
 	 * MSI-X is not supported.
 	 */
 	if (type == PCI_CAP_ID_MSIX)
 		return -EINVAL;
 
-	/*
-	 * If an architecture wants to support multiple MSI, it needs to
-	 * override arch_setup_msi_irqs()
-	 */
-	if (type == PCI_CAP_ID_MSI && nvec > 1)
-		return 1;
-
-	list_for_each_entry(entry, &dev->msi_list, list) {
-		ret = arch_setup_msi_irq(dev, entry);
-		if (ret < 0)
-			return ret;
-		if (ret > 0)
-			return -ENOSPC;
-	}
-
 	return 0;
 }
 
@@ -219,7 +201,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
  *
  * @irq:    The devices first irq number. There may be multple in sequence.
  */
-void arch_teardown_msi_irq(unsigned int irq)
+void octeon_teardown_msi_irq(unsigned int irq)
 {
 	int number_irqs;
 	u64 bitmask;
@@ -229,7 +211,7 @@ void arch_teardown_msi_irq(unsigned int irq)
 	if ((irq < OCTEON_IRQ_MSI_BIT0)
 		|| (irq > msi_irq_size + OCTEON_IRQ_MSI_BIT0))
 		panic("arch_teardown_msi_irq: Attempted to teardown illegal "
-		      "MSI interrupt (%d)", irq);
+			"MSI interrupt (%d)", irq);
 
 	irq -= OCTEON_IRQ_MSI_BIT0;
 	index = irq / 64;
@@ -242,7 +224,7 @@ void arch_teardown_msi_irq(unsigned int irq)
 	 */
 	number_irqs = 0;
 	while ((irq0 + number_irqs < 64) &&
-	       (msi_multiple_irq_bitmask[index]
+		(msi_multiple_irq_bitmask[index]
 		& (1ull << (irq0 + number_irqs))))
 		number_irqs++;
 	number_irqs++;
@@ -252,7 +234,7 @@ void arch_teardown_msi_irq(unsigned int irq)
 	bitmask <<= irq0;
 	if ((msi_free_irq_bitmask[index] & bitmask) != bitmask)
 		panic("arch_teardown_msi_irq: Attempted to teardown MSI "
-		      "interrupt (%d) not in use", irq);
+			"interrupt (%d) not in use", irq);
 
 	/* Checks are done, update the in use bitmask */
 	spin_lock(&msi_free_irq_bitmask_lock);
@@ -261,6 +243,17 @@ void arch_teardown_msi_irq(unsigned int irq)
 	spin_unlock(&msi_free_irq_bitmask_lock);
 }
 
+struct msi_chip octeon_msi_chip = {
+	.setup_irq = octeon_setup_msi_irq,
+	.teardown_irq = octeon_teardown_msi_irq,
+	.check_device = octeon_check_msi_device,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return &octeon_msi_chip;
+}
+
 static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock);
 
 static u64 msi_rcv_reg[4];
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 16/20] arm/iop13xx/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip iop13xx_msi_chip instead of weak arch
functions to configure MSI/MSI-X. And associate the pci bus with msi_chip
in pcibios_add_bus().

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/arm/mach-iop13xx/include/mach/pci.h |    2 ++
 arch/arm/mach-iop13xx/iq81340mc.c        |    1 +
 arch/arm/mach-iop13xx/iq81340sc.c        |    1 +
 arch/arm/mach-iop13xx/msi.c              |   14 ++++++++++++--
 arch/arm/mach-iop13xx/pci.c              |    6 ++++++
 5 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-iop13xx/include/mach/pci.h b/arch/arm/mach-iop13xx/include/mach/pci.h
index 59f42b5..7a073cb 100644
--- a/arch/arm/mach-iop13xx/include/mach/pci.h
+++ b/arch/arm/mach-iop13xx/include/mach/pci.h
@@ -10,6 +10,8 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *);
 void iop13xx_atu_select(struct hw_pci *plat_pci);
 void iop13xx_pci_init(void);
 void iop13xx_map_pci_memory(void);
+void iop13xx_add_bus(struct pci_bus *bus);
+extern struct msi_chip iop13xx_msi_chip;
 
 #define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY |	     \
 			       PCI_STATUS_SIG_TARGET_ABORT | \
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index 9cd07d3..19d47cb 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -59,6 +59,7 @@ static struct hw_pci iq81340mc_pci __initdata = {
 	.map_irq	= iq81340mc_pcix_map_irq,
 	.scan		= iop13xx_scan_bus,
 	.preinit	= iop13xx_pci_init,
+	.add_bus	= iop13xx_add_bus;
 };
 
 static int __init iq81340mc_pci_init(void)
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index b3ec11c..4d56993 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -61,6 +61,7 @@ static struct hw_pci iq81340sc_pci __initdata = {
 	.scan		= iop13xx_scan_bus,
 	.map_irq	= iq81340sc_atux_map_irq,
 	.preinit	= iop13xx_pci_init
+	.add_bus	= iop13xx_add_bus;
 };
 
 static int __init iq81340sc_pci_init(void)
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
index e7730cf..59a9f8f 100644
--- a/arch/arm/mach-iop13xx/msi.c
+++ b/arch/arm/mach-iop13xx/msi.c
@@ -132,7 +132,7 @@ static struct irq_chip iop13xx_msi_chip = {
 	.irq_unmask = unmask_msi_irq,
 };
 
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+int iop13xx_setup_msi_irq(struct device *dev, struct msi_desc *desc)
 {
 	int id, irq = irq_alloc_desc_from(IRQ_IOP13XX_MSI_0, -1);
 	struct msi_msg msg;
@@ -159,7 +159,17 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 	return 0;
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+void iop13xx_teardown_msi_irq(unsigned int irq)
 {
 	irq_free_desc(irq);
 }
+
+struct msi_chip iop13xx_chip = {
+	.setup_irq = iop13xx_setup_msi_irq,
+	.teardown_irq = iop13xx_teardown_msi_irq,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return &iop13xx_chip;
+}
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index 9082b84..f498800 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -962,6 +962,12 @@ void __init iop13xx_atu_select(struct hw_pci *plat_pci)
 	}
 }
 
+void iop13xx_add_bus(struct pci_bus *bus)
+{
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		bus->msi = &iop13xx_msi_chip;
+}
+
 void __init iop13xx_pci_init(void)
 {
 	/* clear pre-existing south bridge errors */
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 17/20] IA64/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip ia64_msi_chip instead of weak arch
functions to configure MSI/MSI-X.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/ia64/kernel/msi_ia64.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index c430f91..6e527c4 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -112,15 +112,15 @@ static struct irq_chip ia64_msi_chip = {
 };
 
 
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+static int arch_ia64_setup_msi_irq(struct device *dev, struct msi_desc *desc)
 {
 	if (platform_setup_msi_irq)
-		return platform_setup_msi_irq(pdev, desc);
+		return platform_setup_msi_irq(to_pci_dev(dev), desc);
 
-	return ia64_setup_msi_irq(pdev, desc);
+	return ia64_setup_msi_irq(to_pci_dev(dev), desc);
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+static void arch_ia64_teardown_msi_irq(unsigned int irq)
 {
 	if (platform_teardown_msi_irq)
 		return platform_teardown_msi_irq(irq);
@@ -128,6 +128,16 @@ void arch_teardown_msi_irq(unsigned int irq)
 	return ia64_teardown_msi_irq(irq);
 }
 
+static struct msi_chip chip = {
+	.setup_irq = arch_ia64_setup_msi_irq,
+	.teardown_irq = arch_ia64_teardown_msi_irq,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return &chip;
+}
+
 #ifdef CONFIG_INTEL_IOMMU
 #ifdef CONFIG_SMP
 static int dmar_msi_set_affinity(struct irq_data *data,
-- 
1.7.1

^ permalink raw reply related

* [RFC PATCH 15/20] s390/MSI: Use msi_chip instead of arch func to configure MSI/MSI-X
From: Yijing Wang @ 2014-08-12  7:26 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-mips, linux-ia64, linux-pci, Xinwei Hu, Yijing Wang,
	H. Peter Anvin, sparclinux, linux-s390, Russell King,
	Joerg Roedel, x86, Sebastian Ott, xen-devel, arnab.basu,
	Arnd Bergmann, Konrad Rzeszutek Wilk, Marc Zyngier, Chris Metcalf,
	Thomas Gleixner, linux-arm-kernel, Tony Luck, linux-kernel, iommu,
	Wuyun, linuxppc-dev, David S. Miller
In-Reply-To: <1407828373-24322-1-git-send-email-wangyijing@huawei.com>

Introduce a new struct msi_chip zpci_msi_chip instead of weak arch
functions to configure MSI/MSI-X.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 arch/s390/pci/pci.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 9ddc51e..ee7b05c 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -398,8 +398,9 @@ static void zpci_irq_handler(struct airq_struct *airq)
 	}
 }
 
-int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+int zpci_setup_msi_irqs(struct device *dev, int nvec, int type)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct zpci_dev *zdev = get_zdev(pdev);
 	unsigned int hwirq, msi_vecs;
 	unsigned long aisb;
@@ -474,8 +475,9 @@ out:
 	return rc;
 }
 
-void arch_teardown_msi_irqs(struct pci_dev *pdev)
+void zpci_teardown_msi_irqs(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct zpci_dev *zdev = get_zdev(pdev);
 	struct msi_desc *msi;
 	int rc;
@@ -501,6 +503,16 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
 	airq_iv_free_bit(zpci_aisb_iv, zdev->aisb);
 }
 
+struct msi_chip zpci_msi_chip = {
+	.setup_irqs = zpci_setup_msi_irqs,
+	.teardown_irqs = zpci_teardown_msi_irqs,
+};
+
+struct msi_chip *arch_get_match_msi_chip(struct device *dev)
+{
+	return &zpci_msi_chip;
+}
+
 static void zpci_map_resources(struct zpci_dev *zdev)
 {
 	struct pci_dev *pdev = zdev->pdev;
-- 
1.7.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox