Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f97cfddc authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Alexandre Belloni
Browse files

rtc: pcf2127: fix reading uninitialized value on RTC_READ_VL ioctl



The flag reported on the RTC_READ_VL ioctl is only initialized when the
date is read out. So the voltage low value doesn't represent reality but
the status at the time the date was read (or 0 if the date was not read
yet).

Moreover when userspace requests a value via an ioctl there is no added
benefit to also make a prosa representation of this (and other) values
appear in the kernel log so remove the calls to dev_info and the driver
data members to track their state.

Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
parent 24417829
Loading
Loading
Loading
Loading
+22 −18
Original line number Diff line number Diff line
@@ -24,7 +24,10 @@

#define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
#define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */

#define PCF2127_REG_CTRL3       (0x02)  /* Control Register 3 */
#define PCF2127_REG_CTRL3_BLF		BIT(2)

#define PCF2127_REG_SC          (0x03)  /* datetime */
#define PCF2127_REG_MN          (0x04)
#define PCF2127_REG_HR          (0x05)
@@ -39,8 +42,6 @@ static struct i2c_driver pcf2127_driver;

struct pcf2127 {
	struct rtc_device *rtc;
	int voltage_low; /* indicates if a low_voltage was detected */
	int oscillator_failed; /* OSF was detected and date is unreliable */
};

/*
@@ -49,7 +50,6 @@ struct pcf2127 {
 */
static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{
	struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
	unsigned char buf[10] = { PCF2127_REG_CTRL1 };

	/* read registers */
@@ -59,18 +59,15 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
		return -EIO;
	}

	if (buf[PCF2127_REG_CTRL3] & 0x04) {
		pcf2127->voltage_low = 1;
	if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
		dev_info(&client->dev,
			"low voltage detected, check/replace RTC battery.\n");
	}

	if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
		/*
		 * no need clear the flag here,
		 * it will be cleared once the new date is saved
		 */
		pcf2127->oscillator_failed = 1;
		dev_warn(&client->dev,
			 "oscillator stop detected, date/time is not reliable\n");
		return -EINVAL;
@@ -107,7 +104,6 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)

static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
	struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
	unsigned char buf[8];
	int i = 0, err;

@@ -141,9 +137,6 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
		return -EIO;
	}

	/* clear OSF flag in client data */
	pcf2127->oscillator_failed = 0;

	return 0;
}

@@ -151,17 +144,28 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_rtc_ioctl(struct device *dev,
				unsigned int cmd, unsigned long arg)
{
	struct pcf2127 *pcf2127 = i2c_get_clientdata(to_i2c_client(dev));
	struct i2c_client *client = to_i2c_client(dev);
	unsigned char buf = PCF2127_REG_CTRL3;
	int touser;
	int ret;

	switch (cmd) {
	case RTC_VL_READ:
		if (pcf2127->voltage_low)
			dev_info(dev, "low voltage detected, check/replace battery\n");
		if (pcf2127->oscillator_failed)
			dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
		ret = i2c_master_send(client, &buf, 1);
		if (!ret)
			ret = -EIO;
		if (ret < 0)
			return ret;

		ret = i2c_master_recv(client, &buf, 1);
		if (!ret)
			ret = -EIO;
		if (ret < 0)
			return ret;

		touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;

		if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
					sizeof(int)))
		if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
			return -EFAULT;
		return 0;
	default: