All of lore.kernel.org
 help / color / mirror / Atom feed
* [RESEND-PATCH] cxl: Avoid double free_irq() for psl,slice interrupts
@ 2017-06-02  9:35 Vaibhav Jain
  2017-06-02 15:30 ` Frederic Barrat
  0 siblings, 1 reply; 4+ messages in thread
From: Vaibhav Jain @ 2017-06-02  9:35 UTC (permalink / raw)
  To: Frederic Barrat, Philippe Bergheaud
  Cc: Vaibhav Jain, linuxppc-dev, Andrew Donnellan, Ian Munsie,
	Christophe Lombard, Greg Kurz, Alastair D'Silva, stable

During an eeh call to cxl_remove can result in double free_irq of
psl,slice interrupts. This can happen if perst_reloads_same_image == 1
and call to cxl_configure_adapter() fails during slot_reset
callback. In such a case we see a kernel oops with following back-trace:

Oops: Kernel access of bad area, sig: 11 [#1]
Call Trace:
  free_irq+0x88/0xd0 (unreliable)
  cxl_unmap_irq+0x20/0x40 [cxl]
  cxl_native_release_psl_irq+0x78/0xd8 [cxl]
  pci_deconfigure_afu+0xac/0x110 [cxl]
  cxl_remove+0x104/0x210 [cxl]
  pci_device_remove+0x6c/0x110
  device_release_driver_internal+0x204/0x2e0
  pci_stop_bus_device+0xa0/0xd0
  pci_stop_and_remove_bus_device+0x28/0x40
  pci_hp_remove_devices+0xb0/0x150
  pci_hp_remove_devices+0x68/0x150
  eeh_handle_normal_event+0x140/0x580
  eeh_handle_event+0x174/0x360
  eeh_event_handler+0x1e8/0x1f0

This patch fixes the issue of double free_irq by checking that
variables that hold the virqs (err_hwirq, serr_hwirq, psl_virq) are
not '0' before un-mapping and resetting these variables to '0' when
they are un-mapped.

Cc: stable@vger.kernel.org
Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>

---
Re-send:
- Added stable to recipients
---
 drivers/misc/cxl/native.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 871a2f0..3ed2254 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -1302,13 +1302,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter)
 
 void cxl_native_release_psl_err_irq(struct cxl *adapter)
 {
-	if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
+	if (adapter->native->err_virq == 0 ||
+	    adapter->native->err_virq !=
+	    irq_find_mapping(NULL, adapter->native->err_hwirq))
 		return;
 
 	cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
 	cxl_unmap_irq(adapter->native->err_virq, adapter);
 	cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
 	kfree(adapter->irq_name);
+	adapter->native->err_virq = 0;
 }
 
 int cxl_native_register_serr_irq(struct cxl_afu *afu)
@@ -1346,13 +1349,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
 
 void cxl_native_release_serr_irq(struct cxl_afu *afu)
 {
-	if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
+	if (afu->serr_virq == 0 ||
+	    afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
 		return;
 
 	cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
 	cxl_unmap_irq(afu->serr_virq, afu);
 	cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
 	kfree(afu->err_irq_name);
+	afu->serr_virq = 0;
 }
 
 int cxl_native_register_psl_irq(struct cxl_afu *afu)
@@ -1375,12 +1380,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu)
 
 void cxl_native_release_psl_irq(struct cxl_afu *afu)
 {
-	if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
+	if (afu->native->psl_virq == 0 ||
+	    afu->native->psl_virq !=
+	    irq_find_mapping(NULL, afu->native->psl_virq))
 		return;
 
 	cxl_unmap_irq(afu->native->psl_virq, afu);
 	cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
 	kfree(afu->psl_irq_name);
+	afu->native->psl_virq = 0;
 }
 
 static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RESEND-PATCH] cxl: Avoid double free_irq() for psl,slice interrupts
  2017-06-02  9:35 [RESEND-PATCH] cxl: Avoid double free_irq() for psl,slice interrupts Vaibhav Jain
@ 2017-06-02 15:30 ` Frederic Barrat
  2017-06-02 16:58     ` [RESEND-PATCH] cxl: Avoid double free_irq() for psl, slice interrupts Vaibhav Jain
  0 siblings, 1 reply; 4+ messages in thread
From: Frederic Barrat @ 2017-06-02 15:30 UTC (permalink / raw)
  To: Vaibhav Jain, Philippe Bergheaud
  Cc: linuxppc-dev, Andrew Donnellan, Ian Munsie, Christophe Lombard,
	Greg Kurz, Alastair D'Silva, stable



Le 02/06/2017 à 11:35, Vaibhav Jain a écrit :
> During an eeh call to cxl_remove can result in double free_irq of
> psl,slice interrupts. This can happen if perst_reloads_same_image == 1
> and call to cxl_configure_adapter() fails during slot_reset
> callback. In such a case we see a kernel oops with following back-trace:
> 
> Oops: Kernel access of bad area, sig: 11 [#1]
> Call Trace:
>    free_irq+0x88/0xd0 (unreliable)
>    cxl_unmap_irq+0x20/0x40 [cxl]
>    cxl_native_release_psl_irq+0x78/0xd8 [cxl]
>    pci_deconfigure_afu+0xac/0x110 [cxl]
>    cxl_remove+0x104/0x210 [cxl]
>    pci_device_remove+0x6c/0x110
>    device_release_driver_internal+0x204/0x2e0
>    pci_stop_bus_device+0xa0/0xd0
>    pci_stop_and_remove_bus_device+0x28/0x40
>    pci_hp_remove_devices+0xb0/0x150
>    pci_hp_remove_devices+0x68/0x150
>    eeh_handle_normal_event+0x140/0x580
>    eeh_handle_event+0x174/0x360
>    eeh_event_handler+0x1e8/0x1f0
> 
> This patch fixes the issue of double free_irq by checking that
> variables that hold the virqs (err_hwirq, serr_hwirq, psl_virq) are
> not '0' before un-mapping and resetting these variables to '0' when
> they are un-mapped.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
> Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
> 
> ---
> Re-send:
> - Added stable to recipients
> ---
>   drivers/misc/cxl/native.c | 14 +++++++++++---
>   1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
> index 871a2f0..3ed2254 100644
> --- a/drivers/misc/cxl/native.c
> +++ b/drivers/misc/cxl/native.c
> @@ -1302,13 +1302,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter)
> 
>   void cxl_native_release_psl_err_irq(struct cxl *adapter)
>   {
> -	if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
> +	if (adapter->native->err_virq == 0 ||
> +	    adapter->native->err_virq !=
> +	    irq_find_mapping(NULL, adapter->native->err_hwirq))
>   		return;
> 
>   	cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
>   	cxl_unmap_irq(adapter->native->err_virq, adapter);
>   	cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
>   	kfree(adapter->irq_name);
> +	adapter->native->err_virq = 0;
>   }
> 
>   int cxl_native_register_serr_irq(struct cxl_afu *afu)
> @@ -1346,13 +1349,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
> 
>   void cxl_native_release_serr_irq(struct cxl_afu *afu)
>   {
> -	if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
> +	if (afu->serr_virq == 0 ||
> +	    afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
>   		return;
> 
>   	cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
>   	cxl_unmap_irq(afu->serr_virq, afu);
>   	cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
>   	kfree(afu->err_irq_name);
> +	afu->serr_virq = 0;
>   }
> 
>   int cxl_native_register_psl_irq(struct cxl_afu *afu)
> @@ -1375,12 +1380,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu)
> 
>   void cxl_native_release_psl_irq(struct cxl_afu *afu)
>   {
> -	if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
> +	if (afu->native->psl_virq == 0 ||
> +	    afu->native->psl_virq !=
> +	    irq_find_mapping(NULL, afu->native->psl_virq))

                                                     ^^^
Shouldn't it be psl_hwirq?

   Fred

>   		return;
> 
>   	cxl_unmap_irq(afu->native->psl_virq, afu);
>   	cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
>   	kfree(afu->psl_irq_name);
> +	afu->native->psl_virq = 0;
>   }
> 
>   static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND-PATCH] cxl: Avoid double free_irq() for psl,slice interrupts
  2017-06-02 15:30 ` Frederic Barrat
@ 2017-06-02 16:58     ` Vaibhav Jain
  0 siblings, 0 replies; 4+ messages in thread
From: Vaibhav Jain @ 2017-06-02 16:58 UTC (permalink / raw)
  To: Frederic Barrat, Philippe Bergheaud
  Cc: linuxppc-dev, Andrew Donnellan, Ian Munsie, Christophe Lombard,
	Greg Kurz, Alastair D'Silva, stable

Frederic Barrat <fbarrat@linux.vnet.ibm.com> writes:


>> +	    irq_find_mapping(NULL, afu->native->psl_virq))
>
>                                                      ^^^
> Shouldn't it be psl_hwirq?
>
Thanks for catching this Fred. I have sent a v2 patch fixing this.

-- 
Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Linux Technology Center, IBM India Pvt. Ltd.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND-PATCH] cxl: Avoid double free_irq() for psl, slice interrupts
@ 2017-06-02 16:58     ` Vaibhav Jain
  0 siblings, 0 replies; 4+ messages in thread
From: Vaibhav Jain @ 2017-06-02 16:58 UTC (permalink / raw)
  To: Frederic Barrat, Philippe Bergheaud
  Cc: linuxppc-dev, Andrew Donnellan, Ian Munsie, Christophe Lombard,
	Greg Kurz, Alastair D'Silva, stable

Frederic Barrat <fbarrat@linux.vnet.ibm.com> writes:


>> +	    irq_find_mapping(NULL, afu->native->psl_virq))
>
>                                                      ^^^
> Shouldn't it be psl_hwirq?
>
Thanks for catching this Fred. I have sent a v2 patch fixing this.

-- 
Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Linux Technology Center, IBM India Pvt. Ltd.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-06-02 16:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-02  9:35 [RESEND-PATCH] cxl: Avoid double free_irq() for psl,slice interrupts Vaibhav Jain
2017-06-02 15:30 ` Frederic Barrat
2017-06-02 16:58   ` Vaibhav Jain
2017-06-02 16:58     ` [RESEND-PATCH] cxl: Avoid double free_irq() for psl, slice interrupts Vaibhav Jain

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.