From: Dave Marquardt <[email protected]>

If request_irq() fails during ibmvfc_register_channel(), the error path
disposes of the IRQ mapping via irq_dispose_mapping() but leaves scrq->irq
populated with the stale virq number. A subsequent call to
ibmvfc_deregister_channel() during teardown or reset cleanup then
unconditionally invokes free_irq() and irq_dispose_mapping() on the stale
IRQ descriptor, triggering kernel warnings.

Fix this by:
1. Explicitly setting scrq->irq to 0 after irq_dispose_mapping() in the
   ibmvfc_register_channel() error path.
2. Guarding free_irq() and irq_dispose_mapping() with a check for scrq->irq
   in ibmvfc_deregister_channel() so unmapped or unregistered queues are
   safely skipped.

Signed-off-by: Dave Marquardt <[email protected]>
---
 drivers/scsi/ibmvscsi/ibmvfc-core.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c 
b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index 1c660edcf608..f88262ffad13 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -6888,6 +6888,7 @@ static int ibmvfc_register_channel(struct ibmvfc_host 
*vhost,
                else
                        dev_err(dev, "Couldn't register async sub-crq irq\n");
                irq_dispose_mapping(scrq->irq);
+               scrq->irq = 0;
                goto irq_failed;
        }
 
@@ -6930,9 +6931,11 @@ static void ibmvfc_deregister_channel(struct ibmvfc_host 
*vhost,
 
        ENTER;
 
-       free_irq(scrq->irq, scrq);
-       irq_dispose_mapping(scrq->irq);
-       scrq->irq = 0;
+       if (scrq->irq) {
+               free_irq(scrq->irq, scrq);
+               irq_dispose_mapping(scrq->irq);
+               scrq->irq = 0;
+       }
 
        do {
                rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address,

-- 
2.55.0



Reply via email to