diff options
author | Tejun Heo <htejun@gmail.com> | 2006-04-02 04:54:46 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-02 10:02:57 -0400 |
commit | cf176e1aa92eb2a3faea8409e841396a66413937 (patch) | |
tree | b62a516d2f91d43a9f6d48492e2f6205160ac849 /drivers | |
parent | edbabd8679a39faef67def4438c9cbccb5c05c5d (diff) |
[PATCH] libata: implement ata_down_xfermask_limit()
Implement ata_down_xfermask_limit(). This function manipulates
@dev->pio/mwdma/udma_mask such that the next lower transfer mode is
selected. This will be used to improve ata_bus_probe() failure
handling and later by EH.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libata-core.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3ddfbe1b86c6..68fa64d24721 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -65,6 +65,8 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, | |||
65 | struct ata_device *dev, | 65 | struct ata_device *dev, |
66 | u16 heads, | 66 | u16 heads, |
67 | u16 sectors); | 67 | u16 sectors); |
68 | static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, | ||
69 | int force_pio0); | ||
68 | static int ata_down_sata_spd_limit(struct ata_port *ap); | 70 | static int ata_down_sata_spd_limit(struct ata_port *ap); |
69 | static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); | 71 | static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); |
70 | static unsigned int ata_dev_set_xfermode(struct ata_port *ap, | 72 | static unsigned int ata_dev_set_xfermode(struct ata_port *ap, |
@@ -1859,6 +1861,56 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, | |||
1859 | return 0; | 1861 | return 0; |
1860 | } | 1862 | } |
1861 | 1863 | ||
1864 | /** | ||
1865 | * ata_down_xfermask_limit - adjust dev xfer masks downward | ||
1866 | * @ap: Port associated with device @dev | ||
1867 | * @dev: Device to adjust xfer masks | ||
1868 | * @force_pio0: Force PIO0 | ||
1869 | * | ||
1870 | * Adjust xfer masks of @dev downward. Note that this function | ||
1871 | * does not apply the change. Invoking ata_set_mode() afterwards | ||
1872 | * will apply the limit. | ||
1873 | * | ||
1874 | * LOCKING: | ||
1875 | * Inherited from caller. | ||
1876 | * | ||
1877 | * RETURNS: | ||
1878 | * 0 on success, negative errno on failure | ||
1879 | */ | ||
1880 | static int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, | ||
1881 | int force_pio0) | ||
1882 | { | ||
1883 | unsigned long xfer_mask; | ||
1884 | int highbit; | ||
1885 | |||
1886 | xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask, | ||
1887 | dev->udma_mask); | ||
1888 | |||
1889 | if (!xfer_mask) | ||
1890 | goto fail; | ||
1891 | /* don't gear down to MWDMA from UDMA, go directly to PIO */ | ||
1892 | if (xfer_mask & ATA_MASK_UDMA) | ||
1893 | xfer_mask &= ~ATA_MASK_MWDMA; | ||
1894 | |||
1895 | highbit = fls(xfer_mask) - 1; | ||
1896 | xfer_mask &= ~(1 << highbit); | ||
1897 | if (force_pio0) | ||
1898 | xfer_mask &= 1 << ATA_SHIFT_PIO; | ||
1899 | if (!xfer_mask) | ||
1900 | goto fail; | ||
1901 | |||
1902 | ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, | ||
1903 | &dev->udma_mask); | ||
1904 | |||
1905 | printk(KERN_WARNING "ata%u: dev %u limiting speed to %s\n", | ||
1906 | ap->id, dev->devno, ata_mode_string(xfer_mask)); | ||
1907 | |||
1908 | return 0; | ||
1909 | |||
1910 | fail: | ||
1911 | return -EINVAL; | ||
1912 | } | ||
1913 | |||
1862 | static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) | 1914 | static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) |
1863 | { | 1915 | { |
1864 | unsigned int err_mask; | 1916 | unsigned int err_mask; |