aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c52
-rw-r--r--include/linux/libata.h2
2 files changed, 44 insertions, 10 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index d2336673601c..315f46841f68 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2786,9 +2786,9 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
2786} 2786}
2787 2787
2788/** 2788/**
2789 * sata_std_hardreset - reset host port via SATA phy reset 2789 * sata_port_hardreset - reset port via SATA phy reset
2790 * @ap: port to reset 2790 * @ap: port to reset
2791 * @class: resulting class of attached device 2791 * @timing: timing parameters { interval, duratinon, timeout } in msec
2792 * 2792 *
2793 * SATA phy-reset host port using DET bits of SControl register. 2793 * SATA phy-reset host port using DET bits of SControl register.
2794 * 2794 *
@@ -2798,10 +2798,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
2798 * RETURNS: 2798 * RETURNS:
2799 * 0 on success, -errno otherwise. 2799 * 0 on success, -errno otherwise.
2800 */ 2800 */
2801int sata_std_hardreset(struct ata_port *ap, unsigned int *class) 2801int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
2802{ 2802{
2803 struct ata_eh_context *ehc = &ap->eh_context;
2804 const unsigned long *timing = sata_ehc_deb_timing(ehc);
2805 u32 scontrol; 2803 u32 scontrol;
2806 int rc; 2804 int rc;
2807 2805
@@ -2814,24 +2812,24 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
2814 * and Sil3124. 2812 * and Sil3124.
2815 */ 2813 */
2816 if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) 2814 if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
2817 return rc; 2815 goto out;
2818 2816
2819 scontrol = (scontrol & 0x0f0) | 0x304; 2817 scontrol = (scontrol & 0x0f0) | 0x304;
2820 2818
2821 if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) 2819 if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
2822 return rc; 2820 goto out;
2823 2821
2824 sata_set_spd(ap); 2822 sata_set_spd(ap);
2825 } 2823 }
2826 2824
2827 /* issue phy wake/reset */ 2825 /* issue phy wake/reset */
2828 if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) 2826 if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
2829 return rc; 2827 goto out;
2830 2828
2831 scontrol = (scontrol & 0x0f0) | 0x301; 2829 scontrol = (scontrol & 0x0f0) | 0x301;
2832 2830
2833 if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) 2831 if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
2834 return rc; 2832 goto out;
2835 2833
2836 /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 2834 /* Couldn't find anything in SATA I/II specs, but AHCI-1.1
2837 * 10.4.2 says at least 1 ms. 2835 * 10.4.2 says at least 1 ms.
@@ -2839,7 +2837,40 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
2839 msleep(1); 2837 msleep(1);
2840 2838
2841 /* bring phy back */ 2839 /* bring phy back */
2842 sata_phy_resume(ap, timing); 2840 rc = sata_phy_resume(ap, timing);
2841 out:
2842 DPRINTK("EXIT, rc=%d\n", rc);
2843 return rc;
2844}
2845
2846/**
2847 * sata_std_hardreset - reset host port via SATA phy reset
2848 * @ap: port to reset
2849 * @class: resulting class of attached device
2850 *
2851 * SATA phy-reset host port using DET bits of SControl register,
2852 * wait for !BSY and classify the attached device.
2853 *
2854 * LOCKING:
2855 * Kernel thread context (may sleep)
2856 *
2857 * RETURNS:
2858 * 0 on success, -errno otherwise.
2859 */
2860int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
2861{
2862 const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
2863 int rc;
2864
2865 DPRINTK("ENTER\n");
2866
2867 /* do hardreset */
2868 rc = sata_port_hardreset(ap, timing);
2869 if (rc) {
2870 ata_port_printk(ap, KERN_ERR,
2871 "COMRESET failed (errno=%d)\n", rc);
2872 return rc;
2873 }
2843 2874
2844 /* TODO: phy layer with polling, timeouts, etc. */ 2875 /* TODO: phy layer with polling, timeouts, etc. */
2845 if (ata_port_offline(ap)) { 2876 if (ata_port_offline(ap)) {
@@ -6159,6 +6190,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset);
6159EXPORT_SYMBOL_GPL(ata_bus_reset); 6190EXPORT_SYMBOL_GPL(ata_bus_reset);
6160EXPORT_SYMBOL_GPL(ata_std_prereset); 6191EXPORT_SYMBOL_GPL(ata_std_prereset);
6161EXPORT_SYMBOL_GPL(ata_std_softreset); 6192EXPORT_SYMBOL_GPL(ata_std_softreset);
6193EXPORT_SYMBOL_GPL(sata_port_hardreset);
6162EXPORT_SYMBOL_GPL(sata_std_hardreset); 6194EXPORT_SYMBOL_GPL(sata_std_hardreset);
6163EXPORT_SYMBOL_GPL(ata_std_postreset); 6195EXPORT_SYMBOL_GPL(ata_std_postreset);
6164EXPORT_SYMBOL_GPL(ata_dev_classify); 6196EXPORT_SYMBOL_GPL(ata_dev_classify);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index d3bf7b936c3f..41fa0890dbfb 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -702,6 +702,8 @@ extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param);
702extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param); 702extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param);
703extern int ata_std_prereset(struct ata_port *ap); 703extern int ata_std_prereset(struct ata_port *ap);
704extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); 704extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
705extern int sata_port_hardreset(struct ata_port *ap,
706 const unsigned long *timing);
705extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); 707extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
706extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); 708extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
707extern void ata_port_disable(struct ata_port *); 709extern void ata_port_disable(struct ata_port *);