FAILED: patch "[PATCH] tpm: ibmvtpm: retry on H_CLOSED in tpm_ibmvtpm_send()" failed to apply to 4.9-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From eba5cf3dcb844c82f54d4a857e124824e252206d Mon Sep 17 00:00:00 2001
From: George Wilson <[email protected]>
Date: Thu, 19 Mar 2020 23:27:58 -0400
Subject: [PATCH] tpm: ibmvtpm: retry on H_CLOSED in tpm_ibmvtpm_send()
tpm_ibmvtpm_send() can fail during PowerVM Live Partition Mobility resume with an H_CLOSED return from ibmvtpm_send_crq(). The PAPR says, 'The "partner partition suspended" transport event disables the associated CRQ such that any H_SEND_CRQ hcall() to the associated CRQ returns H_Closed until the CRQ has been explicitly enabled using the H_ENABLE_CRQ hcall.' This patch adds a check in tpm_ibmvtpm_send() for an H_CLOSED return from ibmvtpm_send_crq() and in that case calls tpm_ibmvtpm_resume() and retries the ibmvtpm_send_crq() once.
drivers/char/tpm/tpm_ibmvtpm.c +73 -63
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0-only /* -* Copyright (C) 2012 IBM Corporation +* Copyright (C) 2012-2020 IBM Corporation * * Author: Ashley Lai <[email protected]> *
@@ -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 );