Loading drivers/scsi/ufs/ufs_quirks.c +15 −1 Original line number Diff line number Diff line /* * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -30,6 +30,20 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ), UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8aL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hD8aL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8aM1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "h08aM1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8GL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8HL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), END_FIX }; Loading drivers/scsi/ufs/ufs_quirks.h +9 −1 Original line number Diff line number Diff line /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -130,6 +130,14 @@ struct ufs_card_fix { */ #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 7) /* * Some UFS devices may stop responding after switching from HS-G1 to HS-G3. * Also, it is found that these devices work fine if we do 2 steps switch: * HS-G1 to HS-G2 followed by HS-G2 to HS-G3. Enabling this quirk for such * device would apply this 2 steps gear switch workaround. */ #define UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH (1 << 8) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); Loading drivers/scsi/ufs/ufshcd.c +30 −4 Original line number Diff line number Diff line Loading @@ -524,7 +524,7 @@ static int ufshcd_reset_device(struct ufs_hba *hba) /* replace non-printable or non-ASCII characters with spaces */ static inline void ufshcd_remove_non_printable(char *val) { if (!val) if (!val || !*val) return; if (*val < 0x20 || *val > 0x7e) Loading Loading @@ -3670,7 +3670,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf, goto out; } buff_ascii = kmalloc(ascii_len, GFP_KERNEL); buff_ascii = kzalloc(ascii_len, GFP_KERNEL); if (!buff_ascii) { dev_err(hba->dev, "%s: Failed allocating %d bytes\n", __func__, ascii_len); Loading Loading @@ -9370,6 +9370,32 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) if (scale_up) { memcpy(&new_pwr_info, &hba->clk_scaling.saved_pwr_info.info, sizeof(struct ufs_pa_layer_attr)); /* * Some UFS devices may stop responding after switching from * HS-G1 to HS-G3. Also, it is found that these devices work * fine if we do 2 steps switch: HS-G1 to HS-G2 followed by * HS-G2 to HS-G3. If UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH * quirk is enabled for such devices, this 2 steps gear switch * workaround will be applied. */ if ((hba->dev_info.quirks & UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH) && (hba->pwr_info.gear_tx == UFS_HS_G1) && (new_pwr_info.gear_tx == UFS_HS_G3)) { /* scale up to G2 first */ new_pwr_info.gear_tx = UFS_HS_G2; new_pwr_info.gear_rx = UFS_HS_G2; ret = ufshcd_change_power_mode(hba, &new_pwr_info); if (ret) goto out; /* scale up to G3 now */ new_pwr_info.gear_tx = UFS_HS_G3; new_pwr_info.gear_rx = UFS_HS_G3; ret = ufshcd_change_power_mode(hba, &new_pwr_info); if (ret) goto out; } } else { memcpy(&new_pwr_info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr)); Loading @@ -9389,10 +9415,10 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) new_pwr_info.pwr_rx = FASTAUTO_MODE; } } } ret = ufshcd_change_power_mode(hba, &new_pwr_info); } out: if (ret) dev_err(hba->dev, "%s: failed err %d, old gear: (tx %d rx %d), new gear: (tx %d rx %d), scale_up = %d", __func__, ret, Loading Loading
drivers/scsi/ufs/ufs_quirks.c +15 −1 Original line number Diff line number Diff line /* * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -30,6 +30,20 @@ static struct ufs_card_fix ufs_fixups[] = { UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ), UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8aL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hD8aL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8aM1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "h08aM1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8GL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8HL1", UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH), END_FIX }; Loading
drivers/scsi/ufs/ufs_quirks.h +9 −1 Original line number Diff line number Diff line /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -130,6 +130,14 @@ struct ufs_card_fix { */ #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 7) /* * Some UFS devices may stop responding after switching from HS-G1 to HS-G3. * Also, it is found that these devices work fine if we do 2 steps switch: * HS-G1 to HS-G2 followed by HS-G2 to HS-G3. Enabling this quirk for such * device would apply this 2 steps gear switch workaround. */ #define UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH (1 << 8) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); Loading
drivers/scsi/ufs/ufshcd.c +30 −4 Original line number Diff line number Diff line Loading @@ -524,7 +524,7 @@ static int ufshcd_reset_device(struct ufs_hba *hba) /* replace non-printable or non-ASCII characters with spaces */ static inline void ufshcd_remove_non_printable(char *val) { if (!val) if (!val || !*val) return; if (*val < 0x20 || *val > 0x7e) Loading Loading @@ -3670,7 +3670,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf, goto out; } buff_ascii = kmalloc(ascii_len, GFP_KERNEL); buff_ascii = kzalloc(ascii_len, GFP_KERNEL); if (!buff_ascii) { dev_err(hba->dev, "%s: Failed allocating %d bytes\n", __func__, ascii_len); Loading Loading @@ -9370,6 +9370,32 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) if (scale_up) { memcpy(&new_pwr_info, &hba->clk_scaling.saved_pwr_info.info, sizeof(struct ufs_pa_layer_attr)); /* * Some UFS devices may stop responding after switching from * HS-G1 to HS-G3. Also, it is found that these devices work * fine if we do 2 steps switch: HS-G1 to HS-G2 followed by * HS-G2 to HS-G3. If UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH * quirk is enabled for such devices, this 2 steps gear switch * workaround will be applied. */ if ((hba->dev_info.quirks & UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH) && (hba->pwr_info.gear_tx == UFS_HS_G1) && (new_pwr_info.gear_tx == UFS_HS_G3)) { /* scale up to G2 first */ new_pwr_info.gear_tx = UFS_HS_G2; new_pwr_info.gear_rx = UFS_HS_G2; ret = ufshcd_change_power_mode(hba, &new_pwr_info); if (ret) goto out; /* scale up to G3 now */ new_pwr_info.gear_tx = UFS_HS_G3; new_pwr_info.gear_rx = UFS_HS_G3; ret = ufshcd_change_power_mode(hba, &new_pwr_info); if (ret) goto out; } } else { memcpy(&new_pwr_info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr)); Loading @@ -9389,10 +9415,10 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) new_pwr_info.pwr_rx = FASTAUTO_MODE; } } } ret = ufshcd_change_power_mode(hba, &new_pwr_info); } out: if (ret) dev_err(hba->dev, "%s: failed err %d, old gear: (tx %d rx %d), new gear: (tx %d rx %d), scale_up = %d", __func__, ret, Loading