diff options
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r-- | drivers/scsi/libata-core.c | 59 |
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 | ||
5539 | err_out_free_irq: | ||
5540 | free_irq(ent->irq, host_set); | ||
5517 | err_out: | 5541 | err_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 */ |