drivers/char/tpm/tpm-dev-common.c
Source file repositories/reference/linux-study-clean/drivers/char/tpm/tpm-dev-common.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/char/tpm/tpm-dev-common.c- Extension
.c- Size
- 7113 bytes
- Lines
- 291
- Domain
- Driver Families
- Bucket
- drivers/char
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/poll.hlinux/slab.hlinux/uaccess.hlinux/workqueue.htpm.htpm-dev.h
Detected Declarations
function tpm_dev_transmitfunction tpm_dev_async_workfunction user_reader_timeoutfunction tpm_timeout_workfunction tpm_common_openfunction tpm_common_readfunction tpm_common_writefunction tpm_common_pollfunction tpm_common_releasefunction tpm_dev_common_initfunction tpm_dev_common_exit
Annotated Snippet
if (ret_size <= 0) {
priv->response_length = 0;
goto out;
}
rc = copy_to_user(buf, priv->data_buffer + *off, ret_size);
if (rc) {
memset(priv->data_buffer, 0, TPM_BUFSIZE);
priv->response_length = 0;
ret_size = -EFAULT;
} else {
memset(priv->data_buffer + *off, 0, ret_size);
priv->response_length -= ret_size;
*off += ret_size;
}
}
out:
if (!priv->response_length) {
*off = 0;
timer_delete_sync(&priv->user_read_timer);
flush_work(&priv->timeout_work);
}
mutex_unlock(&priv->buffer_mutex);
return ret_size;
}
ssize_t tpm_common_write(struct file *file, const char __user *buf,
size_t size, loff_t *off)
{
struct file_priv *priv = file->private_data;
int ret = 0;
if (size > TPM_BUFSIZE)
return -E2BIG;
mutex_lock(&priv->buffer_mutex);
/* Cannot perform a write until the read has cleared either via
* tpm_read or a user_read_timer timeout. This also prevents split
* buffered writes from blocking here.
*/
if ((!priv->response_read && priv->response_length) ||
priv->command_enqueued) {
ret = -EBUSY;
goto out;
}
if (copy_from_user(priv->data_buffer, buf, size)) {
ret = -EFAULT;
goto out;
}
if (size < 6 ||
size < be32_to_cpu(*((__be32 *)(priv->data_buffer + 2)))) {
ret = -EINVAL;
goto out;
}
priv->response_length = 0;
priv->response_read = false;
*off = 0;
/*
* If in nonblocking mode schedule an async job to send
* the command return the size.
* In case of error the err code will be returned in
* the subsequent read call.
*/
if (file->f_flags & O_NONBLOCK) {
priv->command_enqueued = true;
queue_work(tpm_dev_wq, &priv->async_work);
mutex_unlock(&priv->buffer_mutex);
return size;
}
/* atomic tpm command send and result receive. We only hold the ops
* lock during this period so that the tpm can be unregistered even if
* the char dev is held open.
*/
if (tpm_try_get_ops(priv->chip)) {
ret = -EPIPE;
goto out;
}
ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
sizeof(priv->data_buffer));
tpm_put_ops(priv->chip);
if (ret > 0) {
Annotation
- Immediate include surface: `linux/poll.h`, `linux/slab.h`, `linux/uaccess.h`, `linux/workqueue.h`, `tpm.h`, `tpm-dev.h`.
- Detected declarations: `function tpm_dev_transmit`, `function tpm_dev_async_work`, `function user_reader_timeout`, `function tpm_timeout_work`, `function tpm_common_open`, `function tpm_common_read`, `function tpm_common_write`, `function tpm_common_poll`, `function tpm_common_release`, `function tpm_dev_common_init`.
- Atlas domain: Driver Families / drivers/char.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.