aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-03-27 12:58:20 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-29 19:30:28 -0500
commit5444a6f405618706eddbe1605ef8533b1b655764 (patch)
tree9265a1e65563add47a9fe5f1ddae44d6dd0742e3 /drivers
parent692785e798f341c057ff976c35a3d86ad5af8ac6 (diff)
[PATCH] libata: Simplex and other mode filtering logic
Add a field to the host_set called 'flags' (was host_set_flags changed to suit Jeff) Add a simplex_claimed field so we can remember who owns the DMA channel Add a ->mode_filter() hook to allow drivers to filter modes Add docs for mode_filter and set_mode Filter according to simplex state Filter cable in core This provides the needed framework to support all the mode rules found in the PATA world. The simplex filter deals with 'to spec' simplex DMA systems found in older chips. The cable filter avoids duplicating the same rules in each chip driver with PATA. Finally the mode filter is neccessary because drive/chip combinations have errata that forbid certain modes with some drives or types of ATA object. Drive speed setup remains per channel for now and the filters now use the framework Tejun put into place which cleans them up a lot from the older libata-pata patches. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libata-core.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 41659448a20..b1ddf40533b 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1818,7 +1818,7 @@ static void ata_host_set_dma(struct ata_port *ap)
1818 */ 1818 */
1819static void ata_set_mode(struct ata_port *ap) 1819static void ata_set_mode(struct ata_port *ap)
1820{ 1820{
1821 int i, rc; 1821 int i, rc, used_dma = 0;
1822 1822
1823 /* step 1: calculate xfer_mask */ 1823 /* step 1: calculate xfer_mask */
1824 for (i = 0; i < ATA_MAX_DEVICES; i++) { 1824 for (i = 0; i < ATA_MAX_DEVICES; i++) {
@@ -1836,6 +1836,9 @@ static void ata_set_mode(struct ata_port *ap)
1836 dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); 1836 dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
1837 dev->pio_mode = ata_xfer_mask2mode(pio_mask); 1837 dev->pio_mode = ata_xfer_mask2mode(pio_mask);
1838 dev->dma_mode = ata_xfer_mask2mode(dma_mask); 1838 dev->dma_mode = ata_xfer_mask2mode(dma_mask);
1839
1840 if (dev->dma_mode)
1841 used_dma = 1;
1839 } 1842 }
1840 1843
1841 /* step 2: always set host PIO timings */ 1844 /* step 2: always set host PIO timings */
@@ -1857,6 +1860,17 @@ static void ata_set_mode(struct ata_port *ap)
1857 goto err_out; 1860 goto err_out;
1858 } 1861 }
1859 1862
1863 /*
1864 * Record simplex status. If we selected DMA then the other
1865 * host channels are not permitted to do so.
1866 */
1867
1868 if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
1869 ap->host_set->simplex_claimed = 1;
1870
1871 /*
1872 * Chip specific finalisation
1873 */
1860 if (ap->ops->post_set_mode) 1874 if (ap->ops->post_set_mode)
1861 ap->ops->post_set_mode(ap); 1875 ap->ops->post_set_mode(ap);
1862 1876
@@ -2646,13 +2660,14 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
2646 */ 2660 */
2647static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) 2661static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
2648{ 2662{
2663 struct ata_host_set *hs = ap->host_set;
2649 unsigned long xfer_mask; 2664 unsigned long xfer_mask;
2650 int i; 2665 int i;
2651 2666
2652 xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, 2667 xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
2653 ap->udma_mask); 2668 ap->udma_mask);
2654 2669
2655 /* use port-wide xfermask for now */ 2670 /* FIXME: Use port-wide xfermask for now */
2656 for (i = 0; i < ATA_MAX_DEVICES; i++) { 2671 for (i = 0; i < ATA_MAX_DEVICES; i++) {
2657 struct ata_device *d = &ap->device[i]; 2672 struct ata_device *d = &ap->device[i];
2658 if (!ata_dev_present(d)) 2673 if (!ata_dev_present(d))
@@ -2662,12 +2677,23 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
2662 xfer_mask &= ata_id_xfermask(d->id); 2677 xfer_mask &= ata_id_xfermask(d->id);
2663 if (ata_dma_blacklisted(d)) 2678 if (ata_dma_blacklisted(d))
2664 xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); 2679 xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
2680 /* Apply cable rule here. Don't apply it early because when
2681 we handle hot plug the cable type can itself change */
2682 if (ap->cbl == ATA_CBL_PATA40)
2683 xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
2665 } 2684 }
2666 2685
2667 if (ata_dma_blacklisted(dev)) 2686 if (ata_dma_blacklisted(dev))
2668 printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " 2687 printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
2669 "disabling DMA\n", ap->id, dev->devno); 2688 "disabling DMA\n", ap->id, dev->devno);
2670 2689
2690 if (hs->flags & ATA_HOST_SIMPLEX) {
2691 if (hs->simplex_claimed)
2692 xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
2693 }
2694 if (ap->ops->mode_filter)
2695 xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
2696
2671 ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, 2697 ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
2672 &dev->udma_mask); 2698 &dev->udma_mask);
2673} 2699}
@@ -4531,6 +4557,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
4531 host_set->mmio_base = ent->mmio_base; 4557 host_set->mmio_base = ent->mmio_base;
4532 host_set->private_data = ent->private_data; 4558 host_set->private_data = ent->private_data;
4533 host_set->ops = ent->port_ops; 4559 host_set->ops = ent->port_ops;
4560 host_set->flags = ent->host_set_flags;
4534 4561
4535 /* register each port bound to this device */ 4562 /* register each port bound to this device */
4536 for (i = 0; i < ent->n_ports; i++) { 4563 for (i = 0; i < ent->n_ports; i++) {