diff --git a/src/06-mini-project/kernel/regulator/regulator.c b/src/06-mini-project/kernel/regulator/regulator.c index f677a2e..e71be2a 100644 --- a/src/06-mini-project/kernel/regulator/regulator.c +++ b/src/06-mini-project/kernel/regulator/regulator.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "regulator.h" #include "../sysfs/sysfs.h" @@ -14,6 +15,7 @@ static uint32_t current_period = 1000; /* Current blinking period in ms */ static struct task_struct *regulator_thread = NULL; static struct regulator_callbacks regulator_cbs = {0}; +static DEFINE_MUTEX(regulator_lock); /* --- Sysfs Callbacks --- */ @@ -22,22 +24,33 @@ static uint32_t cb_get_temperature(void) { } static int cb_get_mode(void) { - return current_mode; + int mode; + mutex_lock(®ulator_lock); + mode = current_mode; + mutex_unlock(®ulator_lock); + return mode; } static void cb_set_mode(int mode) { /* Accept only 0 or 1 as valid modes */ if (mode == 0 || mode == 1) { + mutex_lock(®ulator_lock); current_mode = mode; + mutex_unlock(®ulator_lock); pr_info("regulator: Mode switched to %s\n", mode ? "Auto" : "Manual"); } } static uint32_t cb_get_period(void) { - return current_period; + uint32_t period; + mutex_lock(®ulator_lock); + period = current_period; + mutex_unlock(®ulator_lock); + return period; } static void cb_set_period(uint32_t period_ms) { + mutex_lock(®ulator_lock); /* Allow period changes only in Manual mode */ if (current_mode == 0) { if (period_ms > 0) { @@ -51,6 +64,7 @@ static void cb_set_period(uint32_t period_ms) { } else { pr_warn("regulator: Cannot set period manually in auto mode\n"); } + mutex_unlock(®ulator_lock); } /* Pack callbacks into the structure expected by sysfs */ @@ -80,6 +94,7 @@ static void process_auto_mode(void) { new_period = 50; } + mutex_lock(®ulator_lock); /* Apply only if the period has changed to avoid unnecessary hardware updates */ if (new_period != current_period) { current_period = new_period; @@ -87,12 +102,19 @@ static void process_auto_mode(void) { pr_info("regulator: Auto mode adjusted period to %u ms (Temp: %u C)\n", current_period, temp_c); } + mutex_unlock(®ulator_lock); } /* Background thread checking the temperature periodically */ static int regulator_thread_fn(void *data) { while (!kthread_should_stop()) { - if (current_mode == 1) { + int mode; + + mutex_lock(®ulator_lock); + mode = current_mode; + mutex_unlock(®ulator_lock); + + if (mode == 1) { process_auto_mode(); } msleep(1000); diff --git a/src/06-mini-project/kernel/sysfs/sysfs.c b/src/06-mini-project/kernel/sysfs/sysfs.c index 9ae03d0..28878fc 100644 --- a/src/06-mini-project/kernel/sysfs/sysfs.c +++ b/src/06-mini-project/kernel/sysfs/sysfs.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "sysfs.h" @@ -13,14 +14,17 @@ static struct device *sysfs_device = NULL; /* Global static structure to hold the registered callbacks */ static struct sysfs_callbacks device_cbs = {0}; +static DEFINE_MUTEX(sysfs_lock); /* Callback triggered on sysfs temperature file read */ static ssize_t temperature_show(struct device *dev, struct device_attribute *attr, char *buf) { uint32_t temp = 0; + mutex_lock(&sysfs_lock); if (device_cbs.get_temperature) { temp = device_cbs.get_temperature(); } + mutex_unlock(&sysfs_lock); /* Format the temperature and write it to the buffer */ return snprintf(buf, PAGE_SIZE, "%u.%03u\n", temp / 1000, temp % 1000); @@ -30,9 +34,11 @@ static ssize_t temperature_show(struct device *dev, struct device_attribute *att static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { int mode = 0; + mutex_lock(&sysfs_lock); if (device_cbs.get_mode) { mode = device_cbs.get_mode(); } + mutex_unlock(&sysfs_lock); return snprintf(buf, PAGE_SIZE, "%d\n", mode); } @@ -43,9 +49,11 @@ static ssize_t mode_store(struct device *dev, struct device_attribute *attr, con /* Safely convert string from user space to integer */ if (kstrtoint(buf, 10, &mode) == 0) { + mutex_lock(&sysfs_lock); if (device_cbs.set_mode) { device_cbs.set_mode(mode); } + mutex_unlock(&sysfs_lock); } return count; @@ -55,9 +63,11 @@ static ssize_t mode_store(struct device *dev, struct device_attribute *attr, con static ssize_t period_status_show(struct device *dev, struct device_attribute *attr, char *buf) { uint32_t period = 0; + mutex_lock(&sysfs_lock); if (device_cbs.get_period) { period = device_cbs.get_period(); } + mutex_unlock(&sysfs_lock); return snprintf(buf, PAGE_SIZE, "%u\n", period); } @@ -67,9 +77,11 @@ static ssize_t period_set_store(struct device *dev, struct device_attribute *att uint32_t period; if (kstrtouint(buf, 10, &period) == 0) { + mutex_lock(&sysfs_lock); if (device_cbs.set_period) { device_cbs.set_period(period); } + mutex_unlock(&sysfs_lock); } return count; @@ -97,10 +109,12 @@ static const struct attribute_group regulator_group = { int temp_regulator_sysfs_init(struct sysfs_callbacks *cbs) { int ret; + mutex_lock(&sysfs_lock); /* Save the callbacks provided by the main module */ if (cbs) { device_cbs = *cbs; } + mutex_unlock(&sysfs_lock); /* Create sysfs class */ sysfs_class = class_create(THIS_MODULE, "temp_regulator"); diff --git a/src/06-mini-project/kernel/temperature/temp.c b/src/06-mini-project/kernel/temperature/temp.c index 9f75492..4b0c42a 100644 --- a/src/06-mini-project/kernel/temperature/temp.c +++ b/src/06-mini-project/kernel/temperature/temp.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "temp.h" @@ -13,8 +14,11 @@ static struct resource *temp_res = NULL; static void __iomem *temp_reg = NULL; +static DEFINE_MUTEX(temp_lock); int temp_init(void) { + mutex_lock(&temp_lock); + /* Request physical memory region */ temp_res = request_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, TEMPERATURE_SENSOR_REG_SIZE, @@ -28,12 +32,17 @@ int temp_init(void) { if (temp_reg == NULL) { pr_err("temp_regulator: Failed to ioremap registers\n"); /* Clean up previously requested region */ - release_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, TEMPERATURE_SENSOR_REG_SIZE); - temp_res = NULL; + if (temp_res) { + release_mem_region(TEMPERATURE_SENSOR_BASE_ADDR, TEMPERATURE_SENSOR_REG_SIZE); + temp_res = NULL; + } + mutex_unlock(&temp_lock); return -ENOMEM; } pr_info("temp_regulator: Temperature sensor memory successfully mapped\n"); + + mutex_unlock(&temp_lock); return 0; } @@ -41,8 +50,11 @@ uint32_t read_temp(void) { uint32_t temperature = 0; uint32_t raw_val = 0; + mutex_lock(&temp_lock); + if (temp_reg == NULL) { pr_warn("temp_regulator: Cannot read temperature, sensor not initialized\n"); + mutex_unlock(&temp_lock); return 0; } @@ -58,10 +70,13 @@ uint32_t read_temp(void) { temperature = -1452 * (int32_t)raw_val / 10 + 259000; } + mutex_unlock(&temp_lock); return temperature; } void temp_exit(void) { + mutex_lock(&temp_lock); + /* Unmap virtual address space */ if (temp_reg != NULL) { iounmap(temp_reg); @@ -74,5 +89,7 @@ void temp_exit(void) { temp_res = NULL; } + mutex_unlock(&temp_lock); + pr_info("temp_regulator: Temperature sensor resources released\n"); }