[PATCH 4/4] hwmon: (pmbus/core): Notify hwmon events

From: Naresh Solanki
Date: Mon Jan 23 2023 - 01:40:50 EST


Notify hwmon events using the pmbus irq handler.

Signed-off-by: Naresh Solanki <Naresh.Solanki@xxxxxxxxxxxxx>
---
drivers/hwmon/pmbus/pmbus_core.c | 45 ++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 3c1c68e93943..cbea92d3a1e6 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2735,8 +2735,35 @@ static const struct pmbus_status_category __maybe_unused pmbus_status_flag_map[]
},
};

+#define to_dev_attr(_dev_attr) \
+ container_of(_dev_attr, struct device_attribute, attr)

-static int pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *error)
+static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
+{
+ int i;
+
+ for (i = 0; i < data->num_attributes; i++) {
+ struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ int index = attr->index;
+ u16 smask = pb_index_to_mask(index);
+ u8 spage = pb_index_to_page(index);
+ u16 sreg = pb_index_to_reg(index);
+
+ if (reg == sreg && page == spage && (smask & flags)) {
+ dev_dbg(data->dev, "sysfs notify: %s", da->attr.name);
+ sysfs_notify(&data->dev->kobj, NULL, da->attr.name);
+ kobject_uevent(&data->dev->kobj, KOBJ_CHANGE);
+ flags &= ~smask;
+ }
+
+ if (!flags)
+ break;
+ }
+}
+
+static int pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *error,
+ bool notify)
{
const struct pmbus_status_category *cat;
const struct pmbus_status_assoc *bit;
@@ -2764,6 +2791,8 @@ static int pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *error
*error |= bit->rflag;
}

+ if (notify && status)
+ pmbus_notify(data, page, cat->reg, status);
}

/*
@@ -2868,7 +2897,7 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_data *data = i2c_get_clientdata(client);

- return pmbus_get_flags(data, rdev_get_id(rdev), flags);
+ return pmbus_get_flags(data, rdev_get_id(rdev), flags, false);
}

static int pmbus_regulator_get_status(struct regulator_dev *rdev)
@@ -3110,10 +3139,14 @@ static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
{
struct pmbus_data *data = pdata;
struct i2c_client *client = to_i2c_client(data->dev);
- int i, status;
+ int i, status, ret;

- mutex_lock(&data->update_lock);
for (i = 0; i < data->info->pages; i++) {
+ ret = pmbus_get_flags(data, i, &status, true);
+ if (ret)
+ return ret;
+
+ mutex_lock(&data->update_lock);
status = pmbus_read_status_word(client, i);
if (status < 0) {
mutex_unlock(&data->update_lock);
@@ -3122,8 +3155,10 @@ static irqreturn_t pmbus_fault_handler(int irq, void *pdata)

if (status & ~(PB_STATUS_OFF | PB_STATUS_BUSY | PB_STATUS_POWER_GOOD_N))
pmbus_clear_fault_page(client, i);
+
+ mutex_unlock(&data->update_lock);
}
- mutex_unlock(&data->update_lock);
+

return IRQ_HANDLED;
}
--
2.38.1