Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80cf1f8c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull PCI fixes from Bjorn Helgaas:
 "Fix legacy IDE probe issues exposed by recent PCI core IRQ mapping
  changes (Bartlomiej Zolnierkiewicz, Lorenzo Pieralisi)"

* tag 'pci-v4.14-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  ide: fix IRQ assignment for PCI bus order probing
  ide: pci: free PCI BARs on initialization failure
  ide: free hwif->portdev on hwif_init() failure
parents 27549068 b1f9e5e3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1451,6 +1451,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
		if (hwif_init(hwif) == 0) {
			printk(KERN_INFO "%s: failed to initialize IDE "
					 "interface\n", hwif->name);
			device_unregister(hwif->portdev);
			device_unregister(&hwif->gendev);
			ide_disable_port(hwif);
			continue;
+9 −4
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ static int __init ide_scan_pcidev(struct pci_dev *dev)
{
	struct list_head *l;
	struct pci_driver *d;
	int ret;

	list_for_each(l, &ide_pci_drivers) {
		d = list_entry(l, struct pci_driver, node);
@@ -63,13 +64,17 @@ static int __init ide_scan_pcidev(struct pci_dev *dev)
			const struct pci_device_id *id =
				pci_match_id(d->id_table, dev);

			if (id != NULL && d->probe(dev, id) >= 0) {
			if (id != NULL) {
				pci_assign_irq(dev);
				ret = d->probe(dev, id);
				if (ret >= 0) {
					dev->driver = d;
					pci_dev_get(dev);
					return 1;
				}
			}
		}
	}
	return 0;
}

+40 −23
Original line number Diff line number Diff line
@@ -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 *dev, const struct ide_port_info *d)
		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, const struct ide_port_info *d)
/**
 *	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, const struct ide_port_info *d)
 *	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(struct pci_dev *dev,
	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,20 @@ static int ide_setup_pci_controller(struct pci_dev *dev,
	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));
	}

	goto out;

out_free_bars:
	pci_release_selected_regions(dev, bars);
out:
	return ret;
}
@@ -540,13 +535,28 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
{
	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 +564,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
	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 +586,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
		 * 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 +599,13 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
	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;
}