diff options
Diffstat (limited to 'drivers/ide/setup-pci.c')
-rw-r--r-- | drivers/ide/setup-pci.c | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 112d2fe1bcdb..fdc8e813170c 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
@@ -179,6 +179,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); | |||
179 | /** | 179 | /** |
180 | * ide_pci_enable - do PCI enables | 180 | * ide_pci_enable - do PCI enables |
181 | * @dev: PCI device | 181 | * @dev: PCI device |
182 | * @bars: PCI BARs mask | ||
182 | * @d: IDE port info | 183 | * @d: IDE port info |
183 | * | 184 | * |
184 | * Enable the IDE PCI device. We attempt to enable the device in full | 185 | * Enable the IDE PCI device. We attempt to enable the device in full |
@@ -189,9 +190,10 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); | |||
189 | * Returns zero on success or an error code | 190 | * Returns zero on success or an error code |
190 | */ | 191 | */ |
191 | 192 | ||
192 | static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) | 193 | static int ide_pci_enable(struct pci_dev *dev, int bars, |
194 | const struct ide_port_info *d) | ||
193 | { | 195 | { |
194 | int ret, bars; | 196 | int ret; |
195 | 197 | ||
196 | if (pci_enable_device(dev)) { | 198 | if (pci_enable_device(dev)) { |
197 | ret = pci_enable_device_io(dev); | 199 | 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) | |||
216 | goto out; | 218 | goto out; |
217 | } | 219 | } |
218 | 220 | ||
219 | if (d->host_flags & IDE_HFLAG_SINGLE) | ||
220 | bars = (1 << 2) - 1; | ||
221 | else | ||
222 | bars = (1 << 4) - 1; | ||
223 | |||
224 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { | ||
225 | if (d->host_flags & IDE_HFLAG_CS5520) | ||
226 | bars |= (1 << 2); | ||
227 | else | ||
228 | bars |= (1 << 4); | ||
229 | } | ||
230 | |||
231 | ret = pci_request_selected_regions(dev, bars, d->name); | 221 | ret = pci_request_selected_regions(dev, bars, d->name); |
232 | if (ret < 0) | 222 | if (ret < 0) |
233 | printk(KERN_ERR "%s %s: can't reserve resources\n", | 223 | 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) | |||
403 | /** | 393 | /** |
404 | * ide_setup_pci_controller - set up IDE PCI | 394 | * ide_setup_pci_controller - set up IDE PCI |
405 | * @dev: PCI device | 395 | * @dev: PCI device |
396 | * @bars: PCI BARs mask | ||
406 | * @d: IDE port info | 397 | * @d: IDE port info |
407 | * @noisy: verbose flag | 398 | * @noisy: verbose flag |
408 | * | 399 | * |
@@ -411,7 +402,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
411 | * and enables it if need be | 402 | * and enables it if need be |
412 | */ | 403 | */ |
413 | 404 | ||
414 | static int ide_setup_pci_controller(struct pci_dev *dev, | 405 | static int ide_setup_pci_controller(struct pci_dev *dev, int bars, |
415 | const struct ide_port_info *d, int noisy) | 406 | const struct ide_port_info *d, int noisy) |
416 | { | 407 | { |
417 | int ret; | 408 | int ret; |
@@ -420,7 +411,7 @@ static int ide_setup_pci_controller(struct pci_dev *dev, | |||
420 | if (noisy) | 411 | if (noisy) |
421 | ide_setup_pci_noise(dev, d); | 412 | ide_setup_pci_noise(dev, d); |
422 | 413 | ||
423 | ret = ide_pci_enable(dev, d); | 414 | ret = ide_pci_enable(dev, bars, d); |
424 | if (ret < 0) | 415 | if (ret < 0) |
425 | goto out; | 416 | goto out; |
426 | 417 | ||
@@ -428,16 +419,20 @@ static int ide_setup_pci_controller(struct pci_dev *dev, | |||
428 | if (ret < 0) { | 419 | if (ret < 0) { |
429 | printk(KERN_ERR "%s %s: error accessing PCI regs\n", | 420 | printk(KERN_ERR "%s %s: error accessing PCI regs\n", |
430 | d->name, pci_name(dev)); | 421 | d->name, pci_name(dev)); |
431 | goto out; | 422 | goto out_free_bars; |
432 | } | 423 | } |
433 | if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ | 424 | if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ |
434 | ret = ide_pci_configure(dev, d); | 425 | ret = ide_pci_configure(dev, d); |
435 | if (ret < 0) | 426 | if (ret < 0) |
436 | goto out; | 427 | goto out_free_bars; |
437 | printk(KERN_INFO "%s %s: device enabled (Linux)\n", | 428 | printk(KERN_INFO "%s %s: device enabled (Linux)\n", |
438 | d->name, pci_name(dev)); | 429 | d->name, pci_name(dev)); |
439 | } | 430 | } |
440 | 431 | ||
432 | goto out; | ||
433 | |||
434 | out_free_bars: | ||
435 | pci_release_selected_regions(dev, bars); | ||
441 | out: | 436 | out: |
442 | return ret; | 437 | return ret; |
443 | } | 438 | } |
@@ -540,13 +535,28 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, | |||
540 | { | 535 | { |
541 | struct pci_dev *pdev[] = { dev1, dev2 }; | 536 | struct pci_dev *pdev[] = { dev1, dev2 }; |
542 | struct ide_host *host; | 537 | struct ide_host *host; |
543 | int ret, i, n_ports = dev2 ? 4 : 2; | 538 | int ret, i, n_ports = dev2 ? 4 : 2, bars; |
544 | struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; | 539 | struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; |
545 | 540 | ||
541 | if (d->host_flags & IDE_HFLAG_SINGLE) | ||
542 | bars = (1 << 2) - 1; | ||
543 | else | ||
544 | bars = (1 << 4) - 1; | ||
545 | |||
546 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { | ||
547 | if (d->host_flags & IDE_HFLAG_CS5520) | ||
548 | bars |= (1 << 2); | ||
549 | else | ||
550 | bars |= (1 << 4); | ||
551 | } | ||
552 | |||
546 | for (i = 0; i < n_ports / 2; i++) { | 553 | for (i = 0; i < n_ports / 2; i++) { |
547 | ret = ide_setup_pci_controller(pdev[i], d, !i); | 554 | ret = ide_setup_pci_controller(pdev[i], bars, d, !i); |
548 | if (ret < 0) | 555 | if (ret < 0) { |
556 | if (i == 1) | ||
557 | pci_release_selected_regions(pdev[0], bars); | ||
549 | goto out; | 558 | goto out; |
559 | } | ||
550 | 560 | ||
551 | ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); | 561 | ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); |
552 | } | 562 | } |
@@ -554,7 +564,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, | |||
554 | host = ide_host_alloc(d, hws, n_ports); | 564 | host = ide_host_alloc(d, hws, n_ports); |
555 | if (host == NULL) { | 565 | if (host == NULL) { |
556 | ret = -ENOMEM; | 566 | ret = -ENOMEM; |
557 | goto out; | 567 | goto out_free_bars; |
558 | } | 568 | } |
559 | 569 | ||
560 | host->dev[0] = &dev1->dev; | 570 | host->dev[0] = &dev1->dev; |
@@ -576,7 +586,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, | |||
576 | * do_ide_setup_pci_device() on the first device! | 586 | * do_ide_setup_pci_device() on the first device! |
577 | */ | 587 | */ |
578 | if (ret < 0) | 588 | if (ret < 0) |
579 | goto out; | 589 | goto out_free_bars; |
580 | 590 | ||
581 | /* fixup IRQ */ | 591 | /* fixup IRQ */ |
582 | if (ide_pci_is_in_compatibility_mode(pdev[i])) { | 592 | 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, | |||
589 | ret = ide_host_register(host, d, hws); | 599 | ret = ide_host_register(host, d, hws); |
590 | if (ret) | 600 | if (ret) |
591 | ide_host_free(host); | 601 | ide_host_free(host); |
602 | else | ||
603 | goto out; | ||
604 | |||
605 | out_free_bars: | ||
606 | i = n_ports / 2; | ||
607 | while (i--) | ||
608 | pci_release_selected_regions(pdev[i], bars); | ||
592 | out: | 609 | out: |
593 | return ret; | 610 | return ret; |
594 | } | 611 | } |