[RESEND][RFC PATCH] regulator: introduce boot protection flag

2016-06-01 Thread WEN Pingbo
In some platforms, critical shared regulator is initialized in
bootloader. But during kernel booting, the driver probing order and
conflicting operations from other regulator consumers, may set the
regulator in a undefined state, which will cause serious problem.

This patch try to add a boot_protection flag in regulator constraints.
And regulator core will postpone all operations until all consumers
have taked their place.

The boot_protection flag only work before late_initicall. And as other
constraints liked, you can specify this flag in a board file, or in
dts file.

Signed-off-by: WEN Pingbo 
Cc: Stephen Boyd 
Cc: David Collins 
---
 drivers/regulator/core.c  | 106 +++---
 drivers/regulator/internal.h  |   2 +
 drivers/regulator/of_regulator.c  |   3 ++
 include/linux/regulator/driver.h  |   3 ++
 include/linux/regulator/machine.h |   1 +
 5 files changed, 109 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index fe47d38..f994a0f 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -55,6 +55,7 @@ static LIST_HEAD(regulator_map_list);
 static LIST_HEAD(regulator_ena_gpio_list);
 static LIST_HEAD(regulator_supply_alias_list);
 static bool has_full_constraints;
+static bool regulator_has_booted;
 
 static struct dentry *debugfs_root;
 
@@ -1030,6 +1031,13 @@ static int set_machine_constraints(struct regulator_dev 
*rdev,
if (!rdev->constraints)
return -ENOMEM;
 
+   /*
+* If a regulator driver is registered after late_initcall, the
+* boot_protection should be ingnored.
+*/
+   if (regulator_has_booted)
+   rdev->constraints->boot_protection = 0;
+
ret = machine_constraints_voltage(rdev, rdev->constraints);
if (ret != 0)
return ret;
@@ -2195,8 +2203,14 @@ static int _regulator_disable(struct regulator_dev *rdev)
if (rdev->use_count == 1 &&
(rdev->constraints && !rdev->constraints->always_on)) {
 
-   /* we are last user */
-   if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
+   /*
+* We are last user.
+*
+* If boot_protection is set, we only clear use_count,
+* and regulator_init_complete() will disable it.
+*/
+   if (!rdev->constraints->boot_protection &&
+   regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
ret = _notifier_call_chain(rdev,
   REGULATOR_EVENT_PRE_DISABLE,
   NULL);
@@ -2297,6 +2311,10 @@ int regulator_force_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret;
 
+   WARN(rdev->constraints->boot_protection,
+   "disable regulator %s with boot protection flag\n",
+   rdev->desc->name);
+
mutex_lock(&rdev->mutex);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev);
@@ -2852,6 +2870,10 @@ static int regulator_set_voltage_unlocked(struct 
regulator *regulator,
if (ret < 0)
goto out2;
 
+   /* We need to change voltage, but boot_protection is set. */
+   if (rdev->constraints->boot_protection)
+   goto out;
+
if (rdev->supply && (rdev->desc->min_dropout_uV ||
!rdev->desc->ops->get_voltage)) {
int current_supply_uV;
@@ -3069,6 +3091,9 @@ int regulator_sync_voltage(struct regulator *regulator)
if (ret < 0)
goto out;
 
+   if (rdev->constraints->boot_protection)
+   goto out;
+
ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
 
 out:
@@ -3161,6 +3186,15 @@ int regulator_set_current_limit(struct regulator 
*regulator,
if (ret < 0)
goto out;
 
+   /*
+* Stage new current value, and applied it later.
+*/
+   if (rdev->constraints->boot_protection) {
+   regulator->min_uA = min_uA;
+   regulator->max_uA = max_uA;
+   goto out;
+   }
+
ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
 out:
mutex_unlock(&rdev->mutex);
@@ -3240,6 +3274,11 @@ int regulator_set_mode(struct regulator *regulator, 
unsigned int mode)
if (ret < 0)
goto out;
 
+   if (rdev->constraints->boot_protection) {
+   rdev->boot_mode = mode;
+   goto out;
+   }
+
ret = rdev->desc->ops->set_mode(rdev, mode);
 out:
mutex_unlock(&rdev->mutex);
@@ -3306,11 +3345,14 @@ EXP

[RFC PATCH] regulator: introduce boot protection flag

2016-05-09 Thread WEN Pingbo
In some platforms, critical shared regulator is initialized in
bootloader. But during kernel booting, the driver probing order and
conflicting operations from other regulator consumers, may set the
regulator in a undefined state, which will cause serious problem.

This patch try to add a boot_protection flag in regulator constraints.
And regulator core will postpone all operations until all consumers
have taked their place.

The boot_protection flag only work before late_initicall. And as other
constraints liked, you can specify this flag in a board file, or in
dts file.

Signed-off-by: WEN Pingbo 
---
 drivers/regulator/core.c  | 106 +++---
 drivers/regulator/internal.h  |   2 +
 drivers/regulator/of_regulator.c  |   3 ++
 include/linux/regulator/driver.h  |   3 ++
 include/linux/regulator/machine.h |   1 +
 5 files changed, 109 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index fe47d38..f994a0f 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -55,6 +55,7 @@ static LIST_HEAD(regulator_map_list);
 static LIST_HEAD(regulator_ena_gpio_list);
 static LIST_HEAD(regulator_supply_alias_list);
 static bool has_full_constraints;
+static bool regulator_has_booted;
 
 static struct dentry *debugfs_root;
 
@@ -1030,6 +1031,13 @@ static int set_machine_constraints(struct regulator_dev 
*rdev,
if (!rdev->constraints)
return -ENOMEM;
 
+   /*
+* If a regulator driver is registered after late_initcall, the
+* boot_protection should be ingnored.
+*/
+   if (regulator_has_booted)
+   rdev->constraints->boot_protection = 0;
+
ret = machine_constraints_voltage(rdev, rdev->constraints);
if (ret != 0)
return ret;
@@ -2195,8 +2203,14 @@ static int _regulator_disable(struct regulator_dev *rdev)
if (rdev->use_count == 1 &&
(rdev->constraints && !rdev->constraints->always_on)) {
 
-   /* we are last user */
-   if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
+   /*
+* We are last user.
+*
+* If boot_protection is set, we only clear use_count,
+* and regulator_init_complete() will disable it.
+*/
+   if (!rdev->constraints->boot_protection &&
+   regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
ret = _notifier_call_chain(rdev,
   REGULATOR_EVENT_PRE_DISABLE,
   NULL);
@@ -2297,6 +2311,10 @@ int regulator_force_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret;
 
+   WARN(rdev->constraints->boot_protection,
+   "disable regulator %s with boot protection flag\n",
+   rdev->desc->name);
+
mutex_lock(&rdev->mutex);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev);
@@ -2852,6 +2870,10 @@ static int regulator_set_voltage_unlocked(struct 
regulator *regulator,
if (ret < 0)
goto out2;
 
+   /* We need to change voltage, but boot_protection is set. */
+   if (rdev->constraints->boot_protection)
+   goto out;
+
if (rdev->supply && (rdev->desc->min_dropout_uV ||
!rdev->desc->ops->get_voltage)) {
int current_supply_uV;
@@ -3069,6 +3091,9 @@ int regulator_sync_voltage(struct regulator *regulator)
if (ret < 0)
goto out;
 
+   if (rdev->constraints->boot_protection)
+   goto out;
+
ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
 
 out:
@@ -3161,6 +3186,15 @@ int regulator_set_current_limit(struct regulator 
*regulator,
if (ret < 0)
goto out;
 
+   /*
+* Stage new current value, and applied it later.
+*/
+   if (rdev->constraints->boot_protection) {
+   regulator->min_uA = min_uA;
+   regulator->max_uA = max_uA;
+   goto out;
+   }
+
ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
 out:
mutex_unlock(&rdev->mutex);
@@ -3240,6 +3274,11 @@ int regulator_set_mode(struct regulator *regulator, 
unsigned int mode)
if (ret < 0)
goto out;
 
+   if (rdev->constraints->boot_protection) {
+   rdev->boot_mode = mode;
+   goto out;
+   }
+
ret = rdev->desc->ops->set_mode(rdev, mode);
 out:
mutex_unlock(&rdev->mutex);
@@ -3306,11 +3345,14 @@ EXPORT_SYMBOL_GPL(regulator_get_mode);

[RFC PATCH 2/2] regulator: add boot protection flag

2016-04-23 Thread WEN Pingbo
In some platform, some critical shared regulator is initialized before
kernel loading. But in kernel booting, the driver probing order and
conflict operation from other regulator consumer, may set the regulator
in a undefined state, which will cause serious problem.

This patch try to add a boot_protection flag in regulator constraints.
So the regulator core will prevent the specified operation during kernel
booting.

The boot_protection flag only work before late_initicall. And as other
constraints liked, you can specify this flag in a board file, or in
dts file. By default, all operations of this regulator will be rejected
during kernel booting, if you add this flag in a regulator. But you
still have a chance to change this, by modifying boot_valid_ops_mask.

[ This patch depends on regulator_ops_is_valid patch. And some document
need to add, but I want to hear some voice first. ]

Signed-off-by: WEN Pingbo 
---
 drivers/regulator/core.c  | 24 +---
 drivers/regulator/of_regulator.c  | 29 +
 include/linux/regulator/machine.h |  2 ++
 3 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index fe47d38..5b9dc22 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -55,6 +55,7 @@ static LIST_HEAD(regulator_map_list);
 static LIST_HEAD(regulator_ena_gpio_list);
 static LIST_HEAD(regulator_supply_alias_list);
 static bool has_full_constraints;
+static bool regulator_has_booted;
 
 static struct dentry *debugfs_root;
 
@@ -139,7 +140,15 @@ static bool regulator_ops_is_valid(struct regulator_dev 
*rdev, int ops)
return false;
}
 
-   if (rdev->constraints->valid_ops_mask & ops)
+   /*
+* Ignore regulator boot-protection, after later_initcall.
+*/
+   if (!regulator_has_booted && rdev->constraints->boot_protection) {
+   if (rdev->constraints->boot_valid_ops_mask & ops)
+   return true;
+   else
+   rdev_info(rdev, "rejected operation 0x%02x\n", ops);
+   } else if (rdev->constraints->valid_ops_mask & ops)
return true;
 
return false;
@@ -868,7 +877,7 @@ static void print_constraints(struct regulator_dev *rdev)
rdev_dbg(rdev, "%s\n", buf);
 
if ((constraints->min_uV != constraints->max_uV) &&
-   !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
+   !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE))
rdev_warn(rdev,
  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
 }
@@ -1309,7 +1318,8 @@ static struct regulator *create_regulator(struct 
regulator_dev *rdev,
 * it is then we don't need to do nearly so much work for
 * enable/disable calls.
 */
-   if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) &&
+   if (rdev->constraints &&
+   !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) &&
_regulator_is_enabled(rdev))
regulator->always_on = true;
 
@@ -4353,6 +4363,12 @@ static int __init regulator_late_cleanup(struct device 
*dev, void *data)
struct regulation_constraints *c = rdev->constraints;
int enabled, ret;
 
+   /*
+* The kernel boot is finished, let's unset boot_protection
+* Need a lock?
+*/
+   c->boot_protection = 0;
+
if (c && c->always_on)
return 0;
 
@@ -4406,6 +4422,8 @@ static int __init regulator_init_complete(void)
if (of_have_populated_dt())
has_full_constraints = true;
 
+   regulator_has_booted = true;
+
/* If we have a full configuration then disable any regulators
 * we have permission to change the status for and which are
 * not in use or always_on.  This is effectively the default
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 6b0aa80..bfec59c 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -78,6 +78,35 @@ static void of_get_regulation_constraints(struct device_node 
*np,
if (of_property_read_bool(np, "regulator-allow-set-load"))
constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
 
+   constraints->boot_protection = of_property_read_bool(np,
+   "regulator-boot-protection");
+
+   if (constraints->boot_protection) {
+   if (of_property_read_bool(np, "boot-allow-set-voltage"))
+   constraints->boot_valid_ops_mask |=
+   REGULATOR_CHANGE_VOLTAGE;
+   if (of_property_read_bool(np, "b

[RFC PATCH 1/2] regulator: refactor valid_ops_mask checking code

2016-04-23 Thread WEN Pingbo
To make the code more compat and centralized, this patch add a
unified function - regulator_ops_is_valid. So we can add
some extra checking code easily later.

Signed-off-by: WEN Pingbo 
---
 drivers/regulator/core.c | 88 
 1 file changed, 29 insertions(+), 59 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e0b7642..fe47d38 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -132,6 +132,19 @@ static bool have_full_constraints(void)
return has_full_constraints || of_have_populated_dt();
 }
 
+static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
+{
+   if (!rdev->constraints) {
+   rdev_err(rdev, "no constraints\n");
+   return false;
+   }
+
+   if (rdev->constraints->valid_ops_mask & ops)
+   return true;
+
+   return false;
+}
+
 static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
 {
if (rdev && rdev->supply)
@@ -198,28 +211,13 @@ static struct device_node *of_get_regulator(struct device 
*dev, const char *supp
return regnode;
 }
 
-static int _regulator_can_change_status(struct regulator_dev *rdev)
-{
-   if (!rdev->constraints)
-   return 0;
-
-   if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
-   return 1;
-   else
-   return 0;
-}
-
 /* Platform voltage constraint check */
 static int regulator_check_voltage(struct regulator_dev *rdev,
   int *min_uV, int *max_uV)
 {
BUG_ON(*min_uV > *max_uV);
 
-   if (!rdev->constraints) {
-   rdev_err(rdev, "no constraints\n");
-   return -ENODEV;
-   }
-   if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+   if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
rdev_err(rdev, "voltage operation not allowed\n");
return -EPERM;
}
@@ -275,11 +273,7 @@ static int regulator_check_current_limit(struct 
regulator_dev *rdev,
 {
BUG_ON(*min_uA > *max_uA);
 
-   if (!rdev->constraints) {
-   rdev_err(rdev, "no constraints\n");
-   return -ENODEV;
-   }
-   if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
+   if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) {
rdev_err(rdev, "current operation not allowed\n");
return -EPERM;
}
@@ -312,11 +306,7 @@ static int regulator_mode_constrain(struct regulator_dev 
*rdev, int *mode)
return -EINVAL;
}
 
-   if (!rdev->constraints) {
-   rdev_err(rdev, "no constraints\n");
-   return -ENODEV;
-   }
-   if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
+   if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) {
rdev_err(rdev, "mode operation not allowed\n");
return -EPERM;
}
@@ -333,20 +323,6 @@ static int regulator_mode_constrain(struct regulator_dev 
*rdev, int *mode)
return -EINVAL;
 }
 
-/* dynamic regulator mode switching constraint check */
-static int regulator_check_drms(struct regulator_dev *rdev)
-{
-   if (!rdev->constraints) {
-   rdev_err(rdev, "no constraints\n");
-   return -ENODEV;
-   }
-   if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
-   rdev_dbg(rdev, "drms operation not allowed\n");
-   return -EPERM;
-   }
-   return 0;
-}
-
 static ssize_t regulator_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
 {
@@ -692,8 +668,7 @@ static int drms_uA_update(struct regulator_dev *rdev)
 * first check to see if we can set modes at all, otherwise just
 * tell the consumer everything is OK.
 */
-   err = regulator_check_drms(rdev);
-   if (err < 0)
+   if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
return 0;
 
if (!rdev->desc->ops->get_optimum_mode &&
@@ -893,7 +868,7 @@ static void print_constraints(struct regulator_dev *rdev)
rdev_dbg(rdev, "%s\n", buf);
 
if ((constraints->min_uV != constraints->max_uV) &&
-   !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE))
+   !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
rdev_warn(rdev,
  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
 }
@@ -1334,7 +1309,7 @@ static struct regulator *create_regulator(struct 
regulator_dev *rdev,
 * it is then we

[PATCH 2/3] input: evdev: add new ioctl EVIOCSIFTYPE / EVIOCGIFTYPE

2015-11-27 Thread WEN Pingbo
This patch depends on 'introduce new evdev interface'.

Userspace cat set / get evdev interface type via the two ioctl
commands. And default interface type is EV_IF_LEGACY, so the old binary
will work normal with new kernel. Maybe we should change this default
option to encourage people to move to new interface.

And since all events are stored as input_value in evdev, there are no
need to flush evdev_client's buffer if we change clk_type and if_type.

Signed-off-by: WEN Pingbo 
---
 drivers/input/evdev.c  | 39 +++
 include/uapi/linux/input.h | 10 ++
 2 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 170681b..090576b 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -175,7 +175,6 @@ static void evdev_queue_syn_dropped(struct evdev_client 
*client)
 
 static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
 {
-   unsigned long flags;
unsigned int clk_type;
 
switch (clkid) {
@@ -193,21 +192,29 @@ static int evdev_set_clk_type(struct evdev_client 
*client, unsigned int clkid)
return -EINVAL;
}
 
-   if (client->clk_type != clk_type) {
+   if (client->clk_type != clk_type)
client->clk_type = clk_type;
 
-   /*
-* Flush pending events and queue SYN_DROPPED event,
-* but only if the queue is not empty.
-*/
-   spin_lock_irqsave(&client->buffer_lock, flags);
+   return 0;
+}
 
-   if (client->head != client->tail) {
-   client->packet_head = client->head = client->tail;
-   __evdev_queue_syn_dropped(client);
-   }
+static int evdev_set_if_type(struct evdev_client *client, unsigned int if_type)
+{
+   if (client->if_type == if_type)
+   return 0;
 
-   spin_unlock_irqrestore(&client->buffer_lock, flags);
+   switch (if_type) {
+   case EVDEV_LEGACY:
+   client->if_type = EV_IF_LEGACY;
+   break;
+   case EVDEV_RAW:
+   client->if_type = EV_IF_RAW;
+   break;
+   case EVDEV_COMPOSITE:
+   client->if_type = EV_IF_COMPOSITE;
+   break;
+   default:
+   return -EINVAL;
}
 
return 0;
@@ -1046,6 +1053,7 @@ static long evdev_do_ioctl(struct file *file, unsigned 
int cmd,
int __user *ip = (int __user *)p;
unsigned int i, t, u, v;
unsigned int size;
+   int if_type;
int error;
 
/* First we check for fixed-length commands */
@@ -1144,6 +1152,13 @@ static long evdev_do_ioctl(struct file *file, unsigned 
int cmd,
 
case EVIOCSKEYCODE_V2:
return evdev_handle_set_keycode_v2(dev, p);
+   case EVIOCSIFTYPE:
+   if (get_user(if_type, ip))
+   return -EFAULT;
+
+   return evdev_set_if_type(client, if_type);
+   case EVIOCGIFTYPE:
+   return put_user(client->if_type, ip);
}
 
size = _IOC_SIZE(cmd);
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 79b35ff..9ae5243 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -234,6 +234,16 @@ struct input_mask {
 
 #define EVIOCSCLOCKID  _IOW('E', 0xa0, int)/* Set 
clockid to be used for timestamps */
 
+#define EVIOCSIFTYPE   _IOW('E', 0xa1, int)/* Set 
if_type */
+#define EVIOCGIFTYPE   _IOR('E', 0xa2, int)/* Get 
if_type */
+
+/*
+ * evdev interface type
+ */
+#define EVDEV_LEGACY   0x00
+#define EVDEV_RAW  0x01
+#define EVDEV_COMPOSITE0x02
+
 /*
  * IDs.
  */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] input: evdev: introduce new evdev interface

2015-11-27 Thread WEN Pingbo
The y2038 problem in 'struct input_event' is complained too much. And
after some discussion with other people, I found it's impossible to
solve this in a simple way, and keep backward compatible at the same
time, so we need some new y2038-safe interface here.

This patch add two new evdev interface type - EV_IF_RAW and
EV_IF_COMPOSITE. And leaving the old interface as EV_IF_LEGACY for
compatibility. Userspace can switch between those interface seamlessly
via ioctl, which will be introduced in another patch.

And since evdev doesn't really interest in event timestamp, the patch
has also converted input_event to input_value in evdev entirely, and
move all time-related operations to input_event_to/from_user().

Signed-off-by: WEN Pingbo 
---
 drivers/input/evdev.c|  78 ---
 drivers/input/input-compat.c | 148 ---
 drivers/input/input-compat.h |  48 ++
 include/linux/input.h|  12 
 include/uapi/linux/input.h   |  17 +
 5 files changed, 176 insertions(+), 127 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e9ae3d5..170681b 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -28,13 +28,6 @@
 #include 
 #include "input-compat.h"
 
-enum evdev_clock_type {
-   EV_CLK_REAL = 0,
-   EV_CLK_MONO,
-   EV_CLK_BOOT,
-   EV_CLK_MAX
-};
-
 struct evdev {
int open;
struct input_handle handle;
@@ -57,10 +50,11 @@ struct evdev_client {
struct evdev *evdev;
struct list_head node;
unsigned int clk_type;
+   unsigned int if_type;
bool revoked;
unsigned long *evmasks[EV_CNT];
unsigned int bufsize;
-   struct input_event buffer[];
+   struct input_value buffer[];
 };
 
 static size_t evdev_get_mask_cnt(unsigned int type)
@@ -113,7 +107,7 @@ static void __evdev_flush_queue(struct evdev_client 
*client, unsigned int type)
unsigned int i, head, num;
unsigned int mask = client->bufsize - 1;
bool is_report;
-   struct input_event *ev;
+   struct input_value *ev;
 
BUG_ON(type == EV_SYN);
 
@@ -135,7 +129,6 @@ static void __evdev_flush_queue(struct evdev_client 
*client, unsigned int type)
continue;
} else if (head != i) {
/* move entry to fill the gap */
-   client->buffer[head].time = ev->time;
client->buffer[head].type = ev->type;
client->buffer[head].code = ev->code;
client->buffer[head].value = ev->value;
@@ -155,16 +148,8 @@ static void __evdev_flush_queue(struct evdev_client 
*client, unsigned int type)
 
 static void __evdev_queue_syn_dropped(struct evdev_client *client)
 {
-   struct input_event ev;
-   ktime_t time;
+   struct input_value ev;
 
-   time = client->clk_type == EV_CLK_REAL ?
-   ktime_get_real() :
-   client->clk_type == EV_CLK_MONO ?
-   ktime_get() :
-   ktime_get_boottime();
-
-   ev.time = ktime_to_timeval(time);
ev.type = EV_SYN;
ev.code = SYN_DROPPED;
ev.value = 0;
@@ -229,7 +214,7 @@ static int evdev_set_clk_type(struct evdev_client *client, 
unsigned int clkid)
 }
 
 static void __pass_event(struct evdev_client *client,
-const struct input_event *event)
+const struct input_value *event)
 {
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
@@ -241,7 +226,6 @@ static void __pass_event(struct evdev_client *client,
 */
client->tail = (client->head - 2) & (client->bufsize - 1);
 
-   client->buffer[client->tail].time = event->time;
client->buffer[client->tail].type = EV_SYN;
client->buffer[client->tail].code = SYN_DROPPED;
client->buffer[client->tail].value = 0;
@@ -256,19 +240,15 @@ static void __pass_event(struct evdev_client *client,
 }
 
 static void evdev_pass_values(struct evdev_client *client,
-   const struct input_value *vals, unsigned int count,
-   ktime_t *ev_time)
+   const struct input_value *vals, unsigned int count)
 {
struct evdev *evdev = client->evdev;
const struct input_value *v;
-   struct input_event event;
bool wakeup = false;
 
if (client->revoked)
return;
 
-   event.time = ktime_to_timeval(ev_time[client->clk_type]);
-
/* Interrupts are disabled, just acquire the lock. */
spin_lock(&client->buffer_lock);
 
@@ -284,10 +264,7 @@ static void evdev_pass_values(struct evdev_client *client

[PATCH 3/3] uinput: convert input_event to input_value

2015-11-27 Thread WEN Pingbo
This patch depends on 'add new evdev interface'.

We should not use input_event in kernel any more. Convert it in
uinput, and adapt to new api changes.

Signed-off-by: WEN Pingbo 
---
 drivers/input/misc/uinput.c | 23 +++
 include/linux/uinput.h  |  2 +-
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 5adbced..d84c6d4 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -50,7 +50,6 @@ static int uinput_dev_event(struct input_dev *dev,
udev->buff[udev->head].type = type;
udev->buff[udev->head].code = code;
udev->buff[udev->head].value = value;
-   do_gettimeofday(&udev->buff[udev->head].time);
udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
wake_up_interruptible(&udev->waitq);
@@ -436,24 +435,24 @@ static int uinput_setup_device(struct uinput_device *udev,
 static ssize_t uinput_inject_events(struct uinput_device *udev,
const char __user *buffer, size_t count)
 {
-   struct input_event ev;
+   struct input_value ev;
size_t bytes = 0;
 
-   if (count != 0 && count < input_event_size())
+   if (count != 0 && count < input_event_size(EV_IF_LEGACY))
return -EINVAL;
 
-   while (bytes + input_event_size() <= count) {
+   while (bytes + input_event_size(EV_IF_LEGACY) <= count) {
/*
 * Note that even if some events were fetched successfully
 * we are still going to return EFAULT instead of partial
 * count to let userspace know that it got it's buffers
 * all wrong.
 */
-   if (input_event_from_user(buffer + bytes, &ev))
+   if (input_event_from_user(buffer + bytes, &ev, EV_IF_LEGACY))
return -EFAULT;
 
input_event(udev->dev, ev.type, ev.code, ev.value);
-   bytes += input_event_size();
+   bytes += input_event_size(EV_IF_LEGACY);
}
 
return bytes;
@@ -482,7 +481,7 @@ static ssize_t uinput_write(struct file *file, const char 
__user *buffer,
 }
 
 static bool uinput_fetch_next_event(struct uinput_device *udev,
-   struct input_event *event)
+   struct input_value *event)
 {
bool have_event;
 
@@ -502,16 +501,16 @@ static bool uinput_fetch_next_event(struct uinput_device 
*udev,
 static ssize_t uinput_events_to_user(struct uinput_device *udev,
 char __user *buffer, size_t count)
 {
-   struct input_event event;
+   struct input_value event;
size_t read = 0;
 
-   while (read + input_event_size() <= count &&
+   while (read + input_event_size(EV_IF_LEGACY) <= count &&
   uinput_fetch_next_event(udev, &event)) {
 
-   if (input_event_to_user(buffer + read, &event))
+   if (input_value_to_user(buffer + read, &event, EV_IF_LEGACY))
return -EFAULT;
 
-   read += input_event_size();
+   read += input_event_size(EV_IF_LEGACY);
}
 
return read;
@@ -523,7 +522,7 @@ static ssize_t uinput_read(struct file *file, char __user 
*buffer,
struct uinput_device *udev = file->private_data;
ssize_t retval;
 
-   if (count != 0 && count < input_event_size())
+   if (count != 0 && count < input_event_size(EV_IF_LEGACY))
return -EINVAL;
 
do {
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 0994c0d..bdb6fca 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -66,7 +66,7 @@ struct uinput_device {
unsigned char   ready;
unsigned char   head;
unsigned char   tail;
-   struct input_event  buff[UINPUT_BUFFER_SIZE];
+   struct input_value  buff[UINPUT_BUFFER_SIZE];
unsigned intff_effects_max;
 
struct uinput_request   *requests[UINPUT_NUM_REQUESTS];
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3] introduce new evdev interface type

2015-11-27 Thread WEN Pingbo
To solve the y2038 problem in input_event, I had some attempts before [1],
and this is the second one.

We can force userspace to use monotonic time in event timestamp, so the
'struct timeval' is enough to keep y2038-safe, as Arnd suggested. But we
can not find a way to make kernel compatible with old binaries, which use
realtime, and there are still some devices, which depend on realtime.

So I get a idea to add a new evdev interface, which is y2038 safe. And
userspace can switch between the old and new interface via ioctl.

The patch series add three evdev interface type:

- EV_IF_LEGACY
  send event by input_event. This is the default option, keep kernel
  backward compatible.

- EV_IF_RAW
  send event by input_value, which doesn't contain a timestamp. If
  userspace don't need the event timestamp, EV_IF_RAW is the best choice.

- EV_IF_COMPOSITE
  send event by input_composite_event. This is a new structure, which
  append a nanosecond timestamp after input_value. Since the input_value
  and s64 are the same size, so you can treat it as two input_value.

Actually, evdev is not interesting in event timestamp, all it should do is
to keep event sequences, and evdev already satisfy this. So in the kernel,
the event should only store in input_value, input_event and
input_composite_event is used by userspace only.

I also wrote a evtest tool [2], to validate those patches. The tool create
a evdev device via uinput, and inject event through evdev or uinput, with 
different interface type.

I have run this test in my Dragonboard 410c, by this command:

$ evtest -l -r -c -n 40

No problem found, all events are received normally.

[1]: previous patches - https://www.spinics.net/lists/y2038/msg00959.html
[2]: evtest source code - https://github.com/wengpingbo/evtest

WEN Pingbo (3):
  input: evdev: introduce new evdev interface
  input: evdev: add new ioctl EVIOCSIFTYPE / EVIOCGIFTYPE
  uinput: convert input_event to input_value

 drivers/input/evdev.c| 117 --
 drivers/input/input-compat.c | 148 ---
 drivers/input/input-compat.h |  48 ++
 drivers/input/misc/uinput.c  |  23 ---
 include/linux/input.h|  12 
 include/linux/uinput.h   |   2 +-
 include/uapi/linux/input.h   |  27 
 7 files changed, 225 insertions(+), 152 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4] hp_sdc: convert struct timeval to ktime_t

2015-10-23 Thread WEN Pingbo
struct timeval is not y2038 safe, convert it to ktime_t,
and there is no need to handle sec and usec separately

And since hp_sdc.rtv is only used for time diff, monotonic time
is better here

Signed-off-by: WEN Pingbo 
---

Version 2:
Using ktime_t instead of struct timespec64
Version 3:
Commit msg adjustment, and using ktime_to_ns to extract nsecs 
Version 4:
Correct commit msg format

 drivers/input/serio/hp_sdc.c | 16 ++--
 include/linux/hp_sdc.h   |  6 +++---
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 852858e..17e3725 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -193,7 +193,7 @@ static void hp_sdc_take(int irq, void *dev_id, uint8_t 
status, uint8_t data)
curr->seq[curr->idx++] = status;
curr->seq[curr->idx++] = data;
hp_sdc.rqty -= 2;
-   do_gettimeofday(&hp_sdc.rtv);
+   hp_sdc.rtv = ktime_get();
 
if (hp_sdc.rqty <= 0) {
/* All data has been gathered. */
@@ -306,13 +306,9 @@ static void hp_sdc_tasklet(unsigned long foo)
write_lock_irq(&hp_sdc.rtq_lock);
 
if (hp_sdc.rcurr >= 0) {
-   struct timeval tv;
+   ktime_t time_diff = ktime_sub(ktime_get(), hp_sdc.rtv);
 
-   do_gettimeofday(&tv);
-   if (tv.tv_sec > hp_sdc.rtv.tv_sec)
-   tv.tv_usec += USEC_PER_SEC;
-
-   if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+   if (ktime_to_ns(time_diff) > HP_SDC_MAX_REG_DELAY) {
hp_sdc_transaction *curr;
uint8_t tmp;
 
@@ -321,8 +317,8 @@ static void hp_sdc_tasklet(unsigned long foo)
 * we'll need to figure out a way to communicate
 * it back to the application. and be less verbose.
 */
-   printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
-  (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
+   printk(KERN_WARNING PREFIX "read timeout (%llins)!\n",
+  ktime_to_ns(time_diff));
curr->idx += hp_sdc.rqty;
hp_sdc.rqty = 0;
tmp = curr->seq[curr->actidx];
@@ -551,7 +547,7 @@ unsigned long hp_sdc_put(void)
 
/* Start a new read */
hp_sdc.rqty = curr->seq[curr->idx];
-   do_gettimeofday(&hp_sdc.rtv);
+   hp_sdc.rtv = ktime_get();
curr->idx++;
/* Still need to lock here in case of spurious irq. */
write_lock_irq(&hp_sdc.rtq_lock);
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
index d392975..348a9b5 100644
--- a/include/linux/hp_sdc.h
+++ b/include/linux/hp_sdc.h
@@ -47,9 +47,9 @@
 #endif
 
 
-/* No 4X status reads take longer than this (in usec).
+/* No 4X status reads take longer than this (in nsec).
  */
-#define HP_SDC_MAX_REG_DELAY 2
+#define HP_SDC_MAX_REG_DELAY 2000
 
 typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
   uint8_t status, uint8_t data);
@@ -281,7 +281,7 @@ typedef struct {
hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
 
int rcurr, rqty;/* Current read transact in process */
-   struct timeval  rtv;/* Time when current read started */
+   ktime_t rtv;/* Time when current read started */
int wcurr;  /* Current write transact in process */
 
int dev_err;/* carries status from registration */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 2/2] hil_mlc: convert timeval to jiffies

2015-10-23 Thread WEN Pingbo
struct timeval is not y2038 safe, and what mlc->instart do is
scheduling a task in a fixed timeout, so jiffies is the
simplest choice here.

In hilse_donode(), the expires in mod_timer equals

jiffies + intimeout - (now - instart)

If we use jiffies in 'now', the expires equals

instart + intimeout

So, all we need to do is that making sure expires is a future
timestamp before passed it to mod_timer

Signed-off-by: WEN Pingbo 
---

Version 2:
Using ktime_t to fix y2038 problem
Version 3:
Convert it to jiffies

 drivers/input/serio/hil_mlc.c| 17 +++--
 drivers/input/serio/hp_sdc_mlc.c |  7 +++
 include/linux/hil_mlc.h  |  2 +-
 3 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index fb297aa..5428098 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -603,7 +603,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, const 
struct hilse_node *node
}
mlc->istarted = 1;
mlc->intimeout = node->arg;
-   do_gettimeofday(&(mlc->instart));
+   mlc->instart = jiffies;
mlc->icount = 15;
memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
BUG_ON(down_trylock(&mlc->isem));
@@ -708,7 +708,7 @@ static int hilse_donode(hil_mlc *mlc)
break;
}
mlc->ostarted = 0;
-   do_gettimeofday(&(mlc->instart));
+   mlc->instart = jiffies;
write_unlock_irqrestore(&mlc->lock, flags);
nextidx = HILSEN_NEXT;
break;
@@ -729,18 +729,15 @@ static int hilse_donode(hil_mlc *mlc)
 #endif
 
while (nextidx & HILSEN_SCHED) {
-   struct timeval tv;
+   unsigned long expires = mlc->instart +
+   usecs_to_jiffies(mlc->intimeout);
 
if (!sched_long)
goto sched;
 
-   do_gettimeofday(&tv);
-   tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-   tv.tv_usec -= mlc->instart.tv_usec;
-   if (tv.tv_usec >= mlc->intimeout) goto sched;
-   tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
-   if (!tv.tv_usec) goto sched;
-   mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+   if (time_after_eq(jiffies, expires))
+   goto sched;
+   mod_timer(&hil_mlcs_kicker, expires);
break;
sched:
tasklet_schedule(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index d50f067..b91d5bb 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -149,7 +149,6 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
 
/* Try to down the semaphore */
if (down_trylock(&mlc->isem)) {
-   struct timeval tv;
if (priv->emtestmode) {
mlc->ipacket[0] =
HIL_ERR_INT | (mlc->opacket &
@@ -160,9 +159,9 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
/* printk(KERN_DEBUG PREFIX ">[%x]\n", 
mlc->ipacket[0]); */
goto wasup;
}
-   do_gettimeofday(&tv);
-   tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-   if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+
+   if (time_after(jiffies,
+   mlc->instart + usecs_to_jiffies(mlc->intimeout))) {
/*  printk("!%i %i",
tv.tv_usec - mlc->instart.tv_usec,
mlc->intimeout);
diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
index 29bb5e3..feb167d 100644
--- a/include/linux/hil_mlc.h
+++ b/include/linux/hil_mlc.h
@@ -144,7 +144,7 @@ struct hil_mlc {
hil_packet  ipacket[16];
hil_packet  imatch;
int icount;
-   struct timeval  instart;
+   unsigned long   instart; /* in jiffies */
suseconds_t intimeout;
 
int ddi;/* Last operational device id */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 1/2] hil_mlc: convert timeval to time64_t

2015-10-23 Thread WEN Pingbo
Since mlc->lcv_t is only interested in seconds,
directly using time64_t here

Signed-off-by: WEN Pingbo 
---

Version 2:
Convert timeval to ktime_t
Version 3:
Convert it to time64_t, since it's a better choice

 drivers/input/serio/hil_mlc.c | 8 +++-
 include/linux/hil_mlc.h   | 2 +-
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65605e4..fb297aa 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -274,14 +274,12 @@ static int hilse_match(hil_mlc *mlc, int unused)
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
 static int hilse_init_lcv(hil_mlc *mlc, int unused)
 {
-   struct timeval tv;
+   time64_t now = ktime_get_seconds();
 
-   do_gettimeofday(&tv);
-
-   if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+   if (mlc->lcv && (now - mlc->lcv_t) < 5)
return -1;
 
-   mlc->lcv_tv = tv;
+   mlc->lcv_t = now;
mlc->lcv = 0;
 
return 0;
diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
index 394a840..29bb5e3 100644
--- a/include/linux/hil_mlc.h
+++ b/include/linux/hil_mlc.h
@@ -149,7 +149,7 @@ struct hil_mlc {
 
int ddi;/* Last operational device id */
int lcv;/* LCV to throttle loops */
-   struct timeval  lcv_tv; /* Time loop was started */
+   time64_tlcv_t; /* Time loop was started */
 
int di_map[7]; /* Maps below items to live devs */
struct hil_mlc_devinfo  di[HIL_MLC_DEVMEM];
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3] hp_sdc: convert struct timeval to ktime_t

2015-10-23 Thread WEN Pingbo
1. struct timeval is not y2038 safe, convert it to ktime_t, and there is no 
need to handle sec and usec separately

2. hp_sdc.rtv is only used for time diff, monotonic time is better here

Signed-off-by: WEN Pingbo 
---

Version 2:
Using ktime_t instead of struct timespec64
Version 3:
Commit msg adjustment, and using ktime_to_ns to extract nsecs 

 drivers/input/serio/hp_sdc.c | 16 ++--
 include/linux/hp_sdc.h   |  6 +++---
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 852858e..17e3725 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -193,7 +193,7 @@ static void hp_sdc_take(int irq, void *dev_id, uint8_t 
status, uint8_t data)
curr->seq[curr->idx++] = status;
curr->seq[curr->idx++] = data;
hp_sdc.rqty -= 2;
-   do_gettimeofday(&hp_sdc.rtv);
+   hp_sdc.rtv = ktime_get();
 
if (hp_sdc.rqty <= 0) {
/* All data has been gathered. */
@@ -306,13 +306,9 @@ static void hp_sdc_tasklet(unsigned long foo)
write_lock_irq(&hp_sdc.rtq_lock);
 
if (hp_sdc.rcurr >= 0) {
-   struct timeval tv;
+   ktime_t time_diff = ktime_sub(ktime_get(), hp_sdc.rtv);
 
-   do_gettimeofday(&tv);
-   if (tv.tv_sec > hp_sdc.rtv.tv_sec)
-   tv.tv_usec += USEC_PER_SEC;
-
-   if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+   if (ktime_to_ns(time_diff) > HP_SDC_MAX_REG_DELAY) {
hp_sdc_transaction *curr;
uint8_t tmp;
 
@@ -321,8 +317,8 @@ static void hp_sdc_tasklet(unsigned long foo)
 * we'll need to figure out a way to communicate
 * it back to the application. and be less verbose.
 */
-   printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
-  (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
+   printk(KERN_WARNING PREFIX "read timeout (%llins)!\n",
+  ktime_to_ns(time_diff));
curr->idx += hp_sdc.rqty;
hp_sdc.rqty = 0;
tmp = curr->seq[curr->actidx];
@@ -551,7 +547,7 @@ unsigned long hp_sdc_put(void)
 
/* Start a new read */
hp_sdc.rqty = curr->seq[curr->idx];
-   do_gettimeofday(&hp_sdc.rtv);
+   hp_sdc.rtv = ktime_get();
curr->idx++;
/* Still need to lock here in case of spurious irq. */
write_lock_irq(&hp_sdc.rtq_lock);
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
index d392975..348a9b5 100644
--- a/include/linux/hp_sdc.h
+++ b/include/linux/hp_sdc.h
@@ -47,9 +47,9 @@
 #endif
 
 
-/* No 4X status reads take longer than this (in usec).
+/* No 4X status reads take longer than this (in nsec).
  */
-#define HP_SDC_MAX_REG_DELAY 2
+#define HP_SDC_MAX_REG_DELAY 2000
 
 typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
   uint8_t status, uint8_t data);
@@ -281,7 +281,7 @@ typedef struct {
hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
 
int rcurr, rqty;/* Current read transact in process */
-   struct timeval  rtv;/* Time when current read started */
+   ktime_t rtv;/* Time when current read started */
int wcurr;  /* Current write transact in process */
 
int dev_err;/* carries status from registration */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2] hil_mlc: convert timeval to ktime_t

2015-10-23 Thread WEN Pingbo
Using struct timeval will cause time overflow in 2038, replacing it with
ktime_t. And we don't need to handle sec and nsec separately.

Since mlc->lcv_t is only interested in seconds, directly using
time64_t here.

And monotonic time is better here, since the original driver don't care
the wall time.

In addition, the original driver try to covert usec to jiffies manually in
hilse_donode(). This is not a universal and safe way, using
nsecs_to_jiffies() to fix that.

Signed-off-by: WEN Pingbo 
---
 drivers/input/serio/hil_mlc.c| 28 +---
 drivers/input/serio/hp_sdc_mlc.c |  8 
 include/linux/hil_mlc.h  |  4 ++--
 3 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65605e4..2746509 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -274,14 +274,12 @@ static int hilse_match(hil_mlc *mlc, int unused)
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
 static int hilse_init_lcv(hil_mlc *mlc, int unused)
 {
-   struct timeval tv;
+   time64_t now = ktime_get_seconds();
 
-   do_gettimeofday(&tv);
-
-   if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+   if (mlc->lcv && (now - mlc->lcv_t) < 5)
return -1;
 
-   mlc->lcv_tv = tv;
+   mlc->lcv_t = now;
mlc->lcv = 0;
 
return 0;
@@ -605,7 +603,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, const 
struct hilse_node *node
}
mlc->istarted = 1;
mlc->intimeout = node->arg;
-   do_gettimeofday(&(mlc->instart));
+   mlc->instart = ktime_get();
mlc->icount = 15;
memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
BUG_ON(down_trylock(&mlc->isem));
@@ -710,7 +708,7 @@ static int hilse_donode(hil_mlc *mlc)
break;
}
mlc->ostarted = 0;
-   do_gettimeofday(&(mlc->instart));
+   mlc->instart = ktime_get();
write_unlock_irqrestore(&mlc->lock, flags);
nextidx = HILSEN_NEXT;
break;
@@ -731,18 +729,18 @@ static int hilse_donode(hil_mlc *mlc)
 #endif
 
while (nextidx & HILSEN_SCHED) {
-   struct timeval tv;
+   ktime_t tmp = ktime_sub(ktime_get(), mlc->instart);
 
if (!sched_long)
goto sched;
 
-   do_gettimeofday(&tv);
-   tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-   tv.tv_usec -= mlc->instart.tv_usec;
-   if (tv.tv_usec >= mlc->intimeout) goto sched;
-   tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
-   if (!tv.tv_usec) goto sched;
-   mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+   if (tmp.tv64 >= (mlc->intimeout * NSEC_PER_USEC))
+   goto sched;
+   tmp.tv64 = mlc->intimeout * NSEC_PER_USEC - tmp.tv64;
+   if (tmp.tv64 < NSEC_PER_USEC)
+   goto sched;
+   mod_timer(&hil_mlcs_kicker,
+   jiffies + nsecs_to_jiffies(tmp.tv64));
break;
sched:
tasklet_schedule(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index d50f067..0a27b89 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -149,7 +149,8 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
 
/* Try to down the semaphore */
if (down_trylock(&mlc->isem)) {
-   struct timeval tv;
+   ktime_t tmp = ktime_sub(ktime_get(), mlc->instart);
+
if (priv->emtestmode) {
mlc->ipacket[0] =
HIL_ERR_INT | (mlc->opacket &
@@ -160,9 +161,8 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
/* printk(KERN_DEBUG PREFIX ">[%x]\n", 
mlc->ipacket[0]); */
goto wasup;
}
-   do_gettimeofday(&tv);
-   tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-   if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+
+   if (tmp.tv64 > mlc->intimeout * NSEC_PER_USEC) {
/*  printk("!%i %i",
tv.tv_usec - mlc->instart.tv_usec,
mlc->intimeout);
diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
index 394a840..ec6 100644
--- a/include/linux/hil_mlc.h
+++ b/include/linux/hil_mlc.h
@@ -1

[PATCH V2] hp_sdc: fixed y2038 problem

2015-10-23 Thread WEN Pingbo
1. Converting timeval to ktime_t, and there is no need to handle sec and
usec separately

2. hp_sdc.rtv is only used for time diff, monotonic time is better here

Signed-off-by: WEN Pingbo 
---
 drivers/input/serio/hp_sdc.c | 16 ++--
 include/linux/hp_sdc.h   |  6 +++---
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 852858e..8ef82ee 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -193,7 +193,7 @@ static void hp_sdc_take(int irq, void *dev_id, uint8_t 
status, uint8_t data)
curr->seq[curr->idx++] = status;
curr->seq[curr->idx++] = data;
hp_sdc.rqty -= 2;
-   do_gettimeofday(&hp_sdc.rtv);
+   hp_sdc.rtv = ktime_get();
 
if (hp_sdc.rqty <= 0) {
/* All data has been gathered. */
@@ -306,13 +306,9 @@ static void hp_sdc_tasklet(unsigned long foo)
write_lock_irq(&hp_sdc.rtq_lock);
 
if (hp_sdc.rcurr >= 0) {
-   struct timeval tv;
+   ktime_t time_diff = ktime_sub(ktime_get(), hp_sdc.rtv);
 
-   do_gettimeofday(&tv);
-   if (tv.tv_sec > hp_sdc.rtv.tv_sec)
-   tv.tv_usec += USEC_PER_SEC;
-
-   if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+   if (time_diff.tv64 > HP_SDC_MAX_REG_DELAY) {
hp_sdc_transaction *curr;
uint8_t tmp;
 
@@ -321,8 +317,8 @@ static void hp_sdc_tasklet(unsigned long foo)
 * we'll need to figure out a way to communicate
 * it back to the application. and be less verbose.
 */
-   printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
-  (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
+   printk(KERN_WARNING PREFIX "read timeout (%llins)!\n",
+  time_diff.tv64);
curr->idx += hp_sdc.rqty;
hp_sdc.rqty = 0;
tmp = curr->seq[curr->actidx];
@@ -551,7 +547,7 @@ unsigned long hp_sdc_put(void)
 
/* Start a new read */
hp_sdc.rqty = curr->seq[curr->idx];
-   do_gettimeofday(&hp_sdc.rtv);
+   hp_sdc.rtv = ktime_get();
curr->idx++;
/* Still need to lock here in case of spurious irq. */
write_lock_irq(&hp_sdc.rtq_lock);
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
index d392975..348a9b5 100644
--- a/include/linux/hp_sdc.h
+++ b/include/linux/hp_sdc.h
@@ -47,9 +47,9 @@
 #endif
 
 
-/* No 4X status reads take longer than this (in usec).
+/* No 4X status reads take longer than this (in nsec).
  */
-#define HP_SDC_MAX_REG_DELAY 2
+#define HP_SDC_MAX_REG_DELAY 2000
 
 typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
   uint8_t status, uint8_t data);
@@ -281,7 +281,7 @@ typedef struct {
hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
 
int rcurr, rqty;/* Current read transact in process */
-   struct timeval  rtv;/* Time when current read started */
+   ktime_t rtv;/* Time when current read started */
int wcurr;  /* Current write transact in process */
 
int dev_err;/* carries status from registration */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] hil_mlc: convert timeval to timespec64

2015-10-18 Thread WEN Pingbo
Using struct timeval will cause time overflow in 2038, replacing it with
a 64bit version.

In addition, the origin driver try to covert usec to jiffies manually in
hilse_donode(). This is not a universal and safe way, using
nsecs_to_jiffies() to fix that.

Signed-off-by: WEN Pingbo 
---
 drivers/input/serio/hil_mlc.c| 31 +--
 drivers/input/serio/hp_sdc_mlc.c | 10 ++
 include/linux/hil_mlc.h  |  4 ++--
 3 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65605e4..4e3b926 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -274,14 +274,14 @@ static int hilse_match(hil_mlc *mlc, int unused)
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
 static int hilse_init_lcv(hil_mlc *mlc, int unused)
 {
-   struct timeval tv;
+   struct timespec64 ts64;
 
-   do_gettimeofday(&tv);
+   ktime_get_ts64(&ts64);
 
-   if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+   if (mlc->lcv && (ts64.tv_sec - mlc->lcv_ts64.tv_sec) < 5)
return -1;
 
-   mlc->lcv_tv = tv;
+   mlc->lcv_ts64 = ts64;
mlc->lcv = 0;
 
return 0;
@@ -605,7 +605,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, const 
struct hilse_node *node
}
mlc->istarted = 1;
mlc->intimeout = node->arg;
-   do_gettimeofday(&(mlc->instart));
+   ktime_get_ts64(&(mlc->instart));
mlc->icount = 15;
memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
BUG_ON(down_trylock(&mlc->isem));
@@ -710,7 +710,7 @@ static int hilse_donode(hil_mlc *mlc)
break;
}
mlc->ostarted = 0;
-   do_gettimeofday(&(mlc->instart));
+   ktime_get_ts64(&(mlc->instart));
write_unlock_irqrestore(&mlc->lock, flags);
nextidx = HILSEN_NEXT;
break;
@@ -731,18 +731,21 @@ static int hilse_donode(hil_mlc *mlc)
 #endif
 
while (nextidx & HILSEN_SCHED) {
-   struct timeval tv;
+   struct timespec64 ts64;
 
if (!sched_long)
goto sched;
 
-   do_gettimeofday(&tv);
-   tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-   tv.tv_usec -= mlc->instart.tv_usec;
-   if (tv.tv_usec >= mlc->intimeout) goto sched;
-   tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
-   if (!tv.tv_usec) goto sched;
-   mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+   ktime_get_ts64(&ts64);
+   ts64.tv_nsec += NSEC_PER_SEC *
+   (ts64.tv_sec - mlc->instart.tv_sec);
+   ts64.tv_nsec -= mlc->instart.tv_nsec;
+   if (ts64.tv_nsec >= (mlc->intimeout * NSEC_PER_USEC))
+   goto sched;
+   ts64.tv_nsec = mlc->intimeout * NSEC_PER_USEC - ts64.tv_nsec;
+   if (!ts64.tv_nsec) goto sched;
+   mod_timer(&hil_mlcs_kicker,
+   jiffies + nsecs_to_jiffies(ts64.tv_nsec));
break;
sched:
tasklet_schedule(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index d50f067..369885d 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -149,7 +149,7 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
 
/* Try to down the semaphore */
if (down_trylock(&mlc->isem)) {
-   struct timeval tv;
+   struct timespec64 ts64;
if (priv->emtestmode) {
mlc->ipacket[0] =
HIL_ERR_INT | (mlc->opacket &
@@ -160,9 +160,11 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
/* printk(KERN_DEBUG PREFIX ">[%x]\n", 
mlc->ipacket[0]); */
goto wasup;
}
-   do_gettimeofday(&tv);
-   tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-   if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+   ktime_get_ts64(&ts64);
+   ts64.tv_nsec += NSEC_PER_SEC *
+   (ts64.tv_sec - mlc->instart.tv_sec);
+   if (ts64.tv_nsec - mlc->instart.tv_nsec > mlc->intimeout *
+   NSEC_PER_USEC) {
/*  printk("!%i %i",
tv.tv_usec - mlc->instart.tv_usec,
mlc-&

[PATCH] hp_sdc: fixed y2038 problem

2015-10-18 Thread WEN Pingbo
Two replacements happened in this patch:
1. using timespec64 to prevent time overflow in 2038
2. using ktime_get_ts64 to avoid wall time issues(leap second, etc)

Signed-off-by: WEN Pingbo 
---
 drivers/input/serio/hp_sdc.c | 18 +-
 include/linux/hp_sdc.h   |  6 +++---
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 852858e..76fb7fa 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -193,7 +193,7 @@ static void hp_sdc_take(int irq, void *dev_id, uint8_t 
status, uint8_t data)
curr->seq[curr->idx++] = status;
curr->seq[curr->idx++] = data;
hp_sdc.rqty -= 2;
-   do_gettimeofday(&hp_sdc.rtv);
+   ktime_get_ts64(&hp_sdc.rtv);
 
if (hp_sdc.rqty <= 0) {
/* All data has been gathered. */
@@ -306,13 +306,13 @@ static void hp_sdc_tasklet(unsigned long foo)
write_lock_irq(&hp_sdc.rtq_lock);
 
if (hp_sdc.rcurr >= 0) {
-   struct timeval tv;
+   struct timespec64 ts64;
 
-   do_gettimeofday(&tv);
-   if (tv.tv_sec > hp_sdc.rtv.tv_sec)
-   tv.tv_usec += USEC_PER_SEC;
+   ktime_get_ts64(&ts64);
+   if (ts64.tv_sec > hp_sdc.rtv.tv_sec)
+   ts64.tv_nsec += NSEC_PER_SEC;
 
-   if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+   if (ts64.tv_nsec - hp_sdc.rtv.tv_nsec > HP_SDC_MAX_REG_DELAY) {
hp_sdc_transaction *curr;
uint8_t tmp;
 
@@ -321,8 +321,8 @@ static void hp_sdc_tasklet(unsigned long foo)
 * we'll need to figure out a way to communicate
 * it back to the application. and be less verbose.
 */
-   printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
-  (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
+   printk(KERN_WARNING PREFIX "read timeout (%llins)!\n",
+  (s64)(ts64.tv_nsec - hp_sdc.rtv.tv_nsec));
curr->idx += hp_sdc.rqty;
hp_sdc.rqty = 0;
tmp = curr->seq[curr->actidx];
@@ -551,7 +551,7 @@ unsigned long hp_sdc_put(void)
 
/* Start a new read */
hp_sdc.rqty = curr->seq[curr->idx];
-   do_gettimeofday(&hp_sdc.rtv);
+   ktime_get_ts64(&hp_sdc.rtv);
curr->idx++;
/* Still need to lock here in case of spurious irq. */
write_lock_irq(&hp_sdc.rtq_lock);
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
index d392975..1535640 100644
--- a/include/linux/hp_sdc.h
+++ b/include/linux/hp_sdc.h
@@ -47,9 +47,9 @@
 #endif
 
 
-/* No 4X status reads take longer than this (in usec).
+/* No 4X status reads take longer than this (in nsec).
  */
-#define HP_SDC_MAX_REG_DELAY 2
+#define HP_SDC_MAX_REG_DELAY 2000
 
 typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
   uint8_t status, uint8_t data);
@@ -281,7 +281,7 @@ typedef struct {
hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
 
int rcurr, rqty;/* Current read transact in process */
-   struct timeval  rtv;/* Time when current read started */
+   struct timespec64   rtv;/* Time when current read 
started */
int wcurr;  /* Current write transact in process */
 
int dev_err;/* carries status from registration */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3] dummy_hcd: replace timeval with timespec64

2015-09-17 Thread WEN Pingbo
The millisecond of the last second will be normal if tv_sec is
overflowed. But for y2038 consistency and demonstration purpose,
and avoiding further risks, we need to remove 'timeval' in this
driver, to avoid similair problems.

Signed-off-by: Pingbo Wen 
Reviewed-by: Arnd Bergmann 
---

V3 Updates:
- using ts64 variable name to avoid confusion

V2 Updates:
- using monotonic time here by replacing getnstimeofday() with
  ktime_get_ts64(), to avoid leap second issues. The frame time in USB
  is always 1ms, no matter what speed, so ktime_get_ts64() have enough
  resolution to cover this.
- using NSEC_PER_MSEC instead of hard code.

 drivers/usb/gadget/udc/dummy_hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c 
b/drivers/usb/gadget/udc/dummy_hcd.c
index 1379ad4..2ac9a13 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -833,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
 /* there are both host and device side versions of this call ... */
 static int dummy_g_get_frame(struct usb_gadget *_gadget)
 {
-   struct timeval  tv;
+   struct timespec64 ts64;
 
-   do_gettimeofday(&tv);
-   return tv.tv_usec / 1000;
+   ktime_get_ts64(&ts64);
+   return ts64.tv_nsec / NSEC_PER_MSEC;
 }
 
 static int dummy_wakeup(struct usb_gadget *_gadget)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2] dummy_hcd: replace timeval with timespec64

2015-09-16 Thread WEN Pingbo
The millisecond of the last second will be normal if tv_sec is
overflowed. But for y2038 consistency and demonstration purpose,
and avoiding further risks, we need to remove 'timeval' in this
driver, to avoid similair problems.

V2 Updates:
- using monotonic time here by replacing getnstimeofday() with
  ktime_get_ts64(), to avoid leap second issues. The frame time in USB
  is always 1ms, no matter what speed, so ktime_get_ts64() have enough
  resolution to cover this.
- using NSEC_PER_MSEC instead of hard code.

Signed-off-by: Pingbo Wen 
Cc: Y2038 
Cc: linux-kernel@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Felipe Balbi 
Signed-off-by: WEN Pingbo 
---
 drivers/usb/gadget/udc/dummy_hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c 
b/drivers/usb/gadget/udc/dummy_hcd.c
index 1379ad4..6d1ed35 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -833,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
 /* there are both host and device side versions of this call ... */
 static int dummy_g_get_frame(struct usb_gadget *_gadget)
 {
-   struct timeval  tv;
+   struct timespec64 tv;
 
-   do_gettimeofday(&tv);
-   return tv.tv_usec / 1000;
+   ktime_get_ts64(&tv);
+   return tv.tv_nsec / NSEC_PER_MSEC;
 }
 
 static int dummy_wakeup(struct usb_gadget *_gadget)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2] hp_sdc_rtc: fixed y2038 problem in proc_show

2015-09-16 Thread WEN Pingbo
hp_sdc_rtc_proc_show() use timeval to store the time, which will
overflowed in 2038.

This patch fixes this problem by replacing timeval with timespec64.
hp_sdc_rtc_proc_show() only output string, so that userspace will work
normally if we apply this patch.

Not all timer in i8042 have y2038 risk(handshake, match timer, etc),
Replacements in those timer are just for consistency.

Version 2 Updates:
- compiled in m68k gcc cross compiler(4.6.3), no extra warnings
- placed s64 type cast in tv.tv_sec, making sure it work properly in
both 32bit and 64bit platform.

Signed-off-by: WEN Pingbo 
Cc: Y2038 
---
 drivers/input/misc/hp_sdc_rtc.c | 52 -
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 45e0e3e..1c8c56e 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -198,7 +198,7 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, 
int numreg)
 
 
 /* Read the i8042 real-time clock */
-static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_rt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms; 
unsigned int days;
@@ -209,15 +209,15 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) 
{
tenms = (uint32_t)raw & 0xff;
days  = (unsigned int)(raw >> 24) & 0x;
 
-   res->tv_usec = (suseconds_t)(tenms % 100) * 1;
-   res->tv_sec =  (time_t)(tenms / 100) + days * 86400;
+   res->tv_nsec = (long)(tenms % 100) * 1 * 1000;
+   res->tv_sec =  (tenms / 100) + (time64_t)days * 86400;
 
return 0;
 }
 
 
 /* Read the i8042 fast handshake timer */
-static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
+static inline int hp_sdc_rtc_read_fhs(struct timespec64 *res) {
int64_t raw;
unsigned int tenms;
 
@@ -226,15 +226,15 @@ static inline int hp_sdc_rtc_read_fhs(struct timeval 
*res) {
 
tenms = (unsigned int)raw & 0x;
 
-   res->tv_usec = (suseconds_t)(tenms % 100) * 1;
-   res->tv_sec  = (time_t)(tenms / 100);
+   res->tv_nsec = (long)(tenms % 100) * 1 * 1000;
+   res->tv_sec  = (time64_t)(tenms / 100);
 
return 0;
 }
 
 
 /* Read the i8042 match timer (a.k.a. alarm) */
-static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_mt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms; 
 
@@ -243,15 +243,15 @@ static inline int hp_sdc_rtc_read_mt(struct timeval *res) 
{
 
tenms = (uint32_t)raw & 0xff;
 
-   res->tv_usec = (suseconds_t)(tenms % 100) * 1;
-   res->tv_sec  = (time_t)(tenms / 100);
+   res->tv_nsec = (long)(tenms % 100) * 1 * 1000;
+   res->tv_sec  = (time64_t)(tenms / 100);
 
return 0;
 }
 
 
 /* Read the i8042 delay timer */
-static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
+static inline int hp_sdc_rtc_read_dt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
 
@@ -260,15 +260,15 @@ static inline int hp_sdc_rtc_read_dt(struct timeval *res) 
{
 
tenms = (uint32_t)raw & 0xff;
 
-   res->tv_usec = (suseconds_t)(tenms % 100) * 1;
-   res->tv_sec  = (time_t)(tenms / 100);
+   res->tv_nsec = (long)(tenms % 100) * 1 * 1000;
+   res->tv_sec  = (time64_t)(tenms / 100);
 
return 0;
 }
 
 
 /* Read the i8042 cycle timer (a.k.a. periodic) */
-static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
+static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
 
@@ -277,8 +277,8 @@ static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
 
tenms = (uint32_t)raw & 0xff;
 
-   res->tv_usec = (suseconds_t)(tenms % 100) * 1;
-   res->tv_sec  = (time_t)(tenms / 100);
+   res->tv_nsec = (long)(tenms % 100) * 1 * 1000;
+   res->tv_sec  = (time64_t)(tenms / 100);
 
return 0;
 }
@@ -433,7 +433,7 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
 #define YN(bit) ("no")
 #define NY(bit) ("yes")
 struct rtc_time tm;
-   struct timeval tv;
+   struct timespec64 tv;
 
memset(&tm, 0, sizeof(struct rtc_time));
 
@@ -452,36 +452,36 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void 
*v)
if (hp_sdc_rtc_read_rt(&tv)) {
seq_puts(m, "i8042 rtc\t: READ FAILED!\n");
} else {
-   seq_printf(m, "i8042 rtc\t: %ld.%02d seconds\n", 
-tv.tv_sec, (int)tv.tv_usec/1000);
+   seq_printf(m, "i8042 rtc\t: %lld.%02ld seconds\n",
+(s64)tv.tv_sec, (long)tv.tv_nsec/100L);
}
 
if (hp_sdc_rtc_read_fhs

[PATCH] dummy_hcd: replace timeval with timespec64

2015-09-15 Thread WEN Pingbo
The millisecond of the last second will be normal if tv_sec is
overflowed. But for y2038 consistency and demonstration purpose,
and avoiding further risks, we still need to fix it here,
to avoid similair problems.

Signed-off-by: Pingbo Wen 
Cc: Y2038 
Cc: linux-kernel@vger.kernel.org
Cc: Arnd Bergmann 
Cc: Felipe Balbi 
---
 drivers/usb/gadget/udc/dummy_hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c 
b/drivers/usb/gadget/udc/dummy_hcd.c
index 1379ad4..7be721dad 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -833,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
 /* there are both host and device side versions of this call ... */
 static int dummy_g_get_frame(struct usb_gadget *_gadget)
 {
-   struct timeval  tv;
+   struct timespec64 tv;
 
-   do_gettimeofday(&tv);
-   return tv.tv_usec / 1000;
+   getnstimeofday64(&tv);
+   return tv.tv_nsec / 100L;
 }
 
 static int dummy_wakeup(struct usb_gadget *_gadget)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/