From patchwork Tue Apr 21 18:30:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarkko Sakkinen X-Patchwork-Id: 6252631 Return-Path: X-Original-To: patchwork-tpmdd-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 193A19F313 for ; Tue, 21 Apr 2015 18:31:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D29BF202F0 for ; Tue, 21 Apr 2015 18:31:24 +0000 (UTC) Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3D269202F8 for ; Tue, 21 Apr 2015 18:31:23 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1Ykcx7-00013G-Eb; Tue, 21 Apr 2015 18:31:21 +0000 Received: from sog-mx-3.v43.ch3.sourceforge.com ([172.29.43.193] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1Ykcx6-000137-CP for tpmdd-devel@lists.sourceforge.net; Tue, 21 Apr 2015 18:31:20 +0000 X-ACL-Warn: Received: from mga02.intel.com ([134.134.136.20]) by sog-mx-3.v43.ch3.sourceforge.com with esmtp (Exim 4.76) id 1Ykcx4-0001Km-BM for tpmdd-devel@lists.sourceforge.net; Tue, 21 Apr 2015 18:31:20 +0000 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga101.jf.intel.com with ESMTP; 21 Apr 2015 11:31:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,617,1422950400"; d="scan'208";a="713075971" Received: from tmaksymc-mobl2.ger.corp.intel.com (HELO localhost) ([10.252.3.161]) by fmsmga002.fm.intel.com with ESMTP; 21 Apr 2015 11:31:06 -0700 From: Jarkko Sakkinen To: peterhuewe@gmx.de, tpmdd-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org Date: Tue, 21 Apr 2015 21:30:55 +0300 Message-Id: <1429641062-14421-1-git-send-email-jarkko.sakkinen@linux.intel.com> X-Mailer: git-send-email 2.1.4 X-Spam-Score: -0.0 (/) X-Headers-End: 1Ykcx4-0001Km-BM Cc: Rasmus Villemoes , Simon Wunderlich , NeilBrown , Greg Kroah-Hartman , Jianyu Zhan , Andrzej Hajda , Al Viro , Tejun Heo , Andrew Morton , Guenter Roeck , "Eric W. Biederman" Subject: [tpmdd-devel] [PATCH v2] tpm: enable PPI for TPM 2.0 X-BeenThere: tpmdd-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Tpm Device Driver maintainance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: tpmdd-devel-bounces@lists.sourceforge.net X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, HK_RANDOM_ENVFROM, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Enabled PPI interface to the character device sysfs directory accessible both for 1.x and 2.0 devices. The ppi group is moved from the platform device directory to the character device directory. In order to retain backwards compatibility with the 1.x devices, a symlink is created to the platform device directory. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jason Gunthorpe --- drivers/char/tpm/tpm-chip.c | 21 +++++++++++++-------- drivers/char/tpm/tpm.h | 17 ++++++----------- drivers/char/tpm/tpm_ppi.c | 34 +++++++++++----------------------- fs/kernfs/dir.c | 1 + fs/sysfs/group.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 8 ++++++++ 6 files changed, 81 insertions(+), 42 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 283f00a..8a4cfdb 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "tpm.h" #include "tpm_eventlog.h" @@ -119,6 +120,9 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, chip->dev.class = tpm_class; chip->dev.release = tpm_dev_release; chip->dev.parent = chip->pdev; +#ifdef CONFIG_ACPI + chip->dev.groups = chip->groups; +#endif if (chip->dev_num == 0) chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); @@ -181,12 +185,6 @@ static int tpm1_chip_register(struct tpm_chip *chip) if (rc) return rc; - rc = tpm_add_ppi(chip); - if (rc) { - tpm_sysfs_del_device(chip); - return rc; - } - chip->bios_dir = tpm_bios_log_setup(chip->devname); return 0; @@ -200,8 +198,6 @@ static void tpm1_chip_unregister(struct tpm_chip *chip) if (chip->bios_dir) tpm_bios_log_teardown(chip->bios_dir); - tpm_remove_ppi(chip); - tpm_sysfs_del_device(chip); } @@ -224,10 +220,17 @@ int tpm_chip_register(struct tpm_chip *chip) if (rc) return rc; + tpm_add_ppi(chip); + rc = tpm_dev_add_device(chip); if (rc) goto out_err; + rc = sysfs_link_group_to_kobj(&chip->pdev->kobj, &chip->dev.kobj, + "ppi"); + if (rc) + goto out_err; + /* Make the chip available. */ spin_lock(&driver_lock); list_add_rcu(&chip->list, &tpm_chip_list); @@ -262,6 +265,8 @@ void tpm_chip_unregister(struct tpm_chip *chip) spin_unlock(&driver_lock); synchronize_rcu(); + kernfs_remove_by_name(chip->pdev->kobj.sd, "ppi"); + tpm1_chip_unregister(chip); tpm_dev_del_device(chip); } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f8319a0..3f96025 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -151,8 +151,7 @@ struct tpm_vendor_specific { enum tpm_chip_flags { TPM_CHIP_FLAG_REGISTERED = BIT(0), - TPM_CHIP_FLAG_PPI = BIT(1), - TPM_CHIP_FLAG_TPM2 = BIT(2), + TPM_CHIP_FLAG_TPM2 = BIT(1), }; struct tpm_chip { @@ -175,6 +174,8 @@ struct tpm_chip { struct dentry **bios_dir; #ifdef CONFIG_ACPI + const struct attribute_group *groups[2]; + unsigned int groups_cnt; acpi_handle acpi_dev_handle; char ppi_version[TPM_PPI_VERSION_LEN + 1]; #endif /* CONFIG_ACPI */ @@ -182,7 +183,7 @@ struct tpm_chip { struct list_head list; }; -#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) +#define to_tpm_chip(n) container_of(dev, struct tpm_chip, dev) static inline void tpm_chip_put(struct tpm_chip *chip) { @@ -412,15 +413,9 @@ void tpm_sysfs_del_device(struct tpm_chip *chip); int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); #ifdef CONFIG_ACPI -extern int tpm_add_ppi(struct tpm_chip *chip); -extern void tpm_remove_ppi(struct tpm_chip *chip); +extern void tpm_add_ppi(struct tpm_chip *chip); #else -static inline int tpm_add_ppi(struct tpm_chip *chip) -{ - return 0; -} - -static inline void tpm_remove_ppi(struct tpm_chip *chip) +static inline void tpm_add_ppi(struct tpm_chip *chip) { } #endif diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 6ca9b5d..692a2c6 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c @@ -53,7 +53,7 @@ tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type, static ssize_t tpm_show_ppi_version(struct device *dev, struct device_attribute *attr, char *buf) { - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version); } @@ -63,7 +63,7 @@ static ssize_t tpm_show_ppi_request(struct device *dev, { ssize_t size = -EINVAL; union acpi_object *obj; - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ, ACPI_TYPE_PACKAGE, NULL); @@ -100,7 +100,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, int func = TPM_PPI_FN_SUBREQ; union acpi_object *obj, tmp; union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); /* * the function to submit TPM operation request to pre-os environment @@ -156,7 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, .buffer.length = 0, .buffer.pointer = NULL }; - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); static char *info[] = { "None", @@ -197,7 +197,7 @@ static ssize_t tpm_show_ppi_response(struct device *dev, acpi_status status = -EINVAL; union acpi_object *obj, *ret_obj; u64 req, res; - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP, ACPI_TYPE_PACKAGE, NULL); @@ -296,7 +296,7 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev, struct device_attribute *attr, char *buf) { - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); return show_ppi_operations(chip->acpi_dev_handle, buf, 0, PPI_TPM_REQ_MAX); @@ -306,7 +306,7 @@ static ssize_t tpm_show_ppi_vs_operations(struct device *dev, struct device_attribute *attr, char *buf) { - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START, PPI_VS_REQ_END); @@ -334,17 +334,16 @@ static struct attribute_group ppi_attr_grp = { .attrs = ppi_attrs }; -int tpm_add_ppi(struct tpm_chip *chip) +void tpm_add_ppi(struct tpm_chip *chip) { union acpi_object *obj; - int rc; if (!chip->acpi_dev_handle) - return 0; + return; if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION)) - return 0; + return; /* Cache PPI version string. */ obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid, @@ -356,16 +355,5 @@ int tpm_add_ppi(struct tpm_chip *chip) ACPI_FREE(obj); } - rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp); - - if (!rc) - chip->flags |= TPM_CHIP_FLAG_PPI; - - return rc; -} - -void tpm_remove_ppi(struct tpm_chip *chip) -{ - if (chip->flags & TPM_CHIP_FLAG_PPI) - sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp); + chip->groups[chip->groups_cnt++] = &ppi_attr_grp; } diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 6acc964..749cea3 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -1225,6 +1225,7 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, else return -ENOENT; } +EXPORT_SYMBOL_GPL(kernfs_remove_by_name_ns); /** * kernfs_rename_ns - move and rename a kernfs_node diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index b400c04..25267d9 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -352,3 +352,45 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, } } EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group); + +/** + * sysfs_link_group_to_kobj - add a symlink to a kobject pointing to a group + * @kobj: The kobject containing the group. + * @target_kobj: The target kobject. + * @target_name: Name of the target group. + */ +int sysfs_link_group_to_kobj(struct kobject *kobj, struct kobject *target_kobj, + const char *target_name) +{ + struct kernfs_node *target_kobj_sd; + struct kernfs_node *target_grp; + struct kernfs_node *link; + + /* + * We don't own @target_kobj and it may be removed at any time. + * Synchronize using sysfs_symlink_target_lock. See sysfs_remove_dir() + * for details. + */ + spin_lock(&sysfs_symlink_target_lock); + target_kobj_sd = target_kobj->sd; + if (target_kobj_sd) + kernfs_get(target_kobj_sd); + spin_unlock(&sysfs_symlink_target_lock); + if (!target_kobj_sd) + return -ENOENT; + + target_grp = kernfs_find_and_get(target_kobj->sd, target_name); + if (!target_grp) { + kernfs_put(target_kobj_sd); + return -ENOENT; + } + + link = kernfs_create_link(kobj->sd, target_name, target_grp); + if (IS_ERR(link) && PTR_ERR(link) == -EEXIST) + sysfs_warn_dup(kobj->sd, target_name); + + kernfs_put(target_grp); + kernfs_put(target_kobj_sd); + return IS_ERR(link) ? PTR_ERR(link) : 0; +} +EXPORT_SYMBOL_GPL(sysfs_link_group_to_kobj); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 99382c0..7f2963e 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -264,6 +264,8 @@ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, struct kobject *target, const char *link_name); void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, const char *link_name); +int sysfs_link_group_to_kobj(struct kobject *kobj, struct kobject *target_kobj, + const char *target_name); void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr); @@ -436,6 +438,12 @@ static inline void sysfs_remove_link_from_group(struct kobject *kobj, { } +int sysfs_link_group_to_kobj(struct kobject *kobj, struct kobject *target_kobj, + const char *target_name) +{ + return 0; +} + static inline void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr) {