lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <24ff79b6-29f5-6921-7418-9ba93bcf7193@roeck-us.net>
Date:   Sat, 22 May 2021 06:41:31 -0700
From:   Guenter Roeck <linux@...ck-us.net>
To:     Erik Rosen <erik.rosen@...ormote.com>,
        Jean Delvare <jdelvare@...e.com>,
        Jonathan Corbet <corbet@....net>, linux-hwmon@...r.kernel.org,
        linux-doc@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v2 3/6] hwmon: (pmbus/pim4328) Add support for reading
 direct format coefficients

On 5/22/21 3:55 AM, Erik Rosen wrote:
> Add support for reading and decoding direct format coefficients to
> the PMBus core driver. If the new flag PMBUS_USE_COEFFICIENTS_CMD
> is set, the driver will use the COEFFICIENTS register together with
> the information in the pmbus_sensor_attr structs to initialize
> relevant coefficients for the direct mode format.
> 
> Signed-off-by: Erik Rosen <erik.rosen@...ormote.com>
> ---
>   drivers/hwmon/pmbus/pmbus_core.c | 93 ++++++++++++++++++++++++++++++++
>   include/linux/pmbus.h            |  8 +++
>   2 files changed, 101 insertions(+)
> 
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index 460cbfd716e4..03c169bf5633 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -2177,6 +2177,38 @@ static int pmbus_find_attributes(struct i2c_client *client,
>   	return ret;
>   }
>   
> +static int pmbus_init_coefficients(struct i2c_client *client,
> +				   struct pmbus_data *data, int page,

This seems wrong. Coefficients are not maintained per page but per class,
and (re-)reading them for each supported page doesn't really add value or
even make sense.

> +				   enum pmbus_sensor_classes sensor_class,
> +				   const struct pmbus_sensor_attr *attrs,
> +				   int nattrs)
> +{
> +	int i, status;
> +
> +	for (i = 0; i < nattrs; i++) {
> +		if (attrs->class == sensor_class &&
> +		    (attrs->func & data->info->func[page])) {
> +			status = pmbus_read_coefficients(client,
> +							 (struct pmbus_driver_info *)data->info,
> +							 sensor_class,
> +							 attrs->reg);
> +			if (status < 0) {
> +				dev_err(&client->dev,
> +					"Failed to read coefficients for register: %x\n",
> +					attrs->reg);
> +				return status;
> +			}
> +			return 0;
> +		}
> +		attrs++;
> +	}
> +
> +	dev_err(&client->dev, "No coefficients found for register: %x\n",
> +		attrs->reg);
> +

attrs points beyond the array size here, so attrs->reg does not point
to a valid array element. The problem would also not be the register
this happens to point to, but the class (ie the chip does not support
a sensor of the requested class).

Not sure if this should trigger a message or error in the first place.
It won't matter since the chip will never need those coefficients.
If anything, this would be a misconfiguration (the driver should
not set direct format for this sensor class), and the return value
should be -EINVAL.

Either case, I wonder if this can be handled with less complex code,
ie without having to check data->info->func[] for all pages. How
about just walking through attrs and try all class matches until
one is found that works (ie not return on error but keep trying) ?

> +	return -ENODEV;
> +}
> +
>   /*
>    * Identify chip parameters.
>    * This function is called for all chips.
> @@ -2185,6 +2217,7 @@ static int pmbus_identify_common(struct i2c_client *client,
>   				 struct pmbus_data *data, int page)
>   {
>   	int vout_mode = -1;
> +	int ret;
>   
>   	if (pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE))
>   		vout_mode = _pmbus_read_byte_data(client, page,
> @@ -2214,6 +2247,66 @@ static int pmbus_identify_common(struct i2c_client *client,
>   		}
>   	}
>   
> +	if (data->flags & PMBUS_USE_COEFFICIENTS_CMD) {

I think there should be a separate function to handle that,
to be called only once, not once per page.

> +		if (!i2c_check_functionality(client->adapter,
> +					     I2C_FUNC_SMBUS_BLOCK_PROC_CALL))
> +			return -ENODEV;
> +
> +		if (data->info->format[PSC_VOLTAGE_IN] == direct) {
> +			ret = pmbus_init_coefficients(client, data, page,
> +						      PSC_VOLTAGE_IN,
> +						      voltage_attributes,
> +						      ARRAY_SIZE(voltage_attributes));
> +			if (ret)
> +				return ret;
> +		}

It might be useful to have a little structure with {class, attribute list pointer,
attribute list size} and walk through that in a loop instead of repeating essentially
the same code multiple times.

> +
> +		if (data->info->format[PSC_VOLTAGE_OUT] == direct) {
> +			ret = pmbus_init_coefficients(client, data, page,
> +						      PSC_VOLTAGE_OUT,
> +						      voltage_attributes,
> +						      ARRAY_SIZE(voltage_attributes));
> +			if (ret)
> +				return ret;
> +		}
> +
> +		if (data->info->format[PSC_CURRENT_IN] == direct) {
> +			ret = pmbus_init_coefficients(client, data, page,
> +						      PSC_CURRENT_IN,
> +						      current_attributes,
> +						      ARRAY_SIZE(current_attributes));
> +			if (ret)
> +				return ret;
> +		}
> +
> +		if (data->info->format[PSC_CURRENT_OUT] == direct) {
> +			ret = pmbus_init_coefficients(client, data, page,
> +						      PSC_CURRENT_OUT,
> +						      current_attributes,
> +						      ARRAY_SIZE(current_attributes));
> +			if (ret)
> +				return ret;
> +		}
> +
> +		if (data->info->format[PSC_POWER] == direct) {
> +			ret = pmbus_init_coefficients(client, data, page,
> +						      PSC_POWER,
> +						      power_attributes,
> +						      ARRAY_SIZE(power_attributes));
> +			if (ret)
> +				return ret;
> +		}
> +
> +		if (data->info->format[PSC_TEMPERATURE] == direct) {
> +			ret = pmbus_init_coefficients(client, data, page,
> +						      PSC_TEMPERATURE,
> +						      temp_attributes,
> +						      ARRAY_SIZE(temp_attributes));
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
>   	pmbus_clear_fault_page(client, page);
>   	return 0;
>   }
> diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
> index f720470b1bab..7fdc282dab5a 100644
> --- a/include/linux/pmbus.h
> +++ b/include/linux/pmbus.h
> @@ -52,6 +52,14 @@
>    */
>   #define PMBUS_NO_WRITE_PROTECT			BIT(4)
>   
> +/*
> + * PMBUS_USE_COEFFICIENTS_CMD
> + *
> + * When this flag is set the PMBus core driver will use the COEFFICIENTS
> + * register to initialize the coefficients for the direct mode format.
> + */
> +#define PMBUS_USE_COEFFICIENTS_CMD		BIT(5)
> +
>   struct pmbus_platform_data {
>   	u32 flags;		/* Device specific flags */
>   
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ