hwmon fixes for v7.1-rc5

- adm1266: Various fixes from Abdurrahman Hussain
   The fixed issues were reported by Sashiko as part of a code review of a
   functional change in the driver.
 
 - lenovo-ec-sensors: Convert to devm_request_region() to fix release_region
   cleanup, and fix EC "MCHP" signature validation logic, from Kean Ren
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmoRvVkACgkQyx8mb86f
 mYFFFBAAqlMPXnhk5ZAVbR7LojzTRtrKhSLUK2hX1A3Kaw6+MZMtnM/ccF2rzhQZ
 d7X2AecZAbIDt/33HrA9WkgcyvdK+RrFE3Ea2bBiBdWnrYlt0v5C2qnWWXdmtp6V
 ea3eu7UiejUAqwpREwQMdFOFCPLUm/lsruIObXT13X9a7HCMtGAsG0gUUO4dy7Tv
 HoYe8FM9sR6tDUf2p+cMnOOQ2ZvzEbq26umJ8gpw0nA9xXx9QCwZ+OgIzpvo+l23
 r/QTMCGlVsqbqltpaP8eyyETIQubPdSdlbdrMCQQFWtpb06lbhoQv4P0L7OBuaWo
 ta9PAdfDqhxMYvU1aNfHUZuDsM/gi+o0ARrAOSY67K+ZjRyMhRGDGq6I10/lk7n2
 xvqlpcYsMRnFtKmBdp14uUMTx/kL0iqd5xpvfWUe59pQOxZqNteJM8OlZU0whfMy
 O7GZcL13Tz7b805El9Zn59Ix80z36f5jPfLai2Fu9P32fEyun+cIWsU4ZM7CDD68
 v1jGExcKbjfHVpR7z0pAQ3X/ufVVnDh4M73OPIwlCOt6DAToYA6wDx+LwYXA+sLP
 FI+qfVwvpAlA0SD/jhvURhXz5bf8Fc1WO5GsXCiD5VmtL3ND+N+ciQeZGu2DxVNY
 I7gDe/KL1i+jLbieLGWB7GRSTdofjUvhD+/jBbJnvyGuXxwnYgw=
 =vk5N
 -----END PGP SIGNATURE-----

Merge tag 'hwmon-for-v7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon fixes from Guenter Roeck:

 - adm1266: Various fixes from Abdurrahman Hussain

   The fixed issues were reported by Sashiko as part of a code review of
   a functional change in the driver.

 - lenovo-ec-sensors: Convert to devm_request_region() to fix
   release_region cleanup, and fix EC "MCHP" signature validation logic,
   from Kean Ren

* tag 'hwmon-for-v7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (pmbus/adm1266) serialize sequencer_state debugfs read with pmbus_lock
  hwmon: (pmbus/adm1266) serialize NVMEM blackbox read with pmbus_lock
  hwmon: (pmbus/adm1266) serialize GPIO PMBus accesses with pmbus_lock
  hwmon: (pmbus/adm1266) register the nvmem device after pmbus_do_probe()
  hwmon: (pmbus/adm1266) register the gpio_chip after pmbus_do_probe()
  hwmon: (pmbus/adm1266) reject short block-read responses in the GPIO accessors
  hwmon: (pmbus/adm1266) don't clobber GPIO bits before PDIO read in get_multiple
  hwmon: (pmbus/adm1266) cap PDIO scan in get_multiple at ADM1266_PDIO_NR
  hwmon: (pmbus/adm1266) bounce blackbox records through a protocol-sized buffer
  hwmon: (pmbus/adm1266) include adapter number in GPIO line label
  hwmon: (pmbus/adm1266) include PEC byte in pmbus_block_xfer read buffer
  hwmon: (pmbus/adm1266) reject implausible blackbox record_count
  hwmon: (pmbus/adm1266) widen blackbox-info buffer to I2C_SMBUS_BLOCK_MAX
  hwmon: (pmbus/adm1266) seed timestamp from the real-time clock
  hwmon: (lenovo-ec-sensors): Fix EC "MCHP" signature validation logic
  hwmon: (lenovo-ec-sensors): Convert to devm_request_region()
This commit is contained in:
Linus Torvalds 2026-05-24 10:37:55 -07:00
commit 2be86a8c57
2 changed files with 40 additions and 26 deletions

View File

@ -519,8 +519,8 @@ static int lenovo_ec_probe(struct platform_device *pdev)
if (!ec_data)
return -ENOMEM;
if (!request_region(IO_REGION_START, IO_REGION_LENGTH, "LNV-WKS")) {
pr_err(":request fail\n");
if (!devm_request_region(dev, IO_REGION_START, IO_REGION_LENGTH, "LNV-WKS")) {
dev_err(dev, "Failed to request I/O region\n");
return -EIO;
}
@ -537,13 +537,11 @@ static int lenovo_ec_probe(struct platform_device *pdev)
outw_p(MCHP_SING_IDX, MCHP_EMI0_EC_ADDRESS);
mutex_unlock(&ec_data->mec_mutex);
if ((inb_p(MCHP_EMI0_EC_DATA_BYTE0) != 'M') &&
(inb_p(MCHP_EMI0_EC_DATA_BYTE1) != 'C') &&
(inb_p(MCHP_EMI0_EC_DATA_BYTE2) != 'H') &&
(inb_p(MCHP_EMI0_EC_DATA_BYTE3) != 'P')) {
release_region(IO_REGION_START, IO_REGION_LENGTH);
if ((inb_p(MCHP_EMI0_EC_DATA_BYTE0) != 'M') ||
(inb_p(MCHP_EMI0_EC_DATA_BYTE1) != 'C') ||
(inb_p(MCHP_EMI0_EC_DATA_BYTE2) != 'H') ||
(inb_p(MCHP_EMI0_EC_DATA_BYTE3) != 'P'))
return -ENODEV;
}
dmi_id = dmi_first_match(thinkstation_dmi_table);
@ -577,7 +575,6 @@ static int lenovo_ec_probe(struct platform_device *pdev)
lenovo_ec_chip_info.info = lenovo_ec_hwmon_info_p8;
break;
default:
release_region(IO_REGION_START, IO_REGION_LENGTH);
return -ENODEV;
}
@ -606,10 +603,8 @@ static int __init lenovo_ec_init(void)
platform_create_bundle(&lenovo_ec_sensors_platform_driver,
lenovo_ec_probe, NULL, 0, NULL, 0);
if (IS_ERR(lenovo_ec_sensors_platform_device)) {
release_region(IO_REGION_START, IO_REGION_LENGTH);
if (IS_ERR(lenovo_ec_sensors_platform_device))
return PTR_ERR(lenovo_ec_sensors_platform_device);
}
return 0;
}
@ -617,7 +612,6 @@ module_init(lenovo_ec_init);
static void __exit lenovo_ec_exit(void)
{
release_region(IO_REGION_START, IO_REGION_LENGTH);
platform_device_unregister(lenovo_ec_sensors_platform_device);
platform_driver_unregister(&lenovo_ec_sensors_platform_driver);
}

View File

@ -46,6 +46,7 @@
#define ADM1266_BLACKBOX_OFFSET 0
#define ADM1266_BLACKBOX_SIZE 64
#define ADM1266_BLACKBOX_MAX_RECORDS 32
#define ADM1266_PMBUS_BLOCK_MAX 255
@ -60,7 +61,7 @@ struct adm1266_data {
u8 *dev_mem;
struct mutex buf_mutex;
u8 write_buf[ADM1266_PMBUS_BLOCK_MAX + 1] ____cacheline_aligned;
u8 read_buf[ADM1266_PMBUS_BLOCK_MAX + 1] ____cacheline_aligned;
u8 read_buf[ADM1266_PMBUS_BLOCK_MAX + 2] ____cacheline_aligned;
};
static const struct nvmem_cell_info adm1266_nvmem_cells[] = {
@ -172,9 +173,13 @@ static int adm1266_gpio_get(struct gpio_chip *chip, unsigned int offset)
else
pmbus_cmd = ADM1266_PDIO_STATUS;
guard(pmbus_lock)(data->client);
ret = i2c_smbus_read_block_data(data->client, pmbus_cmd, read_buf);
if (ret < 0)
return ret;
if (ret < 2)
return -EIO;
pins_status = read_buf[0] + (read_buf[1] << 8);
if (offset < ADM1266_GPIO_NR)
@ -192,9 +197,13 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
unsigned int gpio_nr;
int ret;
guard(pmbus_lock)(data->client);
ret = i2c_smbus_read_block_data(data->client, ADM1266_GPIO_STATUS, read_buf);
if (ret < 0)
return ret;
if (ret < 2)
return -EIO;
status = read_buf[0] + (read_buf[1] << 8);
@ -207,11 +216,12 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
ret = i2c_smbus_read_block_data(data->client, ADM1266_PDIO_STATUS, read_buf);
if (ret < 0)
return ret;
if (ret < 2)
return -EIO;
status = read_buf[0] + (read_buf[1] << 8);
*bits = 0;
for_each_set_bit_from(gpio_nr, mask, ADM1266_GPIO_NR + ADM1266_PDIO_STATUS) {
for_each_set_bit_from(gpio_nr, mask, ADM1266_GPIO_NR + ADM1266_PDIO_NR) {
if (test_bit(gpio_nr - ADM1266_GPIO_NR, &status))
set_bit(gpio_nr, bits);
}
@ -230,6 +240,8 @@ static void adm1266_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
int ret;
int i;
guard(pmbus_lock)(data->client);
for (i = 0; i < ADM1266_GPIO_NR; i++) {
write_cmd = adm1266_gpio_mapping[i][1];
ret = adm1266_pmbus_block_xfer(data, ADM1266_GPIO_CONFIG, 1, &write_cmd, read_buf);
@ -290,8 +302,9 @@ static int adm1266_config_gpio(struct adm1266_data *data)
int i;
for (i = 0; i < ARRAY_SIZE(data->gpio_names); i++) {
gpio_name = devm_kasprintf(&data->client->dev, GFP_KERNEL, "adm1266-%x-%s",
data->client->addr, adm1266_names[i]);
gpio_name = devm_kasprintf(&data->client->dev, GFP_KERNEL, "adm1266-%d-%x-%s",
data->client->adapter->nr, data->client->addr,
adm1266_names[i]);
if (!gpio_name)
return -ENOMEM;
@ -322,6 +335,7 @@ static int adm1266_state_read(struct seq_file *s, void *pdata)
struct i2c_client *client = to_i2c_client(dev);
int ret;
guard(pmbus_lock)(client);
ret = i2c_smbus_read_word_data(client, ADM1266_READ_STATE);
if (ret < 0)
return ret;
@ -347,9 +361,10 @@ static void adm1266_init_debugfs(struct adm1266_data *data)
static int adm1266_nvmem_read_blackbox(struct adm1266_data *data, u8 *read_buff)
{
u8 record[ADM1266_PMBUS_BLOCK_MAX];
int record_count;
char index;
u8 buf[5];
u8 buf[I2C_SMBUS_BLOCK_MAX];
int ret;
ret = i2c_smbus_read_block_data(data->client, ADM1266_BLACKBOX_INFO, buf);
@ -360,15 +375,18 @@ static int adm1266_nvmem_read_blackbox(struct adm1266_data *data, u8 *read_buff)
return -EIO;
record_count = buf[3];
if (record_count > ADM1266_BLACKBOX_MAX_RECORDS)
return -EIO;
for (index = 0; index < record_count; index++) {
ret = adm1266_pmbus_block_xfer(data, ADM1266_READ_BLACKBOX, 1, &index, read_buff);
ret = adm1266_pmbus_block_xfer(data, ADM1266_READ_BLACKBOX, 1, &index, record);
if (ret < 0)
return ret;
if (ret != ADM1266_BLACKBOX_SIZE)
return -EIO;
memcpy(read_buff, record, ADM1266_BLACKBOX_SIZE);
read_buff += ADM1266_BLACKBOX_SIZE;
}
@ -383,6 +401,8 @@ static int adm1266_nvmem_read(void *priv, unsigned int offset, void *val, size_t
if (offset + bytes > data->nvmem_config.size)
return -EINVAL;
guard(pmbus_lock)(data->client);
if (offset == 0) {
memset(data->dev_mem, 0, data->nvmem_config.size);
@ -432,7 +452,7 @@ static int adm1266_set_rtc(struct adm1266_data *data)
char write_buf[6];
int i;
kt = ktime_get_seconds();
kt = ktime_get_real_seconds();
memset(write_buf, 0, sizeof(write_buf));
@ -462,20 +482,20 @@ static int adm1266_probe(struct i2c_client *client)
crc8_populate_msb(pmbus_crc_table, 0x7);
mutex_init(&data->buf_mutex);
ret = adm1266_config_gpio(data);
ret = adm1266_set_rtc(data);
if (ret < 0)
return ret;
ret = adm1266_set_rtc(data);
if (ret < 0)
ret = pmbus_do_probe(client, &data->info);
if (ret)
return ret;
ret = adm1266_config_nvmem(data);
if (ret < 0)
return ret;
ret = pmbus_do_probe(client, &data->info);
if (ret)
ret = adm1266_config_gpio(data);
if (ret < 0)
return ret;
adm1266_init_debugfs(data);