aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c59
1 files changed, 36 insertions, 23 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 4e6c2e8ac0f6..3634279d896d 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5223,8 +5223,9 @@ void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
5223 ap->host_set = host_set; 5223 ap->host_set = host_set;
5224 ap->dev = ent->dev; 5224 ap->dev = ent->dev;
5225 ap->port_no = port_no; 5225 ap->port_no = port_no;
5226 ap->hard_port_no = 5226 ap->hard_port_no = port_no;
5227 ent->legacy_mode ? ent->hard_port_no : port_no; 5227 if (ent->legacy_mode)
5228 ap->hard_port_no += ent->hard_port_no;
5228 ap->pio_mask = ent->pio_mask; 5229 ap->pio_mask = ent->pio_mask;
5229 ap->mwdma_mask = ent->mwdma_mask; 5230 ap->mwdma_mask = ent->mwdma_mask;
5230 ap->udma_mask = ent->udma_mask; 5231 ap->udma_mask = ent->udma_mask;
@@ -5400,6 +5401,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
5400 ata_host_set_init(host_set, dev, ent->host_set_flags, ent->port_ops); 5401 ata_host_set_init(host_set, dev, ent->host_set_flags, ent->port_ops);
5401 host_set->n_ports = ent->n_ports; 5402 host_set->n_ports = ent->n_ports;
5402 host_set->irq = ent->irq; 5403 host_set->irq = ent->irq;
5404 host_set->irq2 = ent->irq2;
5403 host_set->mmio_base = ent->mmio_base; 5405 host_set->mmio_base = ent->mmio_base;
5404 host_set->private_data = ent->private_data; 5406 host_set->private_data = ent->private_data;
5405 5407
@@ -5407,11 +5409,16 @@ int ata_device_add(const struct ata_probe_ent *ent)
5407 for (i = 0; i < host_set->n_ports; i++) { 5409 for (i = 0; i < host_set->n_ports; i++) {
5408 struct ata_port *ap; 5410 struct ata_port *ap;
5409 unsigned long xfer_mode_mask; 5411 unsigned long xfer_mode_mask;
5412 int irq_line = ent->irq;
5410 5413
5411 ap = ata_port_add(ent, host_set, i); 5414 ap = ata_port_add(ent, host_set, i);
5412 if (!ap) 5415 if (!ap)
5413 goto err_out; 5416 goto err_out;
5414 5417
5418 /* Report the secondary IRQ for second channel legacy */
5419 if (i == 1 && ent->irq2)
5420 irq_line = ent->irq2;
5421
5415 host_set->ports[i] = ap; 5422 host_set->ports[i] = ap;
5416 xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | 5423 xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
5417 (ap->mwdma_mask << ATA_SHIFT_MWDMA) | 5424 (ap->mwdma_mask << ATA_SHIFT_MWDMA) |
@@ -5419,20 +5426,20 @@ int ata_device_add(const struct ata_probe_ent *ent)
5419 5426
5420 /* print per-port info to dmesg */ 5427 /* print per-port info to dmesg */
5421 ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX " 5428 ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
5422 "ctl 0x%lX bmdma 0x%lX irq %lu\n", 5429 "ctl 0x%lX bmdma 0x%lX irq %d\n",
5423 ap->flags & ATA_FLAG_SATA ? 'S' : 'P', 5430 ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
5424 ata_mode_string(xfer_mode_mask), 5431 ata_mode_string(xfer_mode_mask),
5425 ap->ioaddr.cmd_addr, 5432 ap->ioaddr.cmd_addr,
5426 ap->ioaddr.ctl_addr, 5433 ap->ioaddr.ctl_addr,
5427 ap->ioaddr.bmdma_addr, 5434 ap->ioaddr.bmdma_addr,
5428 ent->irq); 5435 irq_line);
5429 5436
5430 ata_chk_status(ap); 5437 ata_chk_status(ap);
5431 host_set->ops->irq_clear(ap); 5438 host_set->ops->irq_clear(ap);
5432 ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */ 5439 ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
5433 } 5440 }
5434 5441
5435 /* obtain irq, that is shared between channels */ 5442 /* obtain irq, that may be shared between channels */
5436 rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, 5443 rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
5437 DRV_NAME, host_set); 5444 DRV_NAME, host_set);
5438 if (rc) { 5445 if (rc) {
@@ -5441,6 +5448,21 @@ int ata_device_add(const struct ata_probe_ent *ent)
5441 goto err_out; 5448 goto err_out;
5442 } 5449 }
5443 5450
5451 /* do we have a second IRQ for the other channel, eg legacy mode */
5452 if (ent->irq2) {
5453 /* We will get weird core code crashes later if this is true
5454 so trap it now */
5455 BUG_ON(ent->irq == ent->irq2);
5456
5457 rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
5458 DRV_NAME, host_set);
5459 if (rc) {
5460 dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
5461 ent->irq2, rc);
5462 goto err_out_free_irq;
5463 }
5464 }
5465
5444 /* perform each probe synchronously */ 5466 /* perform each probe synchronously */
5445 DPRINTK("probe begin\n"); 5467 DPRINTK("probe begin\n");
5446 for (i = 0; i < host_set->n_ports; i++) { 5468 for (i = 0; i < host_set->n_ports; i++) {
@@ -5514,6 +5536,8 @@ int ata_device_add(const struct ata_probe_ent *ent)
5514 VPRINTK("EXIT, returning %u\n", ent->n_ports); 5536 VPRINTK("EXIT, returning %u\n", ent->n_ports);
5515 return ent->n_ports; /* success */ 5537 return ent->n_ports; /* success */
5516 5538
5539err_out_free_irq:
5540 free_irq(ent->irq, host_set);
5517err_out: 5541err_out:
5518 for (i = 0; i < host_set->n_ports; i++) { 5542 for (i = 0; i < host_set->n_ports; i++) {
5519 struct ata_port *ap = host_set->ports[i]; 5543 struct ata_port *ap = host_set->ports[i];
@@ -5605,6 +5629,8 @@ void ata_host_set_remove(struct ata_host_set *host_set)
5605 ata_port_detach(host_set->ports[i]); 5629 ata_port_detach(host_set->ports[i]);
5606 5630
5607 free_irq(host_set->irq, host_set); 5631 free_irq(host_set->irq, host_set);
5632 if (host_set->irq2)
5633 free_irq(host_set->irq2, host_set);
5608 5634
5609 for (i = 0; i < host_set->n_ports; i++) { 5635 for (i = 0; i < host_set->n_ports; i++) {
5610 struct ata_port *ap = host_set->ports[i]; 5636 struct ata_port *ap = host_set->ports[i];
@@ -5614,10 +5640,11 @@ void ata_host_set_remove(struct ata_host_set *host_set)
5614 if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) { 5640 if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
5615 struct ata_ioports *ioaddr = &ap->ioaddr; 5641 struct ata_ioports *ioaddr = &ap->ioaddr;
5616 5642
5617 if (ioaddr->cmd_addr == 0x1f0) 5643 /* FIXME: Add -ac IDE pci mods to remove these special cases */
5618 release_region(0x1f0, 8); 5644 if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
5619 else if (ioaddr->cmd_addr == 0x170) 5645 release_region(ATA_PRIMARY_CMD, 8);
5620 release_region(0x170, 8); 5646 else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
5647 release_region(ATA_SECONDARY_CMD, 8);
5621 } 5648 }
5622 5649
5623 scsi_host_put(ap->host); 5650 scsi_host_put(ap->host);
@@ -5735,11 +5762,8 @@ void ata_pci_remove_one (struct pci_dev *pdev)
5735{ 5762{
5736 struct device *dev = pci_dev_to_dev(pdev); 5763 struct device *dev = pci_dev_to_dev(pdev);
5737 struct ata_host_set *host_set = dev_get_drvdata(dev); 5764 struct ata_host_set *host_set = dev_get_drvdata(dev);
5738 struct ata_host_set *host_set2 = host_set->next;
5739 5765
5740 ata_host_set_remove(host_set); 5766 ata_host_set_remove(host_set);
5741 if (host_set2)
5742 ata_host_set_remove(host_set2);
5743 5767
5744 pci_release_regions(pdev); 5768 pci_release_regions(pdev);
5745 pci_disable_device(pdev); 5769 pci_disable_device(pdev);
@@ -5807,14 +5831,6 @@ int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
5807 if (rc) 5831 if (rc)
5808 return rc; 5832 return rc;
5809 5833
5810 if (host_set->next) {
5811 rc = ata_host_set_suspend(host_set->next, mesg);
5812 if (rc) {
5813 ata_host_set_resume(host_set);
5814 return rc;
5815 }
5816 }
5817
5818 ata_pci_device_do_suspend(pdev, mesg); 5834 ata_pci_device_do_suspend(pdev, mesg);
5819 5835
5820 return 0; 5836 return 0;
@@ -5826,9 +5842,6 @@ int ata_pci_device_resume(struct pci_dev *pdev)
5826 5842
5827 ata_pci_device_do_resume(pdev); 5843 ata_pci_device_do_resume(pdev);
5828 ata_host_set_resume(host_set); 5844 ata_host_set_resume(host_set);
5829 if (host_set->next)
5830 ata_host_set_resume(host_set->next);
5831
5832 return 0; 5845 return 0;
5833} 5846}
5834#endif /* CONFIG_PCI */ 5847#endif /* CONFIG_PCI */