--- zzzz-none-000/linux-4.4.60/drivers/scsi/ufs/ufs-qcom.c 2017-04-08 07:53:53.000000000 +0000 +++ jet-2400-727/linux-4.4.60/drivers/scsi/ufs/ufs-qcom.c 2021-03-17 14:36:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -1374,12 +1374,13 @@ host->testbus.select_minor = 1; } -static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) +bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, + u8 select_major, u8 select_minor) { - if (host->testbus.select_major >= TSTBUS_MAX) { + if (select_major >= TSTBUS_MAX) { dev_err(host->hba->dev, "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n", - __func__, host->testbus.select_major); + __func__, select_major); return false; } @@ -1388,10 +1389,10 @@ * mappings of select_minor, since there is no harm in * configuring a non-existent select_minor */ - if (host->testbus.select_minor > 0x1F) { + if (select_minor > 0x1F) { dev_err(host->hba->dev, "%s: 0x%05X is not a legal testbus option\n", - __func__, host->testbus.select_minor); + __func__, select_minor); return false; } @@ -1400,16 +1401,16 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) { - int reg; - int offset; + int reg = 0; + int offset, ret = 0, testbus_sel_offset = 19; u32 mask = TEST_BUS_SUB_SEL_MASK; + unsigned long flags; + struct ufs_hba *hba; if (!host) return -EINVAL; - - if (!ufs_qcom_testbus_cfg_is_ok(host)) - return -EPERM; - + hba = host->hba; + spin_lock_irqsave(hba->host->host_lock, flags); switch (host->testbus.select_major) { case TSTBUS_UAWM: reg = UFS_TEST_BUS_CTRL_0; @@ -1466,19 +1467,27 @@ */ } mask <<= offset; - + spin_unlock_irqrestore(hba->host->host_lock, flags); pm_runtime_get_sync(host->hba->dev); ufshcd_hold(host->hba, false); - ufshcd_rmwl(host->hba, TEST_BUS_SEL, - (u32)host->testbus.select_major << 19, + if (reg) { + ufshcd_rmwl(host->hba, TEST_BUS_SEL, + (u32)host->testbus.select_major << testbus_sel_offset, REG_UFS_CFG1); - ufshcd_rmwl(host->hba, mask, + ufshcd_rmwl(host->hba, mask, (u32)host->testbus.select_minor << offset, reg); - ufshcd_release(host->hba); + } else { + dev_err(hba->dev, "%s: Problem setting minor\n", __func__); + ret = -EINVAL; + goto out; + } + ufs_qcom_enable_test_bus(host); +out: + ufshcd_release(host->hba, false); pm_runtime_put_sync(host->hba->dev); - return 0; + return ret; } static void ufs_qcom_testbus_read(struct ufs_hba *hba)