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

Commit 9335a12b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ufs: fixed bugs in ice related to key syncronization"

parents b184cdd6 d751a8d9
Loading
Loading
Loading
Loading
+71 −9
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
@@ -14,6 +14,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/blkdev.h>
#include <linux/spinlock.h>
#include <crypto/ice.h>

#include "ufs-qcom-ice.h"
@@ -168,6 +169,7 @@ out:

static void ufs_qcom_ice_cfg_work(struct work_struct *work)
{
	unsigned long flags;
	struct ice_data_setting ice_set;
	struct ufs_qcom_host *qcom_host =
		container_of(work, struct ufs_qcom_host, ice_cfg_work);
@@ -185,12 +187,17 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
	qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
		qcom_host->req_pending, &ice_set, false);

	spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
	qcom_host->req_pending = NULL;
	spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);

	/*
	 * Resume with requests processing. We assume config_start has been
	 * successful, but even if it wasn't we still must resume in order to
	 * allow for the request to be retried.
	 */
	ufshcd_scsi_unblock_requests(qcom_host->hba);

}

/**
@@ -246,6 +253,7 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
	struct ice_data_setting ice_set;
	char cmd_op = cmd->cmnd[0];
	int err;
	unsigned long flags;

	if (!qcom_host->ice.pdev || !qcom_host->ice.vops) {
		dev_dbg(qcom_host->hba->dev, "%s: ice device is not enabled\n",
@@ -272,11 +280,33 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
				dev_dbg(qcom_host->hba->dev,
					"%s: scheduling task for ice setup\n",
					__func__);
				qcom_host->req_pending = cmd->request;
				if (schedule_work(&qcom_host->ice_cfg_work))

				spin_lock_irqsave(
					&qcom_host->ice_work_lock, flags);

				if (!qcom_host->req_pending) {
					ufshcd_scsi_block_requests(
						qcom_host->hba);
					qcom_host->req_pending = cmd->request;
					if (!schedule_work(
						&qcom_host->ice_cfg_work)) {
						qcom_host->req_pending = NULL;

						spin_unlock_irqrestore(
						&qcom_host->ice_work_lock,
						flags);

						ufshcd_scsi_unblock_requests(
							qcom_host->hba);
						return err;
					}
				}

				spin_unlock_irqrestore(
					&qcom_host->ice_work_lock, flags);

			} else {
				if (err != -EBUSY)
					dev_err(qcom_host->hba->dev,
						"%s: error in ice_vops->config %d\n",
						__func__, err);
@@ -320,6 +350,7 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
	unsigned int bypass = 0;
	struct request *req;
	char cmd_op;
	unsigned long flags;

	if (!qcom_host->ice.pdev || !qcom_host->ice.vops) {
		dev_dbg(dev, "%s: ice device is not enabled\n", __func__);
@@ -365,12 +396,43 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
			 * request processing.
			 */
			if (err == -EAGAIN) {
				qcom_host->req_pending = req;
				if (schedule_work(&qcom_host->ice_cfg_work))

				dev_dbg(qcom_host->hba->dev,
					"%s: scheduling task for ice setup\n",
					__func__);

				spin_lock_irqsave(
					&qcom_host->ice_work_lock, flags);

				if (!qcom_host->req_pending) {
					ufshcd_scsi_block_requests(
						qcom_host->hba);
					qcom_host->req_pending = cmd->request;
					if (!schedule_work(
						&qcom_host->ice_cfg_work)) {
						qcom_host->req_pending = NULL;

						spin_unlock_irqrestore(
						&qcom_host->ice_work_lock,
						flags);

						ufshcd_scsi_unblock_requests(
							qcom_host->hba);
						return err;
					}
			goto out;
				}

				spin_unlock_irqrestore(
					&qcom_host->ice_work_lock, flags);

			} else {
				if (err != -EBUSY)
					dev_err(qcom_host->hba->dev,
						"%s: error in ice_vops->config %d\n",
						__func__, err);
			}

			return err;
		}
	}

+3 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2016, 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
@@ -1981,6 +1981,8 @@ static int ufs_qcom_init(struct ufs_hba *hba)

	/* Make a two way bind between the qcom host and the hba */
	host->hba = hba;
	spin_lock_init(&host->ice_work_lock);

	ufshcd_set_variant(hba, host);

	err = ufs_qcom_ice_get_dev(host);
+2 −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
@@ -370,6 +370,7 @@ struct ufs_qcom_host {
	u32 dbg_print_en;
	struct ufs_qcom_testbus testbus;

	spinlock_t ice_work_lock;
	struct work_struct ice_cfg_work;
	struct request *req_pending;
};
+6 −5
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
#include "ufshci.h"
#include "ufs_quirks.h"
#include "ufs-debugfs.h"
#include "ufs-qcom.h"

#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>
+43 −7
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-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
@@ -100,6 +100,9 @@ struct kc_entry {
	 struct task_struct *thread_pending;

	 enum pfk_kc_entry_state state;

	 /* ref count for the number of requests in the HW queue for this key */
	 int loaded_ref_cnt;
	 int scm_error;
};

@@ -520,6 +523,10 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
		if (entry_exists) {
			kc_update_timestamp(entry);
			entry->state = ACTIVE_ICE_LOADED;

			if (async)
				entry->loaded_ref_cnt++;

			break;
		}
	case (FREE):
@@ -529,8 +536,17 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
			entry->scm_error = ret;
			pr_err("%s: key load error (%d)\n", __func__, ret);
		} else {
			entry->state = ACTIVE_ICE_LOADED;
			kc_update_timestamp(entry);
			entry->state = ACTIVE_ICE_LOADED;

			/*
			 * only increase ref cnt for async calls,
			 * sync calls from within work thread do not pass
			 * requests further to HW
			 */
			if (async)
				entry->loaded_ref_cnt++;

		}
		break;
	case (ACTIVE_ICE_PRELOAD):
@@ -539,6 +555,10 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
		break;
	case (ACTIVE_ICE_LOADED):
		kc_update_timestamp(entry);

		if (async)
			entry->loaded_ref_cnt++;

		break;
	case(SCM_ERROR):
		ret = entry->scm_error;
@@ -572,6 +592,8 @@ void pfk_kc_load_key_end(const unsigned char *key, size_t key_size,
		const unsigned char *salt, size_t salt_size)
{
	struct kc_entry *entry = NULL;
	struct task_struct *tmp_pending = NULL;
	int ref_cnt = 0;

	if (!kc_is_ready())
		return;
@@ -591,14 +613,28 @@ void pfk_kc_load_key_end(const unsigned char *key, size_t key_size,
	if (!entry) {
		kc_spin_unlock();
		pr_err("internal error, there should an entry to unlock\n");

		return;
	}
	entry->state = INACTIVE;
	ref_cnt = --entry->loaded_ref_cnt;

	if (ref_cnt < 0)
		pr_err("internal error, ref count should never be negative\n");

	/* wake-up invalidation if it's waiting for the entry to be released */
	if (!ref_cnt) {
		entry->state = INACTIVE;
		/*
		 * wake-up invalidation if it's waiting
		 * for the entry to be released
		*/
		if (entry->thread_pending) {
		wake_up_process(entry->thread_pending);
			tmp_pending = entry->thread_pending;
			entry->thread_pending = NULL;

			kc_spin_unlock();
			wake_up_process(tmp_pending);
			return;
		}
	}

	kc_spin_unlock();