Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 626ae1f0 authored by derfelot's avatar derfelot
Browse files

scsi: ufs: Add Sony modifications for yoshino Samsung and Hynix support

Taken from Sony 47.2.A.10.107 stock kernel
parent 27c730c2
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -433,6 +433,9 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
	struct sg_header *old_hdr = NULL;
	int retval = 0;

	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
		return -EINVAL;

	/*
	 * This could cause a response to be stranded. Close the associated
	 * file descriptor to free up any resources being held.
@@ -979,6 +982,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
		 * return an error value. So returning '0' to keep compability
		 * with legacy applications.
		 */
				mutex_lock(&sfp->parentdp->open_rel_lock);
				mutex_unlock(&sfp->parentdp->open_rel_lock);
		return 0;
	case SG_GET_LOW_DMA:
		return put_user((int) sdp->device->host->unchecked_isa_dma, ip);
+7 −0
Original line number Diff line number Diff line
@@ -96,6 +96,13 @@ config SCSI_UFS_QCOM_ICE
	  Select this if you have ICE supported for UFS on QCOM chipset.
	  If unsure, say N.

config SCSI_UFS_RESTRICT_TX_LANES
	bool "Restrict the number of TX lanes to 1"
	default n
	help
	  Say Y here to restrict the number of TX lanes to 1.
	  This will save the power consumption in exchange for
	  the write performance.

config SCSI_UFS_TEST
	tristate "Universal Flash Storage host controller driver unit-tests"
+198 −1
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@
 * of the driver from userspace.
 *
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include <linux/random.h>
#include "ufs-debugfs.h"
@@ -25,6 +30,7 @@
enum field_width {
	BYTE	= 1,
	WORD	= 2,
	DWORD	= 4,
};

struct desc_field_offset {
@@ -366,6 +372,7 @@ static const struct file_operations ufsdbg_err_inj_scenario_ops = {
	.open		= ufsdbg_err_inj_scenario_open,
	.read		= seq_read,
	.write		= ufsdbg_err_inj_scenario_write,
	.release	= single_release,
};

static int ufsdbg_err_inj_stats_read(struct seq_file *file, void *data)
@@ -407,6 +414,7 @@ static const struct file_operations ufsdbg_err_inj_stats_ops = {
	.open		= ufsdbg_err_inj_stats_open,
	.read		= seq_read,
	.write		= ufsdbg_err_inj_stats_write,
	.release	= single_release,
};

static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
@@ -591,6 +599,7 @@ static const struct file_operations ufsdbg_tag_stats_fops = {
	.open		= ufsdbg_tag_stats_open,
	.read		= seq_read,
	.write		= ufsdbg_tag_stats_write,
	.release	= single_release,
};

static int ufsdbg_query_stats_show(struct seq_file *file, void *data)
@@ -662,6 +671,7 @@ static const struct file_operations ufsdbg_query_stats_fops = {
	.open		= ufsdbg_query_stats_open,
	.read		= seq_read,
	.write		= ufsdbg_query_stats_write,
	.release	= single_release,
};

static int ufsdbg_err_stats_show(struct seq_file *file, void *data)
@@ -766,6 +776,7 @@ static const struct file_operations ufsdbg_err_stats_fops = {
	.open		= ufsdbg_err_stats_open,
	.read		= seq_read,
	.write		= ufsdbg_err_stats_write,
	.release	= single_release,
};

static int ufshcd_init_statistics(struct ufs_hba *hba)
@@ -845,6 +856,7 @@ static int ufsdbg_host_regs_open(struct inode *inode, struct file *file)
static const struct file_operations ufsdbg_host_regs_fops = {
	.open		= ufsdbg_host_regs_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
@@ -881,7 +893,15 @@ static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
		{"bUD0BaseOffset",	0x1A, BYTE},
		{"bUDConfigPLength",	0x1B, BYTE},
		{"bDeviceRTTCap",	0x1C, BYTE},
		{"wPeriodicRTCUpdate",	0x1D, WORD}
		{"wPeriodicRTCUpdate",	0x1D, WORD},
		{"bUFSFeaturesSupport",	0x1F, BYTE},
		{"bFFUTimeout",	0x20, BYTE},
		{"bQueueDepth",	0x21, BYTE},
		{"wDeviceVersion",	0x22, WORD},
		{"bNumSecureWPArea",	0x24, BYTE},
		{"dPSAMaxDataSize",	0x25, DWORD},
		{"bPSAStateTimeout",	0x29, BYTE},
		{"iProductRevisionLevel",	0x2A, BYTE},
	};

	pm_runtime_get_sync(hba->dev);
@@ -906,6 +926,12 @@ static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
					   tmp->offset,
					   tmp->name,
					   *(u16 *)&desc_buf[tmp->offset]);
			} else if (tmp->width_byte == DWORD) {
				seq_printf(file,
					   "Device Descriptor[Byte offset 0x%x]: %s = 0x%x\n",
					   tmp->offset,
					   tmp->name,
					   *(u32 *)&desc_buf[tmp->offset]);
			} else {
				seq_printf(file,
				"Device Descriptor[offset 0x%x]: %s. Wrong Width = %d",
@@ -965,6 +991,7 @@ static int ufsdbg_show_hba_open(struct inode *inode, struct file *file)
static const struct file_operations ufsdbg_show_hba_fops = {
	.open		= ufsdbg_show_hba_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
@@ -976,6 +1003,143 @@ static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
static const struct file_operations ufsdbg_dump_device_desc = {
	.open		= ufsdbg_dump_device_desc_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufsdbg_dump_device_health_desc_show(struct seq_file *file, void *data)
{
	int err = 0;
	int buff_len = QUERY_DESC_DEVICE_HEALTH_MAX_SIZE;
	u8 desc_buf[QUERY_DESC_DEVICE_HEALTH_MAX_SIZE];
	struct ufs_hba *hba = (struct ufs_hba *)file->private;

	pm_runtime_get_sync(hba->dev);
	err = ufshcd_read_device_health_desc(hba, desc_buf, buff_len);
	pm_runtime_put_sync(hba->dev);

	if (!err) {
		int i;
		for (i = 0; i < QUERY_DESC_DEVICE_HEALTH_MAX_SIZE; ++i) {
			seq_printf(file, "%02x", desc_buf[i]);
		}
	} else {
		seq_printf(file, "Reading Device Health Descriptor failed. err = %d\n",
			   err);
	}

	return err;
}

static int ufsdbg_dump_device_health_desc_open(struct inode *inode, struct file *file)
{
	return single_open(file,
			   ufsdbg_dump_device_health_desc_show, inode->i_private);
}

static const struct file_operations ufsdbg_dump_device_health_desc = {
	.open		= ufsdbg_dump_device_health_desc_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufsdbg_dump_fw_revision_show(struct seq_file *file, void *data)
{
	int err = 0;
	u8 index;
	u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
	u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1];
	struct ufs_hba *hba = (struct ufs_hba *)file->private;

	pm_runtime_get_sync(hba->dev);
	err = ufshcd_read_device_desc(hba, desc_buf,
				QUERY_DESC_DEVICE_MAX_SIZE);
	if (err) {
		seq_printf(file, "Reading Device Descriptor failed. err = %d\n",
			err);
		goto out;
	}

	index = desc_buf[DEVICE_DESC_PARAM_PRODUCT_REVISION];
	memset(str_desc_buf, 0, QUERY_DESC_STRING_MAX_SIZE + 1);
	err = ufshcd_read_string_desc(hba, index, str_desc_buf,
				QUERY_DESC_STRING_MAX_SIZE, ASCII_STD);

	if (err) {
		seq_printf(file, "Reading String Descriptor failed. err = %d\n",
			err);
	} else {
		seq_printf(file, "FW revision = %s\n", &str_desc_buf[QUERY_DESC_HDR_SIZE]);
	}

out:
	pm_runtime_put_sync(hba->dev);
	return err;
}

static int ufsdbg_dump_fw_revision_open(struct inode *inode, struct file *file)
{
	return single_open(file,
			   ufsdbg_dump_fw_revision_show, inode->i_private);
}

static const struct file_operations ufsdbg_dump_fw_revision = {
	.open		= ufsdbg_dump_fw_revision_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufsdbg_dump_serial_show(struct seq_file *file, void *data)
{
	int err = 0;
	int i, len = 0;
	u8 index;
	u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
	u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE];
	struct ufs_hba *hba = (struct ufs_hba *)file->private;

	pm_runtime_get_sync(hba->dev);
	err = ufshcd_read_device_desc(hba, desc_buf,
				      QUERY_DESC_DEVICE_MAX_SIZE);
	if (err) {
		seq_printf(file, "Reading Device Descriptor failed. err = %d\n",
			   err);
		goto out;
	}

	index = desc_buf[DEVICE_DESC_PARAM_SN];
	memset(str_desc_buf, 0, QUERY_DESC_STRING_MAX_SIZE);

	err = ufshcd_read_string_desc(hba, index, str_desc_buf,
				      QUERY_DESC_STRING_MAX_SIZE, UTF16_STD);
	if (err) {
		seq_printf(file, "Reading String Descriptor failed. err = %d\n",
			   err);
		goto out;
	}

	len = (int)str_desc_buf[QUERY_DESC_LENGTH_OFFSET];
	if (len > QUERY_DESC_STRING_MAX_SIZE)
		len = QUERY_DESC_STRING_MAX_SIZE;

	seq_puts(file, "Serial = ");
	for (i = QUERY_DESC_HDR_SIZE; i < len; i++)
		seq_printf(file, "%02X", str_desc_buf[i]);
	seq_puts(file, "\n");
out:
	pm_runtime_put_sync(hba->dev);
	return err;
}

static int ufsdbg_dump_serial_open(struct inode *inode, struct file *file)
{
	return single_open(file,
			   ufsdbg_dump_serial_show, inode->i_private);
}

static const struct file_operations ufsdbg_dump_serial = {
	.open		= ufsdbg_dump_serial_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufsdbg_power_mode_show(struct seq_file *file, void *data)
@@ -1214,6 +1378,7 @@ static const struct file_operations ufsdbg_power_mode_desc = {
	.open		= ufsdbg_power_mode_open,
	.read		= seq_read,
	.write		= ufsdbg_power_mode_write,
	.release	= single_release,
};

static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer)
@@ -1393,6 +1558,7 @@ static const struct file_operations ufsdbg_req_stats_desc = {
	.open		= ufsdbg_req_stats_open,
	.read		= seq_read,
	.write		= ufsdbg_req_stats_write,
	.release	= single_release,
};


@@ -1441,6 +1607,7 @@ static const struct file_operations ufsdbg_reset_controller = {
	.open		= ufsdbg_reset_controller_open,
	.read		= seq_read,
	.write		= ufsdbg_reset_controller_write,
	.release	= single_release,
};

static int ufsdbg_clear_err_state(void *data, u64 val)
@@ -1649,6 +1816,36 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba)
		goto err;
	}

	hba->debugfs_files.dump_dev_health_desc =
		debugfs_create_file("dump_device_health_desc", S_IRUSR,
				    hba->debugfs_files.debugfs_root, hba,
				    &ufsdbg_dump_device_health_desc);
	if (!hba->debugfs_files.dump_dev_health_desc) {
		dev_err(hba->dev,
			"%s:  NULL dump_device_health_desc file, exiting", __func__);
		goto err;
	}

	hba->debugfs_files.fw_revision =
		debugfs_create_file("fw_revision", S_IRUSR,
				    hba->debugfs_files.debugfs_root, hba,
				    &ufsdbg_dump_fw_revision);
	if (!hba->debugfs_files.fw_revision) {
		dev_err(hba->dev,
			"%s:  NULL fw_revision file, exiting", __func__);
		goto err;
	}

	hba->debugfs_files.serial =
		debugfs_create_file("serial", S_IRUSR,
				    hba->debugfs_files.debugfs_root, hba,
				    &ufsdbg_dump_serial);
	if (!hba->debugfs_files.serial) {
		dev_err(hba->dev,
			"%s:  NULL serial file, exiting", __func__);
		goto err;
	}

	ufsdbg_setup_fault_injection(hba);

	ufshcd_vops_add_debugfs(hba, hba->debugfs_files.debugfs_root);
+3 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ static const struct file_operations ufs_qcom_dbg_testbus_cfg_desc = {
	.open		= ufs_qcom_dbg_testbus_cfg_open,
	.read		= seq_read,
	.write		= ufs_qcom_dbg_testbus_cfg_write,
	.release	= single_release,
};

static int ufs_qcom_dbg_testbus_bus_read(void *data, u64 *attr_val)
@@ -240,6 +241,7 @@ static int ufs_qcom_dbg_dbg_regs_open(struct inode *inode,
static const struct file_operations ufs_qcom_dbg_dbg_regs_desc = {
	.open		= ufs_qcom_dbg_dbg_regs_open,
	.read		= seq_read,
	.release	= single_release,
};

static int ufs_qcom_dbg_pm_qos_show(struct seq_file *file, void *data)
@@ -273,6 +275,7 @@ static int ufs_qcom_dbg_pm_qos_open(struct inode *inode,
static const struct file_operations ufs_qcom_dbg_pm_qos_desc = {
	.open		= ufs_qcom_dbg_pm_qos_open,
	.read		= seq_read,
	.release	= single_release,
};

void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root)
+16 −2
Original line number Diff line number Diff line
@@ -10,6 +10,11 @@
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include <linux/io.h>
#include <linux/of.h>
@@ -27,6 +32,8 @@

#define UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN	0

static struct workqueue_struct *ice_workqueue;

static void ufs_qcom_ice_dump_regs(struct ufs_qcom_host *qcom_host, int offset,
					int len, char *prefix)
{
@@ -224,6 +231,13 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host)
	}

	qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
	ice_workqueue = alloc_workqueue("ice-set-key",
			WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
	if (!ice_workqueue) {
		dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
			__func__);
		goto out;
	}
	INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);

out:
@@ -284,7 +298,7 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
				if (!qcom_host->work_pending) {
					qcom_host->req_pending = cmd->request;

					if (!schedule_work(
					if (!queue_work(ice_workqueue,
						&qcom_host->ice_cfg_work)) {
						qcom_host->req_pending = NULL;

@@ -404,7 +418,7 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
				if (!qcom_host->work_pending) {

					qcom_host->req_pending = cmd->request;
					if (!schedule_work(
					if (!queue_work(ice_workqueue,
						&qcom_host->ice_cfg_work)) {
						qcom_host->req_pending = NULL;

Loading