18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2004 IBM Corporation 48c2ecf20Sopenharmony_ci * Authors: 58c2ecf20Sopenharmony_ci * Leendert van Doorn <leendert@watson.ibm.com> 68c2ecf20Sopenharmony_ci * Dave Safford <safford@watson.ibm.com> 78c2ecf20Sopenharmony_ci * Reiner Sailer <sailer@watson.ibm.com> 88c2ecf20Sopenharmony_ci * Kylene Hall <kjhall@us.ibm.com> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 2013 Obsidian Research Corp 118c2ecf20Sopenharmony_ci * Jason Gunthorpe <jgunthorpe@obsidianresearch.com> 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Device file system interface to the TPM 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include "tpm-dev.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic int tpm_open(struct inode *inode, struct file *file) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci struct tpm_chip *chip; 218c2ecf20Sopenharmony_ci struct file_priv *priv; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci chip = container_of(inode->i_cdev, struct tpm_chip, cdev); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci /* It's assured that the chip will be opened just once, 268c2ecf20Sopenharmony_ci * by the check of is_open variable, which is protected 278c2ecf20Sopenharmony_ci * by driver_lock. */ 288c2ecf20Sopenharmony_ci if (test_and_set_bit(0, &chip->is_open)) { 298c2ecf20Sopenharmony_ci dev_dbg(&chip->dev, "Another process owns this TPM\n"); 308c2ecf20Sopenharmony_ci return -EBUSY; 318c2ecf20Sopenharmony_ci } 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci priv = kzalloc(sizeof(*priv), GFP_KERNEL); 348c2ecf20Sopenharmony_ci if (priv == NULL) 358c2ecf20Sopenharmony_ci goto out; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci tpm_common_open(file, chip, priv, NULL); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci out: 428c2ecf20Sopenharmony_ci clear_bit(0, &chip->is_open); 438c2ecf20Sopenharmony_ci return -ENOMEM; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * Called on file close 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_cistatic int tpm_release(struct inode *inode, struct file *file) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci struct file_priv *priv = file->private_data; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci tpm_common_release(file, priv); 548c2ecf20Sopenharmony_ci clear_bit(0, &priv->chip->is_open); 558c2ecf20Sopenharmony_ci kfree(priv); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci return 0; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ciconst struct file_operations tpm_fops = { 618c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 628c2ecf20Sopenharmony_ci .llseek = no_llseek, 638c2ecf20Sopenharmony_ci .open = tpm_open, 648c2ecf20Sopenharmony_ci .read = tpm_common_read, 658c2ecf20Sopenharmony_ci .write = tpm_common_write, 668c2ecf20Sopenharmony_ci .poll = tpm_common_poll, 678c2ecf20Sopenharmony_ci .release = tpm_release, 688c2ecf20Sopenharmony_ci}; 69