drivers/nvme/host/hwmon.c
Source file repositories/reference/linux-study-clean/drivers/nvme/host/hwmon.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/nvme/host/hwmon.c- Extension
.c- Size
- 6430 bytes
- Lines
- 282
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: implementation source
- Status
- source implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/hwmon.hlinux/units.hlinux/unaligned.hnvme.h
Detected Declarations
struct nvme_hwmon_datafunction nvme_get_temp_threshfunction nvme_set_temp_threshfunction nvme_hwmon_get_smart_logfunction nvme_hwmon_readfunction nvme_hwmon_writefunction nvme_hwmon_read_stringfunction nvme_hwmon_is_visiblefunction nvme_hwmon_initfunction nvme_hwmon_exit
Annotated Snippet
struct nvme_hwmon_data {
struct nvme_ctrl *ctrl;
struct nvme_smart_log *log;
struct mutex read_lock;
};
static int nvme_get_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under,
long *temp)
{
unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT;
u32 status;
int ret;
if (under)
threshold |= NVME_TEMP_THRESH_TYPE_UNDER;
ret = nvme_get_features(ctrl, NVME_FEAT_TEMP_THRESH, threshold, NULL, 0,
&status);
if (ret > 0)
return -EIO;
if (ret < 0)
return ret;
*temp = kelvin_to_millicelsius(status & NVME_TEMP_THRESH_MASK);
return 0;
}
static int nvme_set_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under,
long temp)
{
unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT;
int ret;
temp = millicelsius_to_kelvin(temp);
threshold |= clamp_val(temp, 0, NVME_TEMP_THRESH_MASK);
if (under)
threshold |= NVME_TEMP_THRESH_TYPE_UNDER;
ret = nvme_set_features(ctrl, NVME_FEAT_TEMP_THRESH, threshold, NULL, 0,
NULL);
if (ret > 0)
return -EIO;
return ret;
}
static int nvme_hwmon_get_smart_log(struct nvme_hwmon_data *data)
{
return nvme_get_log(data->ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0,
NVME_CSI_NVM, data->log, sizeof(*data->log), 0);
}
static int nvme_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct nvme_hwmon_data *data = dev_get_drvdata(dev);
struct nvme_smart_log *log = data->log;
int temp;
int err;
/*
* First handle attributes which don't require us to read
* the smart log.
*/
switch (attr) {
case hwmon_temp_max:
return nvme_get_temp_thresh(data->ctrl, channel, false, val);
case hwmon_temp_min:
return nvme_get_temp_thresh(data->ctrl, channel, true, val);
case hwmon_temp_crit:
*val = kelvin_to_millicelsius(data->ctrl->cctemp);
return 0;
default:
break;
}
mutex_lock(&data->read_lock);
err = nvme_hwmon_get_smart_log(data);
if (err)
goto unlock;
switch (attr) {
case hwmon_temp_input:
if (!channel)
temp = get_unaligned_le16(log->temperature);
else
temp = le16_to_cpu(log->temp_sensor[channel - 1]);
*val = kelvin_to_millicelsius(temp);
break;
Annotation
- Immediate include surface: `linux/hwmon.h`, `linux/units.h`, `linux/unaligned.h`, `nvme.h`.
- Detected declarations: `struct nvme_hwmon_data`, `function nvme_get_temp_thresh`, `function nvme_set_temp_thresh`, `function nvme_hwmon_get_smart_log`, `function nvme_hwmon_read`, `function nvme_hwmon_write`, `function nvme_hwmon_read_string`, `function nvme_hwmon_is_visible`, `function nvme_hwmon_init`, `function nvme_hwmon_exit`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: source implementation candidate.
- 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.