kvaser_pci_init_one() maps the PCI I/O regions with pci_iomap(), while kvaser_pci_del_chan() also unmaps the same mappings as part of channel cleanup. If kvaser_pci_add_chan() fails after the master device has been initialized, the probe error path calls kvaser_pci_del_chan(), which unmaps the PCI I/O regions, and then falls through to failure_iounmap, where the same mappings are unmapped again. Move the PCI I/O unmapping out of kvaser_pci_del_chan(). Let the probe error path release the mappings through failure_iounmap and explicitly release them in kvaser_pci_remove_one() after channel cleanup. This ensures that each PCI I/O mapping is released exactly once. This issue was found by manual code inspection. Fixes: 3878fb6fdbce ("The patch adds support for the PCI cards: PCIcan and PCIcanx (1, 2 or 4 channel) from Kvaser (http://www.kvaser.com).") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li --- drivers/net/can/sja1000/kvaser_pci.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c index 95fe9ee1ce32..b21ca65d2daa 100644 --- a/drivers/net/can/sja1000/kvaser_pci.c +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -186,10 +186,6 @@ static void kvaser_pci_del_chan(struct net_device *dev) } unregister_sja1000dev(dev); - pci_iounmap(board->pci_dev, priv->reg_base); - pci_iounmap(board->pci_dev, board->conf_addr); - pci_iounmap(board->pci_dev, board->res_addr); - free_sja1000dev(dev); } @@ -367,9 +363,18 @@ static int kvaser_pci_init_one(struct pci_dev *pdev, static void kvaser_pci_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + struct sja1000_priv *priv = netdev_priv(dev); + struct kvaser_pci *board = priv->priv; + void __iomem *base_addr = priv->reg_base; + void __iomem *conf_addr = board->conf_addr; + void __iomem *res_addr = board->res_addr; kvaser_pci_del_chan(dev); + pci_iounmap(pdev, conf_addr); + pci_iounmap(pdev, res_addr); + pci_iounmap(pdev, base_addr); + pci_release_regions(pdev); pci_disable_device(pdev); } -- 2.43.0