diff options
author | Tejun Heo <htejun@gmail.com> | 2006-03-05 14:31:57 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-11 19:03:39 -0500 |
commit | a6d5a51cf1bf5d83ddd2e06fd372a79b395fb393 (patch) | |
tree | 4dd9a341ed20444d9b66b9032b8d332069f54220 | |
parent | 23e71c3d3e88b9f554ecd47d6f9aec76e89e2e6d (diff) |
[PATCH] libata: reimplement ata_set_mode() using xfer_mask helpers
Use xfer_mask helpers to determine transfer mode. This rewrite also
makes transfer mode determination done before any actual
configuration. This patch doesn't result in any functional changes.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/scsi/libata-core.c | 233 |
1 files changed, 79 insertions, 154 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 88495127efb2..d211f0b1d721 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -65,11 +65,9 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, | |||
65 | struct ata_device *dev); | 65 | struct ata_device *dev); |
66 | static void ata_set_mode(struct ata_port *ap); | 66 | static void ata_set_mode(struct ata_port *ap); |
67 | static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); | 67 | static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); |
68 | static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift); | 68 | static unsigned int ata_dev_xfermask(struct ata_port *ap, |
69 | struct ata_device *dev); | ||
69 | static int fgb(u32 bitmap); | 70 | static int fgb(u32 bitmap); |
70 | static int ata_choose_xfer_mode(const struct ata_port *ap, | ||
71 | u8 *xfer_mode_out, | ||
72 | unsigned int *xfer_shift_out); | ||
73 | 71 | ||
74 | static unsigned int ata_unique_id = 1; | 72 | static unsigned int ata_unique_id = 1; |
75 | static struct workqueue_struct *ata_wq; | 73 | static struct workqueue_struct *ata_wq; |
@@ -1776,51 +1774,42 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) | |||
1776 | 1774 | ||
1777 | static int ata_host_set_pio(struct ata_port *ap) | 1775 | static int ata_host_set_pio(struct ata_port *ap) |
1778 | { | 1776 | { |
1779 | unsigned int mask; | 1777 | int i; |
1780 | int x, i; | ||
1781 | u8 base, xfer_mode; | ||
1782 | |||
1783 | mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); | ||
1784 | x = fgb(mask); | ||
1785 | if (x < 0) { | ||
1786 | printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); | ||
1787 | return -1; | ||
1788 | } | ||
1789 | |||
1790 | base = base_from_shift(ATA_SHIFT_PIO); | ||
1791 | xfer_mode = base + x; | ||
1792 | |||
1793 | DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", | ||
1794 | (int)base, (int)xfer_mode, mask, x); | ||
1795 | 1778 | ||
1796 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 1779 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
1797 | struct ata_device *dev = &ap->device[i]; | 1780 | struct ata_device *dev = &ap->device[i]; |
1798 | if (ata_dev_present(dev)) { | 1781 | |
1799 | dev->pio_mode = xfer_mode; | 1782 | if (!ata_dev_present(dev)) |
1800 | dev->xfer_mode = xfer_mode; | 1783 | continue; |
1801 | dev->xfer_shift = ATA_SHIFT_PIO; | 1784 | |
1802 | if (ap->ops->set_piomode) | 1785 | if (!dev->pio_mode) { |
1803 | ap->ops->set_piomode(ap, dev); | 1786 | printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); |
1787 | return -1; | ||
1804 | } | 1788 | } |
1789 | |||
1790 | dev->xfer_mode = dev->pio_mode; | ||
1791 | dev->xfer_shift = ATA_SHIFT_PIO; | ||
1792 | if (ap->ops->set_piomode) | ||
1793 | ap->ops->set_piomode(ap, dev); | ||
1805 | } | 1794 | } |
1806 | 1795 | ||
1807 | return 0; | 1796 | return 0; |
1808 | } | 1797 | } |
1809 | 1798 | ||
1810 | static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, | 1799 | static void ata_host_set_dma(struct ata_port *ap) |
1811 | unsigned int xfer_shift) | ||
1812 | { | 1800 | { |
1813 | int i; | 1801 | int i; |
1814 | 1802 | ||
1815 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 1803 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
1816 | struct ata_device *dev = &ap->device[i]; | 1804 | struct ata_device *dev = &ap->device[i]; |
1817 | if (ata_dev_present(dev)) { | 1805 | |
1818 | dev->dma_mode = xfer_mode; | 1806 | if (!ata_dev_present(dev) || !dev->dma_mode) |
1819 | dev->xfer_mode = xfer_mode; | 1807 | continue; |
1820 | dev->xfer_shift = xfer_shift; | 1808 | |
1821 | if (ap->ops->set_dmamode) | 1809 | dev->xfer_mode = dev->dma_mode; |
1822 | ap->ops->set_dmamode(ap, dev); | 1810 | dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode); |
1823 | } | 1811 | if (ap->ops->set_dmamode) |
1812 | ap->ops->set_dmamode(ap, dev); | ||
1824 | } | 1813 | } |
1825 | } | 1814 | } |
1826 | 1815 | ||
@@ -1835,28 +1824,34 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, | |||
1835 | */ | 1824 | */ |
1836 | static void ata_set_mode(struct ata_port *ap) | 1825 | static void ata_set_mode(struct ata_port *ap) |
1837 | { | 1826 | { |
1838 | unsigned int xfer_shift; | 1827 | int i, rc; |
1839 | u8 xfer_mode; | ||
1840 | int rc; | ||
1841 | 1828 | ||
1842 | /* step 1: always set host PIO timings */ | 1829 | /* step 1: calculate xfer_mask */ |
1843 | rc = ata_host_set_pio(ap); | 1830 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
1844 | if (rc) | 1831 | struct ata_device *dev = &ap->device[i]; |
1845 | goto err_out; | 1832 | unsigned int xfer_mask; |
1833 | |||
1834 | if (!ata_dev_present(dev)) | ||
1835 | continue; | ||
1846 | 1836 | ||
1847 | /* step 2: choose the best data xfer mode */ | 1837 | xfer_mask = ata_dev_xfermask(ap, dev); |
1848 | xfer_mode = xfer_shift = 0; | 1838 | |
1849 | rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift); | 1839 | dev->pio_mode = ata_xfer_mask2mode(xfer_mask & ATA_MASK_PIO); |
1840 | dev->dma_mode = ata_xfer_mask2mode(xfer_mask & (ATA_MASK_MWDMA | | ||
1841 | ATA_MASK_UDMA)); | ||
1842 | } | ||
1843 | |||
1844 | /* step 2: always set host PIO timings */ | ||
1845 | rc = ata_host_set_pio(ap); | ||
1850 | if (rc) | 1846 | if (rc) |
1851 | goto err_out; | 1847 | goto err_out; |
1852 | 1848 | ||
1853 | /* step 3: if that xfer mode isn't PIO, set host DMA timings */ | 1849 | /* step 3: set host DMA timings */ |
1854 | if (xfer_shift != ATA_SHIFT_PIO) | 1850 | ata_host_set_dma(ap); |
1855 | ata_host_set_dma(ap, xfer_mode, xfer_shift); | ||
1856 | 1851 | ||
1857 | /* step 4: update devices' xfer mode */ | 1852 | /* step 4: update devices' xfer mode */ |
1858 | ata_dev_set_mode(ap, &ap->device[0]); | 1853 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
1859 | ata_dev_set_mode(ap, &ap->device[1]); | 1854 | ata_dev_set_mode(ap, &ap->device[i]); |
1860 | 1855 | ||
1861 | if (ap->flags & ATA_FLAG_PORT_DISABLED) | 1856 | if (ap->flags & ATA_FLAG_PORT_DISABLED) |
1862 | return; | 1857 | return; |
@@ -2654,77 +2649,45 @@ static int ata_dma_blacklisted(const struct ata_device *dev) | |||
2654 | return 0; | 2649 | return 0; |
2655 | } | 2650 | } |
2656 | 2651 | ||
2657 | static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift) | 2652 | /** |
2653 | * ata_dev_xfermask - Compute supported xfermask of the given device | ||
2654 | * @ap: Port on which the device to compute xfermask for resides | ||
2655 | * @dev: Device to compute xfermask for | ||
2656 | * | ||
2657 | * Compute supported xfermask of @dev. This function is | ||
2658 | * responsible for applying all known limits including host | ||
2659 | * controller limits, device blacklist, etc... | ||
2660 | * | ||
2661 | * LOCKING: | ||
2662 | * None. | ||
2663 | * | ||
2664 | * RETURNS: | ||
2665 | * Computed xfermask. | ||
2666 | */ | ||
2667 | static unsigned int ata_dev_xfermask(struct ata_port *ap, | ||
2668 | struct ata_device *dev) | ||
2658 | { | 2669 | { |
2659 | const struct ata_device *master, *slave; | 2670 | unsigned long xfer_mask; |
2660 | unsigned int mask; | 2671 | int i; |
2661 | |||
2662 | master = &ap->device[0]; | ||
2663 | slave = &ap->device[1]; | ||
2664 | 2672 | ||
2665 | WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave)); | 2673 | xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, |
2674 | ap->udma_mask); | ||
2666 | 2675 | ||
2667 | if (shift == ATA_SHIFT_UDMA) { | 2676 | /* use port-wide xfermask for now */ |
2668 | mask = ap->udma_mask; | 2677 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
2669 | if (ata_dev_present(master)) { | 2678 | struct ata_device *d = &ap->device[i]; |
2670 | mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); | 2679 | if (!ata_dev_present(d)) |
2671 | if (ata_dma_blacklisted(master)) { | 2680 | continue; |
2672 | mask = 0; | 2681 | xfer_mask &= ata_id_xfermask(d->id); |
2673 | ata_pr_blacklisted(ap, master); | 2682 | if (ata_dma_blacklisted(d)) |
2674 | } | 2683 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); |
2675 | } | ||
2676 | if (ata_dev_present(slave)) { | ||
2677 | mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); | ||
2678 | if (ata_dma_blacklisted(slave)) { | ||
2679 | mask = 0; | ||
2680 | ata_pr_blacklisted(ap, slave); | ||
2681 | } | ||
2682 | } | ||
2683 | } | ||
2684 | else if (shift == ATA_SHIFT_MWDMA) { | ||
2685 | mask = ap->mwdma_mask; | ||
2686 | if (ata_dev_present(master)) { | ||
2687 | mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); | ||
2688 | if (ata_dma_blacklisted(master)) { | ||
2689 | mask = 0; | ||
2690 | ata_pr_blacklisted(ap, master); | ||
2691 | } | ||
2692 | } | ||
2693 | if (ata_dev_present(slave)) { | ||
2694 | mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); | ||
2695 | if (ata_dma_blacklisted(slave)) { | ||
2696 | mask = 0; | ||
2697 | ata_pr_blacklisted(ap, slave); | ||
2698 | } | ||
2699 | } | ||
2700 | } | ||
2701 | else if (shift == ATA_SHIFT_PIO) { | ||
2702 | mask = ap->pio_mask; | ||
2703 | if (ata_dev_present(master)) { | ||
2704 | /* spec doesn't return explicit support for | ||
2705 | * PIO0-2, so we fake it | ||
2706 | */ | ||
2707 | u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03; | ||
2708 | tmp_mode <<= 3; | ||
2709 | tmp_mode |= 0x7; | ||
2710 | mask &= tmp_mode; | ||
2711 | } | ||
2712 | if (ata_dev_present(slave)) { | ||
2713 | /* spec doesn't return explicit support for | ||
2714 | * PIO0-2, so we fake it | ||
2715 | */ | ||
2716 | u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03; | ||
2717 | tmp_mode <<= 3; | ||
2718 | tmp_mode |= 0x7; | ||
2719 | mask &= tmp_mode; | ||
2720 | } | ||
2721 | } | ||
2722 | else { | ||
2723 | mask = 0xffffffff; /* shut up compiler warning */ | ||
2724 | BUG(); | ||
2725 | } | 2684 | } |
2726 | 2685 | ||
2727 | return mask; | 2686 | if (ata_dma_blacklisted(dev)) |
2687 | printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " | ||
2688 | "disabling DMA\n", ap->id, dev->devno); | ||
2689 | |||
2690 | return xfer_mask; | ||
2728 | } | 2691 | } |
2729 | 2692 | ||
2730 | /* find greatest bit */ | 2693 | /* find greatest bit */ |
@@ -2741,44 +2704,6 @@ static int fgb(u32 bitmap) | |||
2741 | } | 2704 | } |
2742 | 2705 | ||
2743 | /** | 2706 | /** |
2744 | * ata_choose_xfer_mode - attempt to find best transfer mode | ||
2745 | * @ap: Port for which an xfer mode will be selected | ||
2746 | * @xfer_mode_out: (output) SET FEATURES - XFER MODE code | ||
2747 | * @xfer_shift_out: (output) bit shift that selects this mode | ||
2748 | * | ||
2749 | * Based on host and device capabilities, determine the | ||
2750 | * maximum transfer mode that is amenable to all. | ||
2751 | * | ||
2752 | * LOCKING: | ||
2753 | * PCI/etc. bus probe sem. | ||
2754 | * | ||
2755 | * RETURNS: | ||
2756 | * Zero on success, negative on error. | ||
2757 | */ | ||
2758 | |||
2759 | static int ata_choose_xfer_mode(const struct ata_port *ap, | ||
2760 | u8 *xfer_mode_out, | ||
2761 | unsigned int *xfer_shift_out) | ||
2762 | { | ||
2763 | unsigned int mask, shift; | ||
2764 | int x, i; | ||
2765 | |||
2766 | for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { | ||
2767 | shift = xfer_mode_classes[i].shift; | ||
2768 | mask = ata_get_mode_mask(ap, shift); | ||
2769 | |||
2770 | x = fgb(mask); | ||
2771 | if (x >= 0) { | ||
2772 | *xfer_mode_out = xfer_mode_classes[i].base + x; | ||
2773 | *xfer_shift_out = shift; | ||
2774 | return 0; | ||
2775 | } | ||
2776 | } | ||
2777 | |||
2778 | return -1; | ||
2779 | } | ||
2780 | |||
2781 | /** | ||
2782 | * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command | 2707 | * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command |
2783 | * @ap: Port associated with device @dev | 2708 | * @ap: Port associated with device @dev |
2784 | * @dev: Device to which command will be sent | 2709 | * @dev: Device to which command will be sent |