Skip to content

Commit

Permalink
sfc: Convert to use hwmon_device_register_with_groups
Browse files Browse the repository at this point in the history
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: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Guenter Roeck authored and David S. Miller committed Nov 29, 2013
1 parent a0c20fb commit 85493e6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 48 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/sfc/mcdi.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ struct efx_mcdi_mon {
unsigned long last_update;
struct device *device;
struct efx_mcdi_mon_attribute *attrs;
struct attribute_group group;
const struct attribute_group *groups[2];
unsigned int n_attrs;
};

Expand Down
78 changes: 30 additions & 48 deletions drivers/net/ethernet/sfc/mcdi_mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx)
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,
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);
int rc;

Expand Down Expand Up @@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev,
efx_mcdi_sensor_type[mon_attr->type].label);
}

static int
static void
efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
ssize_t (*reader)(struct device *,
struct device_attribute *, char *),
Expand All @@ -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_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
int rc;

strlcpy(attr->name, name, sizeof(attr->name));
attr->index = index;
Expand All @@ -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.mode = S_IRUGO;
attr->dev_attr.show = reader;
rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr);
if (rc == 0)
++hwmon->n_attrs;
return rc;
hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr;
}

int efx_mcdi_mon_probe(struct efx_nic *efx)
Expand Down Expand Up @@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
efx_mcdi_mon_update(efx);

/* 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.
*/
n_attrs = 1 + 6 * n_sensors;
n_attrs = 6 * n_sensors;
hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
if (!hwmon->attrs) {
rc = -ENOMEM;
goto fail;
}

hwmon->device = hwmon_device_register(&efx->pci_dev->dev);
if (IS_ERR(hwmon->device)) {
rc = PTR_ERR(hwmon->device);
hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
GFP_KERNEL);
if (!hwmon->group.attrs) {
rc = -ENOMEM;
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++) {
enum efx_hwmon_type hwmon_type;
const char *hwmon_prefix;
Expand All @@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
page = type / 32;
j = -1;
if (page == n_pages)
return 0;
goto hwmon_register;

MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE,
page);
Expand Down Expand Up @@ -453,61 +438,61 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
if (min1 != max1) {
snprintf(name, sizeof(name), "%s%u_input",
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);
if (rc)
goto fail;

if (hwmon_type != EFX_HWMON_POWER) {
snprintf(name, sizeof(name), "%s%u_min",
hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr(
efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit,
i, type, min1);
if (rc)
goto fail;
}

snprintf(name, sizeof(name), "%s%u_max",
hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr(
efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit,
i, type, max1);
if (rc)
goto fail;

if (min2 != max2) {
/* Assume max2 is critical value.
* But we have no good way to expose min2.
*/
snprintf(name, sizeof(name), "%s%u_crit",
hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr(
efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit,
i, type, max2);
if (rc)
goto fail;
}
}

snprintf(name, sizeof(name), "%s%u_alarm",
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);
if (rc)
goto fail;

if (type < ARRAY_SIZE(efx_mcdi_sensor_type) &&
efx_mcdi_sensor_type[type].label) {
snprintf(name, sizeof(name), "%s%u_label",
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);
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:
efx_mcdi_mon_remove(efx);
return rc;
Expand All @@ -516,14 +501,11 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
void efx_mcdi_mon_remove(struct efx_nic *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)
hwmon_device_unregister(hwmon->device);
kfree(hwmon->attrs);
kfree(hwmon->group.attrs);
efx_nic_free_buffer(efx, &hwmon->dma_buf);
}

Expand Down

0 comments on commit 85493e6

Please sign in to comment.