From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751875AbdJCL7Q (ORCPT ); Tue, 3 Oct 2017 07:59:16 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:10504 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751421AbdJCL7M (ORCPT ); Tue, 3 Oct 2017 07:59:12 -0400 X-AuditID: b6c32a48-c27ff70000001005-26-59d37b8e2a81 From: Bartlomiej Zolnierkiewicz To: "David S. Miller" Cc: Guenter Roeck , Lorenzo Pieralisi , Bjorn Helgaas , Richard Henderson , Ivan Kokshaysky , Matt Turner , linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] ide: pci: free PCI BARs on initialization failure Date: Tue, 03 Oct 2017 13:59:07 +0200 Message-id: <3105781.uZB2mYxEDh@amdc3058> User-Agent: KMail/4.13.3 (Linux/3.13.0-96-generic; KDE/4.13.3; x86_64; ; ) MIME-version: 1.0 Content-transfer-encoding: 7Bit Content-type: text/plain; charset="us-ascii" X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpmleLIzCtJLcpLzFFi42LZdljTVLev+nKkwb6jrBZLmjIs5pxvYbH4 d2ojs8WxHY+YLC7vmsNm8WThGSaLN79fsFt8un2Q2WLaqTusDpwea+atYfTYsvImk8fOWXfZ PRZsKvX4fzbKY+f3BnaPvukfmD0+b5IL4IjisklJzcksSy3St0vgyvjfl1cwS6fiw7XlTA2M 35S6GDk5JARMJFZMnMPexcjFISSwg1HiU+tvJgjnO6PEvWf7gDIcYFW90wUg4hsYJZYtXsYC 4XxllLi1Yys7yCg2ASuJie2rGEFsEQFtiXUHelhBipgF1jFJHNj/mxFkkrCAk8TVv+YgNSwC qhKtk5czgdi8ApoSTa/2gNmiAl4SW/a1Q8UFJX5MvscCYjMLyEvs2z+VFcLWkTh7bB0jyHwJ gSNsEkdmT2WD+MdFoqnnMiOELSzx6vgWdghbWuLZqo1Q8emMEtt/S0A0b2aUWLV7AlSRtcTh 4xehNvBJdBz+C/U+r0RHmxBEiYfEiwc9bBBhR4mu9/UgYSGBWIlzSx8yT2CUmYXk7FlIzp6F 5OwFjMyrGMVSC4pz01OLjQpM9IoTc4tL89L1kvNzNzGCk4aWxw7GA+d8DjEKcDAq8fAmuF2K FGJNLCuuzD3EKMHBrCTCa1J5OVKINyWxsiq1KD++qDQntfgQozQHi5I4b922axFCAumJJanZ qakFqUUwWSYOTqkGxrYcD/58rt9+xhNbH6YfFM+Tlbn03WFW+zpX2/0Zqw54ynPz32PaNe/v /pSEZ51nT83Zq3yt5rDrIwsXd5EzFqmqB1wUrm/uXS1veCqtV25W1of7jgc2bLqVuEsydeXe DZxvuvgsv0kmHP96X63l3vIz3g7sP1m+X1O4HHm73c4qTFLn4e1gTSWW4oxEQy3mouJEADTV jRYWAwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrPLMWRmVeSWpSXmKPExsVy+t9jQd3e6suRBv171SyWNGVYzDnfwmLx 79RGZotjOx4xWVzeNYfN4snCM0wWb36/YLf4dPsgs8W0U3dYHTg91sxbw+ixZeVNJo+ds+6y eyzYVOrx/2yUx87vDewefdM/MHt83iQXwBHFZZOSmpNZllqkb5fAlfG/L69glk7Fh2vLmRoY vyl1MXJwSAiYSPROF+hi5OIQEljHKLH/613WLkZOIOcro8SkzlAQm03ASmJi+ypGEFtEQFti 3YEeVpAGZoF1TBLbp7WzggwSFnCSuPrXHKSGRUBVonXyciYQm1dAU6Lp1R4wW1TAS2LLvnao uKDEj8n3WEBsZgF5iX37p7JC2FoS63ceZ5rAyDsLSdksJGWzkJQtYGRexSiZWlCcm55bbFRg lJdarlecmFtcmpeul5yfu4kRGMzbDmv172B8vCT+EKMAB6MSD+8Oj0uRQqyJZcWVuYcYJTiY lUR4X1VdjhTiTUmsrEotyo8vKs1JLT7EKM3BoiTOy59/LFJIID2xJDU7NbUgtQgmy8TBKdXA uHfynZ137XQlTZ5VsH9fzRT1eN1tMbXQtOamk4vYv+qumX3a5ULhu7T3+6/Pi5MrabuvKx7o IsKnybWriqm96rZpykOZ+7O+TOop+bK7pDzrhoedTMXuuGefucNKVvwJvJfW+7Ttvol59+fk Ds7HM17qP7zqZSko0tuk9dl724HtesfjT/p8U2Ipzkg01GIuKk4EADz6YttiAgAA X-CMS-MailID: 20171003115909epcas2p21c25b1c67678df6fd6c26386345abf9a X-Msg-Generator: CA X-Sender-IP: 182.195.42.143 X-Local-Sender: =?UTF-8?B?QmFydGxvbWllaiBab2xuaWVya2lld2ljehtTUlBPTC1LZXJu?= =?UTF-8?B?ZWwgKFRQKRvsgrzshLHsoITsnpAbU2VuaW9yIFNvZnR3YXJlIEVuZ2luZWVy?= X-Global-Sender: =?UTF-8?B?QmFydGxvbWllaiBab2xuaWVya2lld2ljehtTUlBPTC1LZXJu?= =?UTF-8?B?ZWwgKFRQKRtTYW1zdW5nIEVsZWN0cm9uaWNzG1NlbmlvciBTb2Z0d2FyZSBF?= =?UTF-8?B?bmdpbmVlcg==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTI=?= CMS-TYPE: 102P X-CMS-RootMailID: 20171003115909epcas2p21c25b1c67678df6fd6c26386345abf9a X-RootMTR: 20171003115909epcas2p21c25b1c67678df6fd6c26386345abf9a References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Recent pci_assign_irq() changes uncovered a problem with missing freeing of PCI BARs on PCI IDE host initialization failure: ide0: disabled, no IRQ ide0: failed to initialize IDE interface ide0: disabling port cmd64x 0000:00:02.0: IDE controller (0x1095:0x0646 rev 0x07) CMD64x_IDE 0000:00:02.0: BAR 0: can't reserve [io 0x8050-0x8057] cmd64x 0000:00:02.0: can't reserve resources CMD64x_IDE: probe of 0000:00:02.0 failed with error -16 Fix the problem by adding missing freeing of PCI BARs to ide_setup_pci_controller() and ide_pci_init_two(). Link: http://lkml.kernel.org/r/32ec730f-c1b0-5584-cd35-f8a809122b96@roeck-us.net Reported-by: Guenter Roeck Cc: Bjorn Helgaas Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Guenter Roeck Cc: Matt Turner Signed-off-by: Bartlomiej Zolnierkiewicz --- This should fix problem with reserving PCI resources on a secondary PCI device probe attempt (please test when pci_assign_irq() fix is not present and "[PATCH] ide: add missing hwif->portdev freeing on hwif_init() failure" is applied). drivers/ide/setup-pci.c | 61 +++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 23 deletions(-) Index: b/drivers/ide/setup-pci.c =================================================================== --- a/drivers/ide/setup-pci.c 2017-10-03 13:43:29.567778114 +0200 +++ b/drivers/ide/setup-pci.c 2017-10-03 13:43:54.131778138 +0200 @@ -179,6 +179,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); /** * ide_pci_enable - do PCI enables * @dev: PCI device + * @bars: PCI BARs mask * @d: IDE port info * * Enable the IDE PCI device. We attempt to enable the device in full @@ -189,9 +190,10 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); * Returns zero on success or an error code */ -static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) +static int ide_pci_enable(struct pci_dev *dev, int bars, + const struct ide_port_info *d) { - int ret, bars; + int ret; if (pci_enable_device(dev)) { ret = pci_enable_device_io(dev); @@ -216,18 +218,6 @@ static int ide_pci_enable(struct pci_dev goto out; } - if (d->host_flags & IDE_HFLAG_SINGLE) - bars = (1 << 2) - 1; - else - bars = (1 << 4) - 1; - - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { - if (d->host_flags & IDE_HFLAG_CS5520) - bars |= (1 << 2); - else - bars |= (1 << 4); - } - ret = pci_request_selected_regions(dev, bars, d->name); if (ret < 0) printk(KERN_ERR "%s %s: can't reserve resources\n", @@ -403,6 +393,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, /** * ide_setup_pci_controller - set up IDE PCI * @dev: PCI device + * @bars: PCI BARs mask * @d: IDE port info * @noisy: verbose flag * @@ -411,7 +402,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, * and enables it if need be */ -static int ide_setup_pci_controller(struct pci_dev *dev, +static int ide_setup_pci_controller(struct pci_dev *dev, int bars, const struct ide_port_info *d, int noisy) { int ret; @@ -420,7 +411,7 @@ static int ide_setup_pci_controller(stru if (noisy) ide_setup_pci_noise(dev, d); - ret = ide_pci_enable(dev, d); + ret = ide_pci_enable(dev, bars, d); if (ret < 0) goto out; @@ -428,16 +419,18 @@ static int ide_setup_pci_controller(stru if (ret < 0) { printk(KERN_ERR "%s %s: error accessing PCI regs\n", d->name, pci_name(dev)); - goto out; + goto out_free_bars; } if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ ret = ide_pci_configure(dev, d); if (ret < 0) - goto out; + goto out_free_bars; printk(KERN_INFO "%s %s: device enabled (Linux)\n", d->name, pci_name(dev)); } +out_free_bars: + pci_release_selected_regions(dev, bars); out: return ret; } @@ -540,13 +533,28 @@ int ide_pci_init_two(struct pci_dev *dev { struct pci_dev *pdev[] = { dev1, dev2 }; struct ide_host *host; - int ret, i, n_ports = dev2 ? 4 : 2; + int ret, i, n_ports = dev2 ? 4 : 2, bars; struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; + if (d->host_flags & IDE_HFLAG_SINGLE) + bars = (1 << 2) - 1; + else + bars = (1 << 4) - 1; + + if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { + if (d->host_flags & IDE_HFLAG_CS5520) + bars |= (1 << 2); + else + bars |= (1 << 4); + } + for (i = 0; i < n_ports / 2; i++) { - ret = ide_setup_pci_controller(pdev[i], d, !i); - if (ret < 0) + ret = ide_setup_pci_controller(pdev[i], bars, d, !i); + if (ret < 0) { + if (i == 1) + pci_release_selected_regions(pdev[0], bars); goto out; + } ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); } @@ -554,7 +562,7 @@ int ide_pci_init_two(struct pci_dev *dev host = ide_host_alloc(d, hws, n_ports); if (host == NULL) { ret = -ENOMEM; - goto out; + goto out_free_bars; } host->dev[0] = &dev1->dev; @@ -576,7 +584,7 @@ int ide_pci_init_two(struct pci_dev *dev * do_ide_setup_pci_device() on the first device! */ if (ret < 0) - goto out; + goto out_free_bars; /* fixup IRQ */ if (ide_pci_is_in_compatibility_mode(pdev[i])) { @@ -589,6 +597,13 @@ int ide_pci_init_two(struct pci_dev *dev ret = ide_host_register(host, d, hws); if (ret) ide_host_free(host); + else + goto out; + +out_free_bars: + i = n_ports / 2; + while (i--) + pci_release_selected_regions(pdev[i], bars); out: return ret; }