From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932828AbcAaCF7 (ORCPT ); Sat, 30 Jan 2016 21:05:59 -0500 Received: from mga04.intel.com ([192.55.52.120]:42827 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753256AbcAaCF5 (ORCPT ); Sat, 30 Jan 2016 21:05:57 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,372,1449561600"; d="scan'208";a="872965120" From: Jarkko Sakkinen To: Peter Huewe Cc: tpmdd-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, Jarkko Sakkinen , stable@vger.kernel.org Subject: [PATCH] tpm: fix rollback/cleanup before tpm_chip_register() Date: Sat, 30 Jan 2016 18:05:42 -0800 Message-Id: <1454205942-13033-1-git-send-email-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.7.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The release-callback is not used before the device is attached to the device hierarchy. This caused resources not to cleanup properly if the device driver initialization failed before tpm_chip_register(). This patch fixes the issue by adding the cleanup function to the devres list of the platform device in tpmm_chip_alloc(). Fixes: 313d21eeab ("tpm: device class for tpm") Signed-off-by: Jarkko Sakkinen cc: stable@vger.kernel.org --- drivers/char/tpm/tpm-chip.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 1a9dcee..cf2b351 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -75,16 +75,15 @@ static void tpm_dev_release(struct device *dev) } /** - * tpmm_chip_alloc() - allocate a new struct tpm_chip instance - * @dev: device to which the chip is associated + * tpmm_chip_alloc() - allocate and initialize a TPM chip + * @pdev: the platform device who is the parent of the chip * @ops: struct tpm_class_ops instance * - * Allocates a new struct tpm_chip instance and assigns a free - * device number for it. Caller does not have to worry about - * freeing the allocated resources. When the devices is removed - * devres calls tpmm_chip_remove() to do the job. + * Allocates a new struct tpm_chip instance, prepares the character device and + * assigns a free device number for it. The memory is freed automatically when + * the platform device is detached. */ -struct tpm_chip *tpmm_chip_alloc(struct device *dev, +struct tpm_chip *tpmm_chip_alloc(struct device *pdev, const struct tpm_class_ops *ops) { struct tpm_chip *chip; @@ -103,7 +102,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, spin_unlock(&driver_lock); if (chip->dev_num >= TPM_NUM_DEVICES) { - dev_err(dev, "No available tpm device numbers\n"); + dev_err(pdev, "No available tpm device numbers\n"); kfree(chip); return ERR_PTR(-ENOMEM); } @@ -112,9 +111,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); - chip->pdev = dev; - - dev_set_drvdata(dev, chip); + chip->pdev = pdev; chip->dev.class = tpm_class; chip->dev.release = tpm_dev_release; @@ -136,6 +133,12 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, chip->cdev.owner = chip->pdev->driver->owner; chip->cdev.kobj.parent = &chip->dev.kobj; + /* Associate character device with the platform device only after + * it is properly initialized. + */ + dev_set_drvdata(pdev, chip); + devm_add_action(pdev, (void (*)(void *)) tpm_dev_release, &chip->dev); + return chip; } EXPORT_SYMBOL_GPL(tpmm_chip_alloc); @@ -162,7 +165,10 @@ static int tpm_add_char_device(struct tpm_chip *chip) MINOR(chip->dev.devt), rc); cdev_del(&chip->cdev); - return rc; + } else { + devm_remove_action(chip->dev.parent, + (void (*)(void *)) tpm_dev_release, + &chip->dev); } return rc; @@ -202,15 +208,14 @@ static void tpm1_chip_unregister(struct tpm_chip *chip) } /* - * tpm_chip_register() - create a character device for the TPM chip - * @chip: TPM chip to use. + * tpm_chip_register() - add a TPM chip to the device hierarchy + * @chip: the TPM chip to be added * - * Creates a character device for the TPM chip and adds sysfs attributes for - * the device. As the last step this function adds the chip to the list of TPM - * chips available for in-kernel use. + * Adds a TPM chip to the device hierarchy and makes it available to for + * in-kernel use. * - * This function should be only called after the chip initialization is - * complete. + * This function should be called only after the device driver is otherwise + * initialized because it will become available for client access. */ int tpm_chip_register(struct tpm_chip *chip) { -- 2.7.0