Commit b61f7ff0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull tpm fixes from Jarkko Sakkinen:
 "A few bug fixes"

* tag 'tpmdd-next-20200421' of git://git.infradead.org/users/jjs/linux-tpmdd:
  tpm/tpm_tis: Free IRQ if probing fails
  tpm: fix wrong return value in tpm_pcr_extend
  tpm: ibmvtpm: retry on H_CLOSED in tpm_ibmvtpm_send()
  tpm: Export tpm2_get_cc_attrs_tbl for ibmvtpm driver as module
parents 20f16489 b160c94b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -323,7 +323,7 @@ int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,

	for (i = 0; i < chip->nr_allocated_banks; i++) {
		if (digests[i].alg_id != chip->allocated_banks[i].alg_id) {
			rc = EINVAL;
			rc = -EINVAL;
			goto out;
		}
	}
+1 −0
Original line number Diff line number Diff line
@@ -681,6 +681,7 @@ out:
		rc = -ENODEV;
	return rc;
}
EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl);

/**
 * tpm2_startup - turn on the TPM
+73 −63
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2012 IBM Corporation
 * Copyright (C) 2012-2020 IBM Corporation
 *
 * Author: Ashley Lai <ashleydlai@gmail.com>
 *
@@ -134,6 +134,64 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
	return len;
}

/**
 * ibmvtpm_crq_send_init - Send a CRQ initialize message
 * @ibmvtpm:	vtpm device struct
 *
 * Return:
 *	0 on success.
 *	Non-zero on failure.
 */
static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
{
	int rc;

	rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
	if (rc != H_SUCCESS)
		dev_err(ibmvtpm->dev,
			"%s failed rc=%d\n", __func__, rc);

	return rc;
}

/**
 * tpm_ibmvtpm_resume - Resume from suspend
 *
 * @dev:	device struct
 *
 * Return: Always 0.
 */
static int tpm_ibmvtpm_resume(struct device *dev)
{
	struct tpm_chip *chip = dev_get_drvdata(dev);
	struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
	int rc = 0;

	do {
		if (rc)
			msleep(100);
		rc = plpar_hcall_norets(H_ENABLE_CRQ,
					ibmvtpm->vdev->unit_address);
	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));

	if (rc) {
		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
		return rc;
	}

	rc = vio_enable_interrupts(ibmvtpm->vdev);
	if (rc) {
		dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
		return rc;
	}

	rc = ibmvtpm_crq_send_init(ibmvtpm);
	if (rc)
		dev_err(dev, "Error send_init rc=%d\n", rc);

	return rc;
}

/**
 * tpm_ibmvtpm_send() - Send a TPM command
 * @chip:	tpm chip struct
@@ -147,6 +205,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
	struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
	bool retry = true;
	int rc, sig;

	if (!ibmvtpm->rtce_buf) {
@@ -180,18 +239,27 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
	 */
	ibmvtpm->tpm_processing_cmd = true;

again:
	rc = ibmvtpm_send_crq(ibmvtpm->vdev,
			IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
			count, ibmvtpm->rtce_dma_handle);
	if (rc != H_SUCCESS) {
		/*
		 * H_CLOSED can be returned after LPM resume.  Call
		 * tpm_ibmvtpm_resume() to re-enable the CRQ then retry
		 * ibmvtpm_send_crq() once before failing.
		 */
		if (rc == H_CLOSED && retry) {
			tpm_ibmvtpm_resume(ibmvtpm->dev);
			retry = false;
			goto again;
		}
		dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
		rc = 0;
		ibmvtpm->tpm_processing_cmd = false;
	} else
		rc = 0;
	}

	spin_unlock(&ibmvtpm->rtce_lock);
	return rc;
	return 0;
}

static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
@@ -269,26 +337,6 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
	return rc;
}

/**
 * ibmvtpm_crq_send_init - Send a CRQ initialize message
 * @ibmvtpm:	vtpm device struct
 *
 * Return:
 *	0 on success.
 *	Non-zero on failure.
 */
static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
{
	int rc;

	rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
	if (rc != H_SUCCESS)
		dev_err(ibmvtpm->dev,
			"ibmvtpm_crq_send_init failed rc=%d\n", rc);

	return rc;
}

/**
 * tpm_ibmvtpm_remove - ibm vtpm remove entry point
 * @vdev:	vio device struct
@@ -401,44 +449,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
				  ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
}

/**
 * tpm_ibmvtpm_resume - Resume from suspend
 *
 * @dev:	device struct
 *
 * Return: Always 0.
 */
static int tpm_ibmvtpm_resume(struct device *dev)
{
	struct tpm_chip *chip = dev_get_drvdata(dev);
	struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
	int rc = 0;

	do {
		if (rc)
			msleep(100);
		rc = plpar_hcall_norets(H_ENABLE_CRQ,
					ibmvtpm->vdev->unit_address);
	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));

	if (rc) {
		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
		return rc;
	}

	rc = vio_enable_interrupts(ibmvtpm->vdev);
	if (rc) {
		dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
		return rc;
	}

	rc = ibmvtpm_crq_send_init(ibmvtpm);
	if (rc)
		dev_err(dev, "Error send_init rc=%d\n", rc);

	return rc;
}

static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
{
	return (status == 0);
+7 −1
Original line number Diff line number Diff line
@@ -433,6 +433,9 @@ static void disable_interrupts(struct tpm_chip *chip)
	u32 intmask;
	int rc;

	if (priv->irq == 0)
		return;

	rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
	if (rc < 0)
		intmask = 0;
@@ -1062,9 +1065,12 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
		if (irq) {
			tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
						 irq);
			if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
			if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
				dev_err(&chip->dev, FW_BUG
					"TPM interrupt not working, polling instead\n");

				disable_interrupts(chip);
			}
		} else {
			tpm_tis_probe_irq(chip, intmask);
		}