Home Home > GIT Browse > openSUSE-15.0
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKernel Build Daemon <kbuild@suse.de>2018-07-12 07:07:35 +0200
committerKernel Build Daemon <kbuild@suse.de>2018-07-12 07:07:35 +0200
commit12e3ca560ff1be8a727e3108491aaa5fc0c1afa3 (patch)
tree3594b65960f24d54eb3a90beeb0110f70494d245
parent97fb25408f39eb3845b66e811f5c1bbe0e64bfde (diff)
parent816c6084089006ba90934ff6ef1294e1346f162f (diff)
Merge branch 'SLE15' into openSUSE-15.0
-rw-r--r--drivers/hid/hid-debug.c8
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c2
-rw-r--r--drivers/hid/usbhid/hiddev.c11
-rw-r--r--drivers/hid/wacom_wac.c10
-rw-r--r--drivers/watchdog/da9063_wdt.c63
5 files changed, 86 insertions, 8 deletions
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 5271db593478..ae8c8e66a6c4 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -1154,6 +1154,8 @@ copy_rest:
goto out;
if (list->tail > list->head) {
len = list->tail - list->head;
+ if (len > count)
+ len = count;
if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
ret = -EFAULT;
@@ -1163,6 +1165,8 @@ copy_rest:
list->head += len;
} else {
len = HID_DEBUG_BUFSIZE - list->head;
+ if (len > count)
+ len = count;
if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
ret = -EFAULT;
@@ -1170,7 +1174,9 @@ copy_rest:
}
list->head = 0;
ret += len;
- goto copy_rest;
+ count -= len;
+ if (count > 0)
+ goto copy_rest;
}
}
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 7cc367d6e1b1..1c28847dcca1 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -476,7 +476,7 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
return;
}
- if ((ret_size > size) || (ret_size <= 2)) {
+ if ((ret_size > size) || (ret_size < 2)) {
dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
__func__, size, ret_size);
return;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 0e06368d1fbb..e9931cc452ad 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -36,6 +36,7 @@
#include <linux/hiddev.h>
#include <linux/compat.h>
#include <linux/vmalloc.h>
+#include <linux/nospec.h>
#include "usbhid.h"
#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -469,10 +470,14 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
if (uref->field_index >= report->maxfield)
goto inval;
+ uref->field_index = array_index_nospec(uref->field_index,
+ report->maxfield);
field = report->field[uref->field_index];
if (uref->usage_index >= field->maxusage)
goto inval;
+ uref->usage_index = array_index_nospec(uref->usage_index,
+ field->maxusage);
uref->usage_code = field->usage[uref->usage_index].hid;
@@ -499,6 +504,8 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
if (uref->field_index >= report->maxfield)
goto inval;
+ uref->field_index = array_index_nospec(uref->field_index,
+ report->maxfield);
field = report->field[uref->field_index];
@@ -753,6 +760,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (finfo.field_index >= report->maxfield)
break;
+ finfo.field_index = array_index_nospec(finfo.field_index,
+ report->maxfield);
field = report->field[finfo.field_index];
memset(&finfo, 0, sizeof(finfo));
@@ -797,6 +806,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (cinfo.index >= hid->maxcollection)
break;
+ cinfo.index = array_index_nospec(cinfo.index,
+ hid->maxcollection);
cinfo.type = hid->collection[cinfo.index].type;
cinfo.usage = hid->collection[cinfo.index].usage;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index a165f2f79f3d..fee11cf9a871 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3172,8 +3172,14 @@ void wacom_setup_device_quirks(struct wacom *wacom)
if (features->type >= INTUOSHT && features->type <= BAMBOO_PT)
features->device_type |= WACOM_DEVICETYPE_PAD;
- features->x_max = 4096;
- features->y_max = 4096;
+ if (features->type == INTUOSHT2) {
+ features->x_max = features->x_max / 10;
+ features->y_max = features->y_max / 10;
+ }
+ else {
+ features->x_max = 4096;
+ features->y_max = 4096;
+ }
}
else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) {
features->device_type |= WACOM_DEVICETYPE_PAD;
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
index 4691c5509129..99997777c2d0 100644
--- a/drivers/watchdog/da9063_wdt.c
+++ b/drivers/watchdog/da9063_wdt.c
@@ -53,8 +53,43 @@ static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
return DA9063_TWDSCALE_MAX;
}
+/*
+ * Return 0 if watchdog is disabled, else non zero.
+ */
+static unsigned int da9063_wdt_is_running(struct da9063 *da9063)
+{
+ unsigned int val;
+
+ regmap_read(da9063->regmap, DA9063_REG_CONTROL_D, &val);
+
+ return val & DA9063_TWDSCALE_MASK;
+}
+
+static int da9063_wdt_disable_timer(struct da9063 *da9063)
+{
+ return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
+ DA9063_TWDSCALE_MASK,
+ DA9063_TWDSCALE_DISABLE);
+}
+
static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
{
+ int ret;
+
+ /*
+ * The watchdog triggers a reboot if a timeout value is already
+ * programmed because the timeout value combines two functions
+ * in one: indicating the counter limit and starting the watchdog.
+ * The watchdog must be disabled to be able to change the timeout
+ * value if the watchdog is already running. Then we can set the
+ * new timeout value which enables the watchdog again.
+ */
+ ret = da9063_wdt_disable_timer(da9063);
+ if (ret)
+ return ret;
+
+ usleep_range(150, 300);
+
return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
DA9063_TWDSCALE_MASK, regval);
}
@@ -79,8 +114,7 @@ static int da9063_wdt_stop(struct watchdog_device *wdd)
struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
int ret;
- ret = regmap_update_bits(wdt->da9063->regmap, DA9063_REG_CONTROL_D,
- DA9063_TWDSCALE_MASK, DA9063_TWDSCALE_DISABLE);
+ ret = da9063_wdt_disable_timer(da9063);
if (ret)
dev_alert(wdt->da9063->dev, "Watchdog failed to stop (err = %d)\n",
ret);
@@ -107,10 +141,23 @@ static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
{
struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
unsigned int selector;
- int ret;
+ int ret = 0;
selector = da9063_wdt_timeout_to_sel(timeout);
- ret = _da9063_wdt_set_timeout(wdt->da9063, selector);
+
+ /*
+ * There are two cases when a set_timeout() will be called:
+ * 1. The watchdog is off and someone wants to set the timeout for the
+ * further use.
+ * 2. The watchdog is already running and a new timeout value should be
+ * set.
+ *
+ * The watchdog can't store a timeout value not equal zero without
+ * enabling the watchdog, so the timeout must be buffered by the driver.
+ */
+ if (watchdog_active(wdd))
+ ret = _da9063_wdt_set_timeout(da9063, selector);
+
if (ret)
dev_err(wdt->da9063->dev, "Failed to set watchdog timeout (err = %d)\n",
ret);
@@ -181,6 +228,14 @@ static int da9063_wdt_probe(struct platform_device *pdev)
watchdog_set_drvdata(&wdt->wdtdev, wdt);
+ /* Change the timeout to the default value if the watchdog is running */
+ if (da9063_wdt_is_running(da9063)) {
+ unsigned int timeout;
+
+ timeout = da9063_wdt_timeout_to_sel(DA9063_WDG_TIMEOUT);
+ _da9063_wdt_set_timeout(da9063, timeout);
+ set_bit(WDOG_HW_RUNNING, &wdd->status);
+ }
return devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
}