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

Commit 0db51ef2 authored by James Morris's avatar James Morris
Browse files

Merge tag 'tpmdd-next-20181217' of git://git.infradead.org/users/jjs/linux-tpmdd into next-tpm

tpmdd updates for Linux v4.21

From Jarkko:

v4.21 updates:

* Support for partial reads of /dev/tpm0.
* Clean up for TPM 1.x code: move the commands to tpm1-cmd.c and make
  everything to use the same data structure for building TPM commands
  i.e. struct tpm_buf.
parents 8bd8ea19 9488585b
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -3,9 +3,19 @@
# Makefile for the kernel tpm device drivers.
#
obj-$(CONFIG_TCG_TPM) += tpm.o
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
	 tpm-dev-common.o tpmrm-dev.o eventlog/common.o eventlog/tpm1.o \
	 eventlog/tpm2.o tpm2-space.o
tpm-y := tpm-chip.o
tpm-y += tpm-dev-common.o
tpm-y += tpm-dev.o
tpm-y += tpm-interface.o
tpm-y += tpm1-cmd.o
tpm-y += tpm2-cmd.o
tpm-y += tpmrm-dev.o
tpm-y += tpm2-space.o
tpm-y += tpm-sysfs.o
tpm-y += eventlog/common.o
tpm-y += eventlog/tpm1.o
tpm-y += eventlog/tpm2.o

tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o
tpm-$(CONFIG_EFI) += eventlog/efi.o
tpm-$(CONFIG_OF) += eventlog/of.o
+1 −1
Original line number Diff line number Diff line
@@ -649,7 +649,7 @@ int st33zp24_pm_resume(struct device *dev)
	} else {
		ret = tpm_pm_resume(dev);
		if (!ret)
			tpm_do_selftest(chip);
			tpm1_do_selftest(chip);
	}
	return ret;
} /* st33zp24_pm_resume() */
+3 −8
Original line number Diff line number Diff line
@@ -451,14 +451,9 @@ int tpm_chip_register(struct tpm_chip *chip)
{
	int rc;

	if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
		if (chip->flags & TPM_CHIP_FLAG_TPM2)
			rc = tpm2_auto_startup(chip);
		else
			rc = tpm1_auto_startup(chip);
	rc = tpm_auto_startup(chip);
	if (rc)
		return rc;
	}

	tpm_sysfs_add_device(chip);

+36 −16
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ static void tpm_async_work(struct work_struct *work)

	tpm_put_ops(priv->chip);
	if (ret > 0) {
		priv->data_pending = ret;
		priv->response_length = ret;
		mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
	}
	mutex_unlock(&priv->buffer_mutex);
@@ -63,7 +63,8 @@ static void tpm_timeout_work(struct work_struct *work)
					      timeout_work);

	mutex_lock(&priv->buffer_mutex);
	priv->data_pending = 0;
	priv->response_read = true;
	priv->response_length = 0;
	memset(priv->data_buffer, 0, sizeof(priv->data_buffer));
	mutex_unlock(&priv->buffer_mutex);
	wake_up_interruptible(&priv->async_wait);
@@ -74,6 +75,7 @@ void tpm_common_open(struct file *file, struct tpm_chip *chip,
{
	priv->chip = chip;
	priv->space = space;
	priv->response_read = true;

	mutex_init(&priv->buffer_mutex);
	timer_setup(&priv->user_read_timer, user_reader_timeout, 0);
@@ -90,22 +92,35 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
	ssize_t ret_size = 0;
	int rc;

	del_singleshot_timer_sync(&priv->user_read_timer);
	flush_work(&priv->timeout_work);
	mutex_lock(&priv->buffer_mutex);

	if (priv->data_pending) {
		ret_size = min_t(ssize_t, size, priv->data_pending);
		if (ret_size > 0) {
			rc = copy_to_user(buf, priv->data_buffer, ret_size);
			memset(priv->data_buffer, 0, priv->data_pending);
			if (rc)
				ret_size = -EFAULT;
	if (priv->response_length) {
		priv->response_read = true;

		ret_size = min_t(ssize_t, size, priv->response_length);
		if (!ret_size) {
			priv->response_length = 0;
			goto out;
		}

		priv->data_pending = 0;
		rc = copy_to_user(buf, priv->data_buffer + *off, ret_size);
		if (rc) {
			memset(priv->data_buffer, 0, TPM_BUFSIZE);
			priv->response_length = 0;
			ret_size = -EFAULT;
		} else {
			memset(priv->data_buffer + *off, 0, ret_size);
			priv->response_length -= ret_size;
			*off += ret_size;
		}
	}

out:
	if (!priv->response_length) {
		*off = 0;
		del_singleshot_timer_sync(&priv->user_read_timer);
		flush_work(&priv->timeout_work);
	}
	mutex_unlock(&priv->buffer_mutex);
	return ret_size;
}
@@ -125,7 +140,8 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
	 * tpm_read or a user_read_timer timeout. This also prevents split
	 * buffered writes from blocking here.
	 */
	if (priv->data_pending != 0 || priv->command_enqueued) {
	if ((!priv->response_read && priv->response_length) ||
	    priv->command_enqueued) {
		ret = -EBUSY;
		goto out;
	}
@@ -150,6 +166,10 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
		goto out;
	}

	priv->response_length = 0;
	priv->response_read = false;
	*off = 0;

	/*
	 * If in nonblocking mode schedule an async job to send
	 * the command return the size.
@@ -168,7 +188,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
	tpm_put_ops(priv->chip);

	if (ret > 0) {
		priv->data_pending = ret;
		priv->response_length = ret;
		mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
		ret = size;
	}
@@ -184,7 +204,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)

	poll_wait(file, &priv->async_wait, wait);

	if (priv->data_pending)
	if (!priv->response_read || priv->response_length)
		mask = EPOLLIN | EPOLLRDNORM;
	else
		mask = EPOLLOUT | EPOLLWRNORM;
@@ -201,7 +221,7 @@ void tpm_common_release(struct file *file, struct file_priv *priv)
	del_singleshot_timer_sync(&priv->user_read_timer);
	flush_work(&priv->timeout_work);
	file->private_data = NULL;
	priv->data_pending = 0;
	priv->response_length = 0;
}

int __init tpm_dev_common_init(void)
+2 −3
Original line number Diff line number Diff line
@@ -9,14 +9,13 @@ struct file_priv {
	struct tpm_chip *chip;
	struct tpm_space *space;

	/* Holds the amount of data passed or an error code from async op */
	ssize_t data_pending;
	struct mutex buffer_mutex;

	struct timer_list user_read_timer;      /* user needs to claim result */
	struct work_struct timeout_work;
	struct work_struct async_work;
	wait_queue_head_t async_wait;
	size_t response_length;
	bool response_read;
	bool command_enqueued;

	u8 data_buffer[TPM_BUFSIZE];
Loading