isdn: mISDNinfineon: check/cleanup ioremap failure correctly in setup_io
authorPhillip Potter <phil@philpotter.co.uk>
Mon, 3 May 2021 11:57:08 +0000 (13:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Jun 2021 06:36:21 +0000 (08:36 +0200)
[ Upstream commit c446f0d4702d316e1c6bf621f70e79678d28830a ]

Move hw->cfg.mode and hw->addr.mode assignments from hw->ci->cfg_mode
and hw->ci->addr_mode respectively, to be before the subsequent checks
for memory IO mode (and possible ioremap calls in this case).

Also introduce ioremap error checks at both locations. This allows
resources to be properly freed on ioremap failure, as when the caller
of setup_io then subsequently calls release_io via its error path,
release_io can now correctly determine the mode as it has been set
before the ioremap call.

Finally, refactor release_io function so that it will call
release_mem_region in the memory IO case, regardless of whether or not
hw->cfg.p/hw->addr.p are NULL. This means resources are then properly
released on failure.

This properly implements the original reverted commit (d721fe99f6ad)
from the University of Minnesota, whilst also implementing the ioremap
check for the hw->ci->cfg_mode if block as well.

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
Link: https://lore.kernel.org/r/20210503115736.2104747-42-gregkh@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/isdn/hardware/mISDN/mISDNinfineon.c

index d5bdbaf93a1afe2d905a21ecad5cca09d637a731..d0b6377b98345101d404805a3fa292ed5b753a56 100644 (file)
@@ -645,17 +645,19 @@ static void
 release_io(struct inf_hw *hw)
 {
        if (hw->cfg.mode) {
-               if (hw->cfg.p) {
+               if (hw->cfg.mode == AM_MEMIO) {
                        release_mem_region(hw->cfg.start, hw->cfg.size);
-                       iounmap(hw->cfg.p);
+                       if (hw->cfg.p)
+                               iounmap(hw->cfg.p);
                } else
                        release_region(hw->cfg.start, hw->cfg.size);
                hw->cfg.mode = AM_NONE;
        }
        if (hw->addr.mode) {
-               if (hw->addr.p) {
+               if (hw->addr.mode == AM_MEMIO) {
                        release_mem_region(hw->addr.start, hw->addr.size);
-                       iounmap(hw->addr.p);
+                       if (hw->addr.p)
+                               iounmap(hw->addr.p);
                } else
                        release_region(hw->addr.start, hw->addr.size);
                hw->addr.mode = AM_NONE;
@@ -685,9 +687,12 @@ setup_io(struct inf_hw *hw)
                                (ulong)hw->cfg.start, (ulong)hw->cfg.size);
                        return err;
                }
-               if (hw->ci->cfg_mode == AM_MEMIO)
-                       hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
                hw->cfg.mode = hw->ci->cfg_mode;
+               if (hw->ci->cfg_mode == AM_MEMIO) {
+                       hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
+                       if (!hw->cfg.p)
+                               return -ENOMEM;
+               }
                if (debug & DEBUG_HW)
                        pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
                                  hw->name, (ulong)hw->cfg.start,
@@ -712,9 +717,12 @@ setup_io(struct inf_hw *hw)
                                (ulong)hw->addr.start, (ulong)hw->addr.size);
                        return err;
                }
-               if (hw->ci->addr_mode == AM_MEMIO)
-                       hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
                hw->addr.mode = hw->ci->addr_mode;
+               if (hw->ci->addr_mode == AM_MEMIO) {
+                       hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
+                       if (!hw->addr.p)
+                               return -ENOMEM;
+               }
                if (debug & DEBUG_HW)
                        pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
                                  hw->name, (ulong)hw->addr.start,