Commit 85493e6d authored by Guenter Roeck's avatar Guenter Roeck Committed by David S. Miller

sfc: Convert to use hwmon_device_register_with_groups

Simplify the code. Avoid race conditions caused by attributes
being created after hwmon device registration. Implicitly
(through hwmon API) add mandatory 'name' sysfs attribute.
Reviewed-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a0c20fb0
...@@ -75,6 +75,8 @@ struct efx_mcdi_mon { ...@@ -75,6 +75,8 @@ struct efx_mcdi_mon {
unsigned long last_update; unsigned long last_update;
struct device *device; struct device *device;
struct efx_mcdi_mon_attribute *attrs; struct efx_mcdi_mon_attribute *attrs;
struct attribute_group group;
const struct attribute_group *groups[2];
unsigned int n_attrs; unsigned int n_attrs;
}; };
......
...@@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx) ...@@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx)
return rc; return rc;
} }
static ssize_t efx_mcdi_mon_show_name(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", KBUILD_MODNAME);
}
static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index, static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index,
efx_dword_t *entry) efx_dword_t *entry)
{ {
struct efx_nic *efx = dev_get_drvdata(dev); struct efx_nic *efx = dev_get_drvdata(dev->parent);
struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
int rc; int rc;
...@@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev, ...@@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev,
efx_mcdi_sensor_type[mon_attr->type].label); efx_mcdi_sensor_type[mon_attr->type].label);
} }
static int static void
efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
ssize_t (*reader)(struct device *, ssize_t (*reader)(struct device *,
struct device_attribute *, char *), struct device_attribute *, char *),
...@@ -272,7 +265,6 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, ...@@ -272,7 +265,6 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
{ {
struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs]; struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
int rc;
strlcpy(attr->name, name, sizeof(attr->name)); strlcpy(attr->name, name, sizeof(attr->name));
attr->index = index; attr->index = index;
...@@ -286,10 +278,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, ...@@ -286,10 +278,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
attr->dev_attr.attr.name = attr->name; attr->dev_attr.attr.name = attr->name;
attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.attr.mode = S_IRUGO;
attr->dev_attr.show = reader; attr->dev_attr.show = reader;
rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr); hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr;
if (rc == 0)
++hwmon->n_attrs;
return rc;
} }
int efx_mcdi_mon_probe(struct efx_nic *efx) int efx_mcdi_mon_probe(struct efx_nic *efx)
...@@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) ...@@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
efx_mcdi_mon_update(efx); efx_mcdi_mon_update(efx);
/* Allocate space for the maximum possible number of /* Allocate space for the maximum possible number of
* attributes for this set of sensors: name of the driver plus * attributes for this set of sensors:
* value, min, max, crit, alarm and label for each sensor. * value, min, max, crit, alarm and label for each sensor.
*/ */
n_attrs = 1 + 6 * n_sensors; n_attrs = 6 * n_sensors;
hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
if (!hwmon->attrs) { if (!hwmon->attrs) {
rc = -ENOMEM; rc = -ENOMEM;
goto fail; goto fail;
} }
hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
hwmon->device = hwmon_device_register(&efx->pci_dev->dev); GFP_KERNEL);
if (IS_ERR(hwmon->device)) { if (!hwmon->group.attrs) {
rc = PTR_ERR(hwmon->device); rc = -ENOMEM;
goto fail; goto fail;
} }
rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0);
if (rc)
goto fail;
for (i = 0, j = -1, type = -1; ; i++) { for (i = 0, j = -1, type = -1; ; i++) {
enum efx_hwmon_type hwmon_type; enum efx_hwmon_type hwmon_type;
const char *hwmon_prefix; const char *hwmon_prefix;
...@@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) ...@@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
page = type / 32; page = type / 32;
j = -1; j = -1;
if (page == n_pages) if (page == n_pages)
return 0; goto hwmon_register;
MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE,
page); page);
...@@ -453,28 +438,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) ...@@ -453,28 +438,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
if (min1 != max1) { if (min1 != max1) {
snprintf(name, sizeof(name), "%s%u_input", snprintf(name, sizeof(name), "%s%u_input",
hwmon_prefix, hwmon_index); hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr( efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_value, i, type, 0); efx, name, efx_mcdi_mon_show_value, i, type, 0);
if (rc)
goto fail;
if (hwmon_type != EFX_HWMON_POWER) { if (hwmon_type != EFX_HWMON_POWER) {
snprintf(name, sizeof(name), "%s%u_min", snprintf(name, sizeof(name), "%s%u_min",
hwmon_prefix, hwmon_index); hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr( efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit, efx, name, efx_mcdi_mon_show_limit,
i, type, min1); i, type, min1);
if (rc)
goto fail;
} }
snprintf(name, sizeof(name), "%s%u_max", snprintf(name, sizeof(name), "%s%u_max",
hwmon_prefix, hwmon_index); hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr( efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit, efx, name, efx_mcdi_mon_show_limit,
i, type, max1); i, type, max1);
if (rc)
goto fail;
if (min2 != max2) { if (min2 != max2) {
/* Assume max2 is critical value. /* Assume max2 is critical value.
...@@ -482,32 +461,38 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) ...@@ -482,32 +461,38 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
*/ */
snprintf(name, sizeof(name), "%s%u_crit", snprintf(name, sizeof(name), "%s%u_crit",
hwmon_prefix, hwmon_index); hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr( efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit, efx, name, efx_mcdi_mon_show_limit,
i, type, max2); i, type, max2);
if (rc)
goto fail;
} }
} }
snprintf(name, sizeof(name), "%s%u_alarm", snprintf(name, sizeof(name), "%s%u_alarm",
hwmon_prefix, hwmon_index); hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr( efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_alarm, i, type, 0); efx, name, efx_mcdi_mon_show_alarm, i, type, 0);
if (rc)
goto fail;
if (type < ARRAY_SIZE(efx_mcdi_sensor_type) && if (type < ARRAY_SIZE(efx_mcdi_sensor_type) &&
efx_mcdi_sensor_type[type].label) { efx_mcdi_sensor_type[type].label) {
snprintf(name, sizeof(name), "%s%u_label", snprintf(name, sizeof(name), "%s%u_label",
hwmon_prefix, hwmon_index); hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr( efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_label, i, type, 0); efx, name, efx_mcdi_mon_show_label, i, type, 0);
if (rc)
goto fail;
} }
} }
hwmon_register:
hwmon->groups[0] = &hwmon->group;
hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev,
KBUILD_MODNAME, NULL,
hwmon->groups);
if (IS_ERR(hwmon->device)) {
rc = PTR_ERR(hwmon->device);
goto fail;
}
return 0;
fail: fail:
efx_mcdi_mon_remove(efx); efx_mcdi_mon_remove(efx);
return rc; return rc;
...@@ -516,14 +501,11 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) ...@@ -516,14 +501,11 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
void efx_mcdi_mon_remove(struct efx_nic *efx) void efx_mcdi_mon_remove(struct efx_nic *efx)
{ {
struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
unsigned int i;
for (i = 0; i < hwmon->n_attrs; i++)
device_remove_file(&efx->pci_dev->dev,
&hwmon->attrs[i].dev_attr);
kfree(hwmon->attrs);
if (hwmon->device) if (hwmon->device)
hwmon_device_unregister(hwmon->device); hwmon_device_unregister(hwmon->device);
kfree(hwmon->attrs);
kfree(hwmon->group.attrs);
efx_nic_free_buffer(efx, &hwmon->dma_buf); efx_nic_free_buffer(efx, &hwmon->dma_buf);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment