From cd459d788dca771882e88f03fb8265b34ac6d9f6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: May 09 2019 19:37:35 +0000 Subject: Add mutexes --- diff --git a/system76-io.c b/system76-io.c index ab26ddc..40b655f 100644 --- a/system76-io.c +++ b/system76-io.c @@ -55,32 +55,42 @@ static ssize_t show_bootloader(struct device *dev, struct device_attribute *attr } static ssize_t set_bootloader(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct io_dev * io_dev = dev_get_drvdata(dev); - unsigned int val; int ret; - ret = kstrtouint(buf, 10, &val); - if (ret) { - return ret; - } + struct io_dev * io_dev = dev_get_drvdata(dev); + + mutex_lock(&io_dev->lock); - if (val) { - ret = io_dev_bootloader(io_dev, IO_TIMEOUT); - if(ret) { - return ret; + ret = kstrtouint(buf, 10, &val); + if (!ret) { + if (val) { + ret = io_dev_bootloader(io_dev, IO_TIMEOUT); + if(!ret) { + ret = size; + } } } - return size; + mutex_unlock(&io_dev->lock); + + return ret; } static DEVICE_ATTR(bootloader, S_IRUGO | S_IWUSR, show_bootloader, set_bootloader); static ssize_t show_revision(struct device *dev, struct device_attribute *attr, char *buf) { + int ret; + struct io_dev * io_dev = dev_get_drvdata(dev); - return io_dev_revision(io_dev, buf, PAGE_SIZE, IO_TIMEOUT); + mutex_lock(&io_dev->lock); + + ret = io_dev_revision(io_dev, buf, PAGE_SIZE, IO_TIMEOUT); + + mutex_unlock(&io_dev->lock); + + return ret; } static DEVICE_ATTR(revision, S_IRUGO, show_revision, NULL); @@ -89,6 +99,8 @@ static DEVICE_ATTR(revision, S_IRUGO, show_revision, NULL); static int io_pm(struct notifier_block *nb, unsigned long action, void *data) { struct io_dev * io_dev = container_of(nb, struct io_dev, pm_notifier); + mutex_lock(&io_dev->lock); + switch (action) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: @@ -106,6 +118,8 @@ static int io_pm(struct notifier_block *nb, unsigned long action, void *data) { break; } + mutex_unlock(&io_dev->lock); + return NOTIFY_DONE; } #endif @@ -161,6 +175,10 @@ static int io_probe(struct usb_interface *interface, const struct usb_device_id memset(io_dev, 0, sizeof(struct io_dev)); + mutex_init(&io_dev->lock); + + mutex_lock(&io_dev->lock); + io_dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); usb_set_intfdata(interface, io_dev); @@ -202,6 +220,8 @@ static int io_probe(struct usb_interface *interface, const struct usb_device_id register_pm_notifier(&io_dev->pm_notifier); #endif + mutex_unlock(&io_dev->lock); + return 0; fail3: @@ -211,7 +231,12 @@ static int io_probe(struct usb_interface *interface, const struct usb_device_id fail1: usb_set_intfdata(interface, NULL); usb_put_dev(io_dev->usb_dev); + + mutex_unlock(&io_dev->lock); + + mutex_destroy(&io_dev->lock); kfree(io_dev); + return result; } else { return -ENODEV; @@ -226,6 +251,8 @@ static void io_disconnect(struct usb_interface *interface) { io_dev = usb_get_intfdata(interface); if (io_dev) { + mutex_lock(&io_dev->lock); + #ifdef CONFIG_PM_SLEEP unregister_pm_notifier(&io_dev->pm_notifier); #endif @@ -237,9 +264,11 @@ static void io_disconnect(struct usb_interface *interface) { device_remove_file(&interface->dev, &dev_attr_bootloader); usb_set_intfdata(interface, NULL); - usb_put_dev(io_dev->usb_dev); + mutex_unlock(&io_dev->lock); + + mutex_destroy(&io_dev->lock); kfree(io_dev); } } diff --git a/system76-io_dev.c b/system76-io_dev.c index 0056ab2..8356dff 100644 --- a/system76-io_dev.c +++ b/system76-io_dev.c @@ -18,6 +18,7 @@ */ struct io_dev { + struct mutex lock; struct usb_device * usb_dev; struct device * hwmon_dev; #ifdef CONFIG_PM_SLEEP diff --git a/system76-io_hwmon.c b/system76-io_hwmon.c index 8aed46d..00b8032 100644 --- a/system76-io_hwmon.c +++ b/system76-io_hwmon.c @@ -37,104 +37,125 @@ static const char * io_fan_name(int index) { static ssize_t io_fan_input_show(struct device *dev, struct device_attribute *attr, char *buf) { u16 value; - int result; + int ret; struct io_dev * io_dev = dev_get_drvdata(dev); + + mutex_lock(&io_dev->lock); + const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); if (name) { - result = io_dev_tach(io_dev, name, &value, IO_TIMEOUT); - if (result) { - return result; + ret = io_dev_tach(io_dev, name, &value, IO_TIMEOUT); + if (!ret) { + ret = sprintf(buf, "%i\n", value * 30); } - - return sprintf(buf, "%i\n", value * 30); } else { - return -ENOENT; + ret = -ENOENT; } + + mutex_unlock(&io_dev->lock); + + return ret; } static ssize_t io_fan_label_show(struct device *dev, struct device_attribute *attr, char *buf) { + int ret; + const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); if (name) { - return sprintf(buf, "%s\n", name); + ret = sprintf(buf, "%s\n", name); } else { - return -ENOENT; + ret = -ENOENT; } + + return ret; } static ssize_t io_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) { u16 value; - int result; + int ret; struct io_dev * io_dev = dev_get_drvdata(dev); + + mutex_lock(&io_dev->lock); + const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); if (name) { - result = io_dev_duty(io_dev, name, &value, IO_TIMEOUT); - if (result) { - return result; + ret = io_dev_duty(io_dev, name, &value, IO_TIMEOUT); + if (!ret) { + ret = sprintf(buf, "%i\n", (((u32)value) * 255) / 10000); } - - return sprintf(buf, "%i\n", (((u32)value) * 255) / 10000); } else { - return -ENOENT; + ret = -ENOENT; } + + mutex_unlock(&io_dev->lock); + + return ret; } static ssize_t io_pwm_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - u32 value; - int result; + u32 value; + int ret; struct io_dev * io_dev = dev_get_drvdata(dev); - const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); - if (name) { - result = kstrtou32(buf, 10, &value); - if (result) { - return result; - } - if (value > 255) { - return -EINVAL; - } + mutex_lock(&io_dev->lock); - result = io_dev_set_duty(io_dev, name, (u16)((value * 10000) / 255), IO_TIMEOUT); - if (result) { - return result; + const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); + if (name) { + ret = kstrtou32(buf, 10, &value); + if (!ret) { + if (value <= 255) { + ret = io_dev_set_duty(io_dev, name, (u16)((value * 10000) / 255), IO_TIMEOUT); + if (!ret) { + ret = count; + } + } else { + ret = -EINVAL; + } } - - return count; } else { - return -ENOENT; + ret = -ENOENT; } + + mutex_unlock(&io_dev->lock); + + return ret; } static ssize_t io_pwm_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { + int ret; + const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); if (name) { - return sprintf(buf, "%i\n", 1); + ret = sprintf(buf, "%i\n", 1); } else { - return -ENOENT; + ret = -ENOENT; } + + return ret; } static ssize_t io_pwm_enable_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - u8 value; - int result; + u8 value; + int ret; const char * name = io_fan_name(to_sensor_dev_attr(attr)->index); if (name) { - result = kstrtou8(buf, 10, &value); - if (result) { - return result; - } - - if (value == 1) { - return count; - } else { - return -EINVAL; + ret = kstrtou8(buf, 10, &value); + if (!ret) { + if (value == 1) { + ret = count; + } else { + ret = -EINVAL; + } } } else { - return -ENOENT; + ret = -ENOENT; } + + return ret; } #undef IO_FAN