Commit 85d678c0 authored by Bryan O'Donoghue's avatar Bryan O'Donoghue Committed by Greg Kroah-Hartman

greybus: loopback: make loopback code thread safe

Current code allows a sysfs callback and a kernel worker thread to write
all over and act upon data that could be in the process of being updated by
the other. This patch adds a reasonably coarse mutex to enscure sync
between the two.
Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent a7e60062
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -30,6 +31,7 @@ struct gb_loopback { ...@@ -30,6 +31,7 @@ struct gb_loopback {
u8 version_major; u8 version_major;
u8 version_minor; u8 version_minor;
struct mutex mutex;
struct task_struct *task; struct task_struct *task;
wait_queue_head_t wq; wait_queue_head_t wq;
...@@ -101,10 +103,13 @@ static ssize_t field##_store(struct device *dev, \ ...@@ -101,10 +103,13 @@ static ssize_t field##_store(struct device *dev, \
struct gb_connection *connection = to_gb_connection(dev); \ struct gb_connection *connection = to_gb_connection(dev); \
struct gb_loopback *gb = \ struct gb_loopback *gb = \
(struct gb_loopback *)connection->private; \ (struct gb_loopback *)connection->private; \
mutex_lock(&gb->mutex); \
ret = sscanf(buf, "%"#type, &gb->field); \ ret = sscanf(buf, "%"#type, &gb->field); \
if (ret != 1) \ if (ret != 1) \
return -EINVAL; \ len = -EINVAL; \
else \
gb_loopback_check_attr(gb); \ gb_loopback_check_attr(gb); \
mutex_unlock(&gb->mutex); \
return len; \ return len; \
} \ } \
static DEVICE_ATTR_RW(field) static DEVICE_ATTR_RW(field)
...@@ -385,6 +390,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) ...@@ -385,6 +390,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb)
static int gb_loopback_fn(void *data) static int gb_loopback_fn(void *data)
{ {
int error = 0; int error = 0;
int ms_wait;
struct gb_loopback *gb = (struct gb_loopback *)data; struct gb_loopback *gb = (struct gb_loopback *)data;
while (1) { while (1) {
...@@ -393,6 +399,8 @@ static int gb_loopback_fn(void *data) ...@@ -393,6 +399,8 @@ static int gb_loopback_fn(void *data)
kthread_should_stop()); kthread_should_stop());
if (kthread_should_stop()) if (kthread_should_stop())
break; break;
mutex_lock(&gb->mutex);
if (gb->iteration_max) { if (gb->iteration_max) {
if (gb->iteration_count < gb->iteration_max) { if (gb->iteration_count < gb->iteration_max) {
gb->iteration_count++; gb->iteration_count++;
...@@ -400,6 +408,7 @@ static int gb_loopback_fn(void *data) ...@@ -400,6 +408,7 @@ static int gb_loopback_fn(void *data)
"iteration_count"); "iteration_count");
} else { } else {
gb->type = 0; gb->type = 0;
mutex_unlock(&gb->mutex);
continue; continue;
} }
} }
...@@ -412,8 +421,10 @@ static int gb_loopback_fn(void *data) ...@@ -412,8 +421,10 @@ static int gb_loopback_fn(void *data)
if (error) if (error)
gb->error++; gb->error++;
gb_loopback_calculate_stats(gb); gb_loopback_calculate_stats(gb);
if (gb->ms_wait) ms_wait = gb->ms_wait;
msleep(gb->ms_wait); mutex_unlock(&gb->mutex);
if (ms_wait)
msleep(ms_wait);
} }
return 0; return 0;
} }
...@@ -448,6 +459,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) ...@@ -448,6 +459,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
gb_loopback_reset_stats(gb); gb_loopback_reset_stats(gb);
init_waitqueue_head(&gb->wq); init_waitqueue_head(&gb->wq);
mutex_init(&gb->mutex);
gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback");
if (IS_ERR(gb->task)) { if (IS_ERR(gb->task)) {
retval = PTR_ERR(gb->task); retval = PTR_ERR(gb->task);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment