diff options
author | Tejun Heo <tj@kernel.org> | 2009-01-29 06:31:33 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-02-02 23:03:22 -0500 |
commit | a07d499b4759881db1359dd8812eecd00b0e0a28 (patch) | |
tree | aaa5a5c95b64ab121ca89a71899abfe8837890f6 /drivers/ata | |
parent | 99cf610aa4840d822cdc67d194b23b55010ca9bd (diff) |
libata: add @spd_limit to sata_down_spd_limit()
Add @spd_limit to sata_down_spd_limit() so that the caller can specify
the SPD limit it wants. This parameter doesn't get in the way even
when it's too low. The closest possible limit is applied.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 25 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 10 | ||||
-rw-r--r-- | drivers/ata/libata-pmp.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata.h | 2 |
4 files changed, 27 insertions, 12 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 564c03c4ebb3..3c5965d56c47 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -2777,7 +2777,7 @@ int ata_bus_probe(struct ata_port *ap) | |||
2777 | /* This is the last chance, better to slow | 2777 | /* This is the last chance, better to slow |
2778 | * down than lose it. | 2778 | * down than lose it. |
2779 | */ | 2779 | */ |
2780 | sata_down_spd_limit(&ap->link); | 2780 | sata_down_spd_limit(&ap->link, 0); |
2781 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); | 2781 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); |
2782 | } | 2782 | } |
2783 | } | 2783 | } |
@@ -2873,21 +2873,27 @@ void ata_port_disable(struct ata_port *ap) | |||
2873 | /** | 2873 | /** |
2874 | * sata_down_spd_limit - adjust SATA spd limit downward | 2874 | * sata_down_spd_limit - adjust SATA spd limit downward |
2875 | * @link: Link to adjust SATA spd limit for | 2875 | * @link: Link to adjust SATA spd limit for |
2876 | * @spd_limit: Additional limit | ||
2876 | * | 2877 | * |
2877 | * Adjust SATA spd limit of @link downward. Note that this | 2878 | * Adjust SATA spd limit of @link downward. Note that this |
2878 | * function only adjusts the limit. The change must be applied | 2879 | * function only adjusts the limit. The change must be applied |
2879 | * using sata_set_spd(). | 2880 | * using sata_set_spd(). |
2880 | * | 2881 | * |
2882 | * If @spd_limit is non-zero, the speed is limited to equal to or | ||
2883 | * lower than @spd_limit if such speed is supported. If | ||
2884 | * @spd_limit is slower than any supported speed, only the lowest | ||
2885 | * supported speed is allowed. | ||
2886 | * | ||
2881 | * LOCKING: | 2887 | * LOCKING: |
2882 | * Inherited from caller. | 2888 | * Inherited from caller. |
2883 | * | 2889 | * |
2884 | * RETURNS: | 2890 | * RETURNS: |
2885 | * 0 on success, negative errno on failure | 2891 | * 0 on success, negative errno on failure |
2886 | */ | 2892 | */ |
2887 | int sata_down_spd_limit(struct ata_link *link) | 2893 | int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) |
2888 | { | 2894 | { |
2889 | u32 sstatus, spd, mask; | 2895 | u32 sstatus, spd, mask; |
2890 | int rc, highbit; | 2896 | int rc, bit; |
2891 | 2897 | ||
2892 | if (!sata_scr_valid(link)) | 2898 | if (!sata_scr_valid(link)) |
2893 | return -EOPNOTSUPP; | 2899 | return -EOPNOTSUPP; |
@@ -2906,8 +2912,8 @@ int sata_down_spd_limit(struct ata_link *link) | |||
2906 | return -EINVAL; | 2912 | return -EINVAL; |
2907 | 2913 | ||
2908 | /* unconditionally mask off the highest bit */ | 2914 | /* unconditionally mask off the highest bit */ |
2909 | highbit = fls(mask) - 1; | 2915 | bit = fls(mask) - 1; |
2910 | mask &= ~(1 << highbit); | 2916 | mask &= ~(1 << bit); |
2911 | 2917 | ||
2912 | /* Mask off all speeds higher than or equal to the current | 2918 | /* Mask off all speeds higher than or equal to the current |
2913 | * one. Force 1.5Gbps if current SPD is not available. | 2919 | * one. Force 1.5Gbps if current SPD is not available. |
@@ -2921,6 +2927,15 @@ int sata_down_spd_limit(struct ata_link *link) | |||
2921 | if (!mask) | 2927 | if (!mask) |
2922 | return -EINVAL; | 2928 | return -EINVAL; |
2923 | 2929 | ||
2930 | if (spd_limit) { | ||
2931 | if (mask & ((1 << spd_limit) - 1)) | ||
2932 | mask &= (1 << spd_limit) - 1; | ||
2933 | else { | ||
2934 | bit = ffs(mask) - 1; | ||
2935 | mask = 1 << bit; | ||
2936 | } | ||
2937 | } | ||
2938 | |||
2924 | link->sata_spd_limit = mask; | 2939 | link->sata_spd_limit = mask; |
2925 | 2940 | ||
2926 | ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n", | 2941 | ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n", |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 90092c1aae53..685509bc7ff0 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1875,7 +1875,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, | |||
1875 | /* speed down? */ | 1875 | /* speed down? */ |
1876 | if (verdict & ATA_EH_SPDN_SPEED_DOWN) { | 1876 | if (verdict & ATA_EH_SPDN_SPEED_DOWN) { |
1877 | /* speed down SATA link speed if possible */ | 1877 | /* speed down SATA link speed if possible */ |
1878 | if (sata_down_spd_limit(link) == 0) { | 1878 | if (sata_down_spd_limit(link, 0) == 0) { |
1879 | action |= ATA_EH_RESET; | 1879 | action |= ATA_EH_RESET; |
1880 | goto done; | 1880 | goto done; |
1881 | } | 1881 | } |
@@ -2627,11 +2627,11 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2627 | } | 2627 | } |
2628 | 2628 | ||
2629 | if (try == max_tries - 1) { | 2629 | if (try == max_tries - 1) { |
2630 | sata_down_spd_limit(link); | 2630 | sata_down_spd_limit(link, 0); |
2631 | if (slave) | 2631 | if (slave) |
2632 | sata_down_spd_limit(slave); | 2632 | sata_down_spd_limit(slave, 0); |
2633 | } else if (rc == -EPIPE) | 2633 | } else if (rc == -EPIPE) |
2634 | sata_down_spd_limit(failed_link); | 2634 | sata_down_spd_limit(failed_link, 0); |
2635 | 2635 | ||
2636 | if (hardreset) | 2636 | if (hardreset) |
2637 | reset = hardreset; | 2637 | reset = hardreset; |
@@ -3011,7 +3011,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) | |||
3011 | /* This is the last chance, better to slow | 3011 | /* This is the last chance, better to slow |
3012 | * down than lose it. | 3012 | * down than lose it. |
3013 | */ | 3013 | */ |
3014 | sata_down_spd_limit(ata_dev_phys_link(dev)); | 3014 | sata_down_spd_limit(ata_dev_phys_link(dev), 0); |
3015 | if (dev->pio_mode > XFER_PIO_0) | 3015 | if (dev->pio_mode > XFER_PIO_0) |
3016 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); | 3016 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); |
3017 | } | 3017 | } |
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 98ca07a2db87..619f2c33950e 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c | |||
@@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, | |||
729 | if (tries) { | 729 | if (tries) { |
730 | /* consecutive revalidation failures? speed down */ | 730 | /* consecutive revalidation failures? speed down */ |
731 | if (reval_failed) | 731 | if (reval_failed) |
732 | sata_down_spd_limit(link); | 732 | sata_down_spd_limit(link, 0); |
733 | else | 733 | else |
734 | reval_failed = 1; | 734 | reval_failed = 1; |
735 | 735 | ||
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 0a6f5be15112..cea8014cd87e 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -99,7 +99,7 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); | |||
99 | extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, | 99 | extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, |
100 | unsigned int readid_flags); | 100 | unsigned int readid_flags); |
101 | extern int ata_dev_configure(struct ata_device *dev); | 101 | extern int ata_dev_configure(struct ata_device *dev); |
102 | extern int sata_down_spd_limit(struct ata_link *link); | 102 | extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); |
103 | extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); | 103 | extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); |
104 | extern void ata_sg_clean(struct ata_queued_cmd *qc); | 104 | extern void ata_sg_clean(struct ata_queued_cmd *qc); |
105 | extern void ata_qc_free(struct ata_queued_cmd *qc); | 105 | extern void ata_qc_free(struct ata_queued_cmd *qc); |