diff options
author | Guenter Roeck <linux@roeck-us.net> | 2013-11-27 21:54:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-29 16:26:16 -0500 |
commit | 85493e6dd42dcaf0eaf0a19f12f1295e35cc3b7f (patch) | |
tree | c6f26f8195e7e54301e71d3727a0c20142d2b08f | |
parent | a0c20fb02592d372e744d1d739cda3e1b3defaae (diff) |
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: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_mon.c | 78 |
2 files changed, 32 insertions, 48 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 656a3277c2b2..15816cacb548 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h | |||
@@ -75,6 +75,8 @@ struct efx_mcdi_mon { | |||
75 | unsigned long last_update; | 75 | unsigned long last_update; |
76 | struct device *device; | 76 | struct device *device; |
77 | struct efx_mcdi_mon_attribute *attrs; | 77 | struct efx_mcdi_mon_attribute *attrs; |
78 | struct attribute_group group; | ||
79 | const struct attribute_group *groups[2]; | ||
78 | unsigned int n_attrs; | 80 | unsigned int n_attrs; |
79 | }; | 81 | }; |
80 | 82 | ||
diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c index 4cc5d95b2a5a..d72ad4fc3617 100644 --- a/drivers/net/ethernet/sfc/mcdi_mon.c +++ b/drivers/net/ethernet/sfc/mcdi_mon.c | |||
@@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx) | |||
139 | return rc; | 139 | return rc; |
140 | } | 140 | } |
141 | 141 | ||
142 | static ssize_t efx_mcdi_mon_show_name(struct device *dev, | ||
143 | struct device_attribute *attr, | ||
144 | char *buf) | ||
145 | { | ||
146 | return sprintf(buf, "%s\n", KBUILD_MODNAME); | ||
147 | } | ||
148 | |||
149 | static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index, | 142 | static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index, |
150 | efx_dword_t *entry) | 143 | efx_dword_t *entry) |
151 | { | 144 | { |
152 | struct efx_nic *efx = dev_get_drvdata(dev); | 145 | struct efx_nic *efx = dev_get_drvdata(dev->parent); |
153 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); | 146 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); |
154 | int rc; | 147 | int rc; |
155 | 148 | ||
@@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev, | |||
263 | efx_mcdi_sensor_type[mon_attr->type].label); | 256 | efx_mcdi_sensor_type[mon_attr->type].label); |
264 | } | 257 | } |
265 | 258 | ||
266 | static int | 259 | static void |
267 | efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, | 260 | efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, |
268 | ssize_t (*reader)(struct device *, | 261 | ssize_t (*reader)(struct device *, |
269 | struct device_attribute *, char *), | 262 | struct device_attribute *, char *), |
@@ -272,7 +265,6 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, | |||
272 | { | 265 | { |
273 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); | 266 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); |
274 | struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs]; | 267 | struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs]; |
275 | int rc; | ||
276 | 268 | ||
277 | strlcpy(attr->name, name, sizeof(attr->name)); | 269 | strlcpy(attr->name, name, sizeof(attr->name)); |
278 | attr->index = index; | 270 | attr->index = index; |
@@ -286,10 +278,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, | |||
286 | attr->dev_attr.attr.name = attr->name; | 278 | attr->dev_attr.attr.name = attr->name; |
287 | attr->dev_attr.attr.mode = S_IRUGO; | 279 | attr->dev_attr.attr.mode = S_IRUGO; |
288 | attr->dev_attr.show = reader; | 280 | attr->dev_attr.show = reader; |
289 | rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr); | 281 | hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr; |
290 | if (rc == 0) | ||
291 | ++hwmon->n_attrs; | ||
292 | return rc; | ||
293 | } | 282 | } |
294 | 283 | ||
295 | int efx_mcdi_mon_probe(struct efx_nic *efx) | 284 | int efx_mcdi_mon_probe(struct efx_nic *efx) |
@@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
338 | efx_mcdi_mon_update(efx); | 327 | efx_mcdi_mon_update(efx); |
339 | 328 | ||
340 | /* Allocate space for the maximum possible number of | 329 | /* Allocate space for the maximum possible number of |
341 | * attributes for this set of sensors: name of the driver plus | 330 | * attributes for this set of sensors: |
342 | * value, min, max, crit, alarm and label for each sensor. | 331 | * value, min, max, crit, alarm and label for each sensor. |
343 | */ | 332 | */ |
344 | n_attrs = 1 + 6 * n_sensors; | 333 | n_attrs = 6 * n_sensors; |
345 | hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); | 334 | hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); |
346 | if (!hwmon->attrs) { | 335 | if (!hwmon->attrs) { |
347 | rc = -ENOMEM; | 336 | rc = -ENOMEM; |
348 | goto fail; | 337 | goto fail; |
349 | } | 338 | } |
350 | 339 | hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *), | |
351 | hwmon->device = hwmon_device_register(&efx->pci_dev->dev); | 340 | GFP_KERNEL); |
352 | if (IS_ERR(hwmon->device)) { | 341 | if (!hwmon->group.attrs) { |
353 | rc = PTR_ERR(hwmon->device); | 342 | rc = -ENOMEM; |
354 | goto fail; | 343 | goto fail; |
355 | } | 344 | } |
356 | 345 | ||
357 | rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0); | ||
358 | if (rc) | ||
359 | goto fail; | ||
360 | |||
361 | for (i = 0, j = -1, type = -1; ; i++) { | 346 | for (i = 0, j = -1, type = -1; ; i++) { |
362 | enum efx_hwmon_type hwmon_type; | 347 | enum efx_hwmon_type hwmon_type; |
363 | const char *hwmon_prefix; | 348 | const char *hwmon_prefix; |
@@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
372 | page = type / 32; | 357 | page = type / 32; |
373 | j = -1; | 358 | j = -1; |
374 | if (page == n_pages) | 359 | if (page == n_pages) |
375 | return 0; | 360 | goto hwmon_register; |
376 | 361 | ||
377 | MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, | 362 | MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, |
378 | page); | 363 | page); |
@@ -453,28 +438,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
453 | if (min1 != max1) { | 438 | if (min1 != max1) { |
454 | snprintf(name, sizeof(name), "%s%u_input", | 439 | snprintf(name, sizeof(name), "%s%u_input", |
455 | hwmon_prefix, hwmon_index); | 440 | hwmon_prefix, hwmon_index); |
456 | rc = efx_mcdi_mon_add_attr( | 441 | efx_mcdi_mon_add_attr( |
457 | efx, name, efx_mcdi_mon_show_value, i, type, 0); | 442 | efx, name, efx_mcdi_mon_show_value, i, type, 0); |
458 | if (rc) | ||
459 | goto fail; | ||
460 | 443 | ||
461 | if (hwmon_type != EFX_HWMON_POWER) { | 444 | if (hwmon_type != EFX_HWMON_POWER) { |
462 | snprintf(name, sizeof(name), "%s%u_min", | 445 | snprintf(name, sizeof(name), "%s%u_min", |
463 | hwmon_prefix, hwmon_index); | 446 | hwmon_prefix, hwmon_index); |
464 | rc = efx_mcdi_mon_add_attr( | 447 | efx_mcdi_mon_add_attr( |
465 | efx, name, efx_mcdi_mon_show_limit, | 448 | efx, name, efx_mcdi_mon_show_limit, |
466 | i, type, min1); | 449 | i, type, min1); |
467 | if (rc) | ||
468 | goto fail; | ||
469 | } | 450 | } |
470 | 451 | ||
471 | snprintf(name, sizeof(name), "%s%u_max", | 452 | snprintf(name, sizeof(name), "%s%u_max", |
472 | hwmon_prefix, hwmon_index); | 453 | hwmon_prefix, hwmon_index); |
473 | rc = efx_mcdi_mon_add_attr( | 454 | efx_mcdi_mon_add_attr( |
474 | efx, name, efx_mcdi_mon_show_limit, | 455 | efx, name, efx_mcdi_mon_show_limit, |
475 | i, type, max1); | 456 | i, type, max1); |
476 | if (rc) | ||
477 | goto fail; | ||
478 | 457 | ||
479 | if (min2 != max2) { | 458 | if (min2 != max2) { |
480 | /* Assume max2 is critical value. | 459 | /* Assume max2 is critical value. |
@@ -482,32 +461,38 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
482 | */ | 461 | */ |
483 | snprintf(name, sizeof(name), "%s%u_crit", | 462 | snprintf(name, sizeof(name), "%s%u_crit", |
484 | hwmon_prefix, hwmon_index); | 463 | hwmon_prefix, hwmon_index); |
485 | rc = efx_mcdi_mon_add_attr( | 464 | efx_mcdi_mon_add_attr( |
486 | efx, name, efx_mcdi_mon_show_limit, | 465 | efx, name, efx_mcdi_mon_show_limit, |
487 | i, type, max2); | 466 | i, type, max2); |
488 | if (rc) | ||
489 | goto fail; | ||
490 | } | 467 | } |
491 | } | 468 | } |
492 | 469 | ||
493 | snprintf(name, sizeof(name), "%s%u_alarm", | 470 | snprintf(name, sizeof(name), "%s%u_alarm", |
494 | hwmon_prefix, hwmon_index); | 471 | hwmon_prefix, hwmon_index); |
495 | rc = efx_mcdi_mon_add_attr( | 472 | efx_mcdi_mon_add_attr( |
496 | efx, name, efx_mcdi_mon_show_alarm, i, type, 0); | 473 | efx, name, efx_mcdi_mon_show_alarm, i, type, 0); |
497 | if (rc) | ||
498 | goto fail; | ||
499 | 474 | ||
500 | if (type < ARRAY_SIZE(efx_mcdi_sensor_type) && | 475 | if (type < ARRAY_SIZE(efx_mcdi_sensor_type) && |
501 | efx_mcdi_sensor_type[type].label) { | 476 | efx_mcdi_sensor_type[type].label) { |
502 | snprintf(name, sizeof(name), "%s%u_label", | 477 | snprintf(name, sizeof(name), "%s%u_label", |
503 | hwmon_prefix, hwmon_index); | 478 | hwmon_prefix, hwmon_index); |
504 | rc = efx_mcdi_mon_add_attr( | 479 | efx_mcdi_mon_add_attr( |
505 | efx, name, efx_mcdi_mon_show_label, i, type, 0); | 480 | efx, name, efx_mcdi_mon_show_label, i, type, 0); |
506 | if (rc) | ||
507 | goto fail; | ||
508 | } | 481 | } |
509 | } | 482 | } |
510 | 483 | ||
484 | hwmon_register: | ||
485 | hwmon->groups[0] = &hwmon->group; | ||
486 | hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev, | ||
487 | KBUILD_MODNAME, NULL, | ||
488 | hwmon->groups); | ||
489 | if (IS_ERR(hwmon->device)) { | ||
490 | rc = PTR_ERR(hwmon->device); | ||
491 | goto fail; | ||
492 | } | ||
493 | |||
494 | return 0; | ||
495 | |||
511 | fail: | 496 | fail: |
512 | efx_mcdi_mon_remove(efx); | 497 | efx_mcdi_mon_remove(efx); |
513 | return rc; | 498 | return rc; |
@@ -516,14 +501,11 @@ fail: | |||
516 | void efx_mcdi_mon_remove(struct efx_nic *efx) | 501 | void efx_mcdi_mon_remove(struct efx_nic *efx) |
517 | { | 502 | { |
518 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); | 503 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); |
519 | unsigned int i; | ||
520 | 504 | ||
521 | for (i = 0; i < hwmon->n_attrs; i++) | ||
522 | device_remove_file(&efx->pci_dev->dev, | ||
523 | &hwmon->attrs[i].dev_attr); | ||
524 | kfree(hwmon->attrs); | ||
525 | if (hwmon->device) | 505 | if (hwmon->device) |
526 | hwmon_device_unregister(hwmon->device); | 506 | hwmon_device_unregister(hwmon->device); |
507 | kfree(hwmon->attrs); | ||
508 | kfree(hwmon->group.attrs); | ||
527 | efx_nic_free_buffer(efx, &hwmon->dma_buf); | 509 | efx_nic_free_buffer(efx, &hwmon->dma_buf); |
528 | } | 510 | } |
529 | 511 | ||