1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Power capping class 4 * Copyright (c) 2013, Intel Corporation. 5 */ 6 7 #include <linux/module.h> 8 #include <linux/device.h> 9 #include <linux/err.h> 10 #include <linux/kstrtox.h> 11 #include <linux/slab.h> 12 #include <linux/powercap.h> 13 14 #define to_powercap_zone(n) container_of(n, struct powercap_zone, dev) 15 #define to_powercap_control_type(n) \ 16 container_of(n, struct powercap_control_type, dev) 17 18 /* Power zone show function */ 19 #define define_power_zone_show(_attr) \ 20 static ssize_t _attr##_show(struct device *dev, \ 21 struct device_attribute *dev_attr,\ 22 char *buf) \ 23 { \ 24 u64 value; \ 25 ssize_t len = -EINVAL; \ 26 struct powercap_zone *power_zone = to_powercap_zone(dev); \ 27 \ 28 if (power_zone->ops->get_##_attr) { \ 29 if (!power_zone->ops->get_##_attr(power_zone, &value)) \ 30 len = sysfs_emit(buf, "%lld\n", value); \ 31 } \ 32 \ 33 return len; \ 34 } 35 36 /* The only meaningful input is 0 (reset), others are silently ignored */ 37 #define define_power_zone_store(_attr) \ 38 static ssize_t _attr##_store(struct device *dev,\ 39 struct device_attribute *dev_attr, \ 40 const char *buf, size_t count) \ 41 { \ 42 int err; \ 43 struct powercap_zone *power_zone = to_powercap_zone(dev); \ 44 u64 value; \ 45 \ 46 err = kstrtoull(buf, 10, &value); \ 47 if (err) \ 48 return -EINVAL; \ 49 if (value) \ 50 return count; \ 51 if (power_zone->ops->reset_##_attr) { \ 52 if (!power_zone->ops->reset_##_attr(power_zone)) \ 53 return count; \ 54 } \ 55 \ 56 return -EINVAL; \ 57 } 58 59 /* Power zone constraint show function */ 60 #define define_power_zone_constraint_show(_attr) \ 61 static ssize_t show_constraint_##_attr(struct device *dev, \ 62 struct device_attribute *dev_attr,\ 63 char *buf) \ 64 { \ 65 u64 value; \ 66 ssize_t len = -ENODATA; \ 67 struct powercap_zone *power_zone = to_powercap_zone(dev); \ 68 int id; \ 69 struct powercap_zone_constraint *pconst;\ 70 \ 71 if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \ 72 return -EINVAL; \ 73 if (id >= power_zone->const_id_cnt) \ 74 return -EINVAL; \ 75 pconst = &power_zone->constraints[id]; \ 76 if (pconst && pconst->ops && pconst->ops->get_##_attr) { \ 77 if (!pconst->ops->get_##_attr(power_zone, id, &value)) \ 78 len = sysfs_emit(buf, "%lld\n", value); \ 79 } \ 80 \ 81 return len; \ 82 } 83 84 /* Power zone constraint store function */ 85 #define define_power_zone_constraint_store(_attr) \ 86 static ssize_t store_constraint_##_attr(struct device *dev,\ 87 struct device_attribute *dev_attr, \ 88 const char *buf, size_t count) \ 89 { \ 90 int err; \ 91 u64 value; \ 92 struct powercap_zone *power_zone = to_powercap_zone(dev); \ 93 int id; \ 94 struct powercap_zone_constraint *pconst;\ 95 \ 96 if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \ 97 return -EINVAL; \ 98 if (id >= power_zone->const_id_cnt) \ 99 return -EINVAL; \ 100 pconst = &power_zone->constraints[id]; \ 101 err = kstrtoull(buf, 10, &value); \ 102 if (err) \ 103 return -EINVAL; \ 104 if (pconst && pconst->ops && pconst->ops->set_##_attr) { \ 105 if (!pconst->ops->set_##_attr(power_zone, id, value)) \ 106 return count; \ 107 } \ 108 \ 109 return -ENODATA; \ 110 } 111 112 /* Power zone information callbacks */ 113 define_power_zone_show(power_uw); 114 define_power_zone_show(max_power_range_uw); 115 define_power_zone_show(energy_uj); 116 define_power_zone_store(energy_uj); 117 define_power_zone_show(max_energy_range_uj); 118 119 /* Power zone attributes */ 120 static DEVICE_ATTR_RO(max_power_range_uw); 121 static DEVICE_ATTR_RO(power_uw); 122 static DEVICE_ATTR_RO(max_energy_range_uj); 123 static DEVICE_ATTR_RW(energy_uj); 124 125 /* Power zone constraint attributes callbacks */ 126 define_power_zone_constraint_show(power_limit_uw); 127 define_power_zone_constraint_store(power_limit_uw); 128 define_power_zone_constraint_show(time_window_us); 129 define_power_zone_constraint_store(time_window_us); 130 define_power_zone_constraint_show(max_power_uw); 131 define_power_zone_constraint_show(min_power_uw); 132 define_power_zone_constraint_show(max_time_window_us); 133 define_power_zone_constraint_show(min_time_window_us); 134 135 /* For one time seeding of constraint device attributes */ 136 struct powercap_constraint_attr { 137 struct device_attribute power_limit_attr; 138 struct device_attribute time_window_attr; 139 struct device_attribute max_power_attr; 140 struct device_attribute min_power_attr; 141 struct device_attribute max_time_window_attr; 142 struct device_attribute min_time_window_attr; 143 struct device_attribute name_attr; 144 }; 145 146 static struct powercap_constraint_attr 147 constraint_attrs[MAX_CONSTRAINTS_PER_ZONE]; 148 149 /* A list of powercap control_types */ 150 static LIST_HEAD(powercap_cntrl_list); 151 /* Mutex to protect list of powercap control_types */ 152 static DEFINE_MUTEX(powercap_cntrl_list_lock); 153 154 #define POWERCAP_CONSTRAINT_NAME_LEN 30 /* Some limit to avoid overflow */ 155 static ssize_t show_constraint_name(struct device *dev, 156 struct device_attribute *dev_attr, 157 char *buf) 158 { 159 const char *name; 160 struct powercap_zone *power_zone = to_powercap_zone(dev); 161 int id; 162 ssize_t len = -ENODATA; 163 struct powercap_zone_constraint *pconst; 164 165 if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) 166 return -EINVAL; 167 if (id >= power_zone->const_id_cnt) 168 return -EINVAL; 169 pconst = &power_zone->constraints[id]; 170 171 if (pconst && pconst->ops && pconst->ops->get_name) { 172 name = pconst->ops->get_name(power_zone, id); 173 if (name) { 174 len = sysfs_emit(buf, "%.*s\n", 175 POWERCAP_CONSTRAINT_NAME_LEN - 1, name); 176 } 177 } 178 179 return len; 180 } 181 182 static int create_constraint_attribute(int id, const char *name, 183 int mode, 184 struct device_attribute *dev_attr, 185 ssize_t (*show)(struct device *, 186 struct device_attribute *, char *), 187 ssize_t (*store)(struct device *, 188 struct device_attribute *, 189 const char *, size_t) 190 ) 191 { 192 193 dev_attr->attr.name = kasprintf(GFP_KERNEL, "constraint_%d_%s", 194 id, name); 195 if (!dev_attr->attr.name) 196 return -ENOMEM; 197 dev_attr->attr.mode = mode; 198 dev_attr->show = show; 199 dev_attr->store = store; 200 201 return 0; 202 } 203 204 static void free_constraint_attributes(void) 205 { 206 int i; 207 208 for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) { 209 kfree(constraint_attrs[i].power_limit_attr.attr.name); 210 kfree(constraint_attrs[i].time_window_attr.attr.name); 211 kfree(constraint_attrs[i].name_attr.attr.name); 212 kfree(constraint_attrs[i].max_power_attr.attr.name); 213 kfree(constraint_attrs[i].min_power_attr.attr.name); 214 kfree(constraint_attrs[i].max_time_window_attr.attr.name); 215 kfree(constraint_attrs[i].min_time_window_attr.attr.name); 216 } 217 } 218 219 static int seed_constraint_attributes(void) 220 { 221 int i; 222 int ret; 223 224 for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) { 225 ret = create_constraint_attribute(i, "power_limit_uw", 226 S_IWUSR | S_IRUGO, 227 &constraint_attrs[i].power_limit_attr, 228 show_constraint_power_limit_uw, 229 store_constraint_power_limit_uw); 230 if (ret) 231 goto err_alloc; 232 ret = create_constraint_attribute(i, "time_window_us", 233 S_IWUSR | S_IRUGO, 234 &constraint_attrs[i].time_window_attr, 235 show_constraint_time_window_us, 236 store_constraint_time_window_us); 237 if (ret) 238 goto err_alloc; 239 ret = create_constraint_attribute(i, "name", S_IRUGO, 240 &constraint_attrs[i].name_attr, 241 show_constraint_name, 242 NULL); 243 if (ret) 244 goto err_alloc; 245 ret = create_constraint_attribute(i, "max_power_uw", S_IRUGO, 246 &constraint_attrs[i].max_power_attr, 247 show_constraint_max_power_uw, 248 NULL); 249 if (ret) 250 goto err_alloc; 251 ret = create_constraint_attribute(i, "min_power_uw", S_IRUGO, 252 &constraint_attrs[i].min_power_attr, 253 show_constraint_min_power_uw, 254 NULL); 255 if (ret) 256 goto err_alloc; 257 ret = create_constraint_attribute(i, "max_time_window_us", 258 S_IRUGO, 259 &constraint_attrs[i].max_time_window_attr, 260 show_constraint_max_time_window_us, 261 NULL); 262 if (ret) 263 goto err_alloc; 264 ret = create_constraint_attribute(i, "min_time_window_us", 265 S_IRUGO, 266 &constraint_attrs[i].min_time_window_attr, 267 show_constraint_min_time_window_us, 268 NULL); 269 if (ret) 270 goto err_alloc; 271 272 } 273 274 return 0; 275 276 err_alloc: 277 free_constraint_attributes(); 278 279 return ret; 280 } 281 282 static int create_constraints(struct powercap_zone *power_zone, 283 int nr_constraints, 284 const struct powercap_zone_constraint_ops *const_ops) 285 { 286 int i; 287 int ret = 0; 288 int count; 289 struct powercap_zone_constraint *pconst; 290 291 if (!power_zone || !const_ops || !const_ops->get_power_limit_uw || 292 !const_ops->set_power_limit_uw || 293 !const_ops->get_time_window_us || 294 !const_ops->set_time_window_us) 295 return -EINVAL; 296 297 count = power_zone->zone_attr_count; 298 for (i = 0; i < nr_constraints; ++i) { 299 pconst = &power_zone->constraints[i]; 300 pconst->ops = const_ops; 301 pconst->id = power_zone->const_id_cnt; 302 power_zone->const_id_cnt++; 303 power_zone->zone_dev_attrs[count++] = 304 &constraint_attrs[i].power_limit_attr.attr; 305 power_zone->zone_dev_attrs[count++] = 306 &constraint_attrs[i].time_window_attr.attr; 307 if (pconst->ops->get_name) 308 power_zone->zone_dev_attrs[count++] = 309 &constraint_attrs[i].name_attr.attr; 310 if (pconst->ops->get_max_power_uw) 311 power_zone->zone_dev_attrs[count++] = 312 &constraint_attrs[i].max_power_attr.attr; 313 if (pconst->ops->get_min_power_uw) 314 power_zone->zone_dev_attrs[count++] = 315 &constraint_attrs[i].min_power_attr.attr; 316 if (pconst->ops->get_max_time_window_us) 317 power_zone->zone_dev_attrs[count++] = 318 &constraint_attrs[i].max_time_window_attr.attr; 319 if (pconst->ops->get_min_time_window_us) 320 power_zone->zone_dev_attrs[count++] = 321 &constraint_attrs[i].min_time_window_attr.attr; 322 } 323 power_zone->zone_attr_count = count; 324 325 return ret; 326 } 327 328 static bool control_type_valid(void *control_type) 329 { 330 struct powercap_control_type *pos = NULL; 331 bool found = false; 332 333 mutex_lock(&powercap_cntrl_list_lock); 334 335 list_for_each_entry(pos, &powercap_cntrl_list, node) { 336 if (pos == control_type) { 337 found = true; 338 break; 339 } 340 } 341 mutex_unlock(&powercap_cntrl_list_lock); 342 343 return found; 344 } 345 346 static ssize_t name_show(struct device *dev, 347 struct device_attribute *attr, 348 char *buf) 349 { 350 struct powercap_zone *power_zone = to_powercap_zone(dev); 351 352 return sysfs_emit(buf, "%s\n", power_zone->name); 353 } 354 355 static DEVICE_ATTR_RO(name); 356 357 /* Create zone and attributes in sysfs */ 358 static void create_power_zone_common_attributes( 359 struct powercap_zone *power_zone) 360 { 361 int count = 0; 362 363 power_zone->zone_dev_attrs[count++] = &dev_attr_name.attr; 364 if (power_zone->ops->get_max_energy_range_uj) 365 power_zone->zone_dev_attrs[count++] = 366 &dev_attr_max_energy_range_uj.attr; 367 if (power_zone->ops->get_energy_uj) { 368 if (power_zone->ops->reset_energy_uj) 369 dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUSR; 370 else 371 dev_attr_energy_uj.attr.mode = S_IRUSR; 372 power_zone->zone_dev_attrs[count++] = 373 &dev_attr_energy_uj.attr; 374 } 375 if (power_zone->ops->get_power_uw) 376 power_zone->zone_dev_attrs[count++] = 377 &dev_attr_power_uw.attr; 378 if (power_zone->ops->get_max_power_range_uw) 379 power_zone->zone_dev_attrs[count++] = 380 &dev_attr_max_power_range_uw.attr; 381 power_zone->zone_dev_attrs[count] = NULL; 382 power_zone->zone_attr_count = count; 383 } 384 385 static void powercap_release(struct device *dev) 386 { 387 bool allocated; 388 389 if (dev->parent) { 390 struct powercap_zone *power_zone = to_powercap_zone(dev); 391 392 /* Store flag as the release() may free memory */ 393 allocated = power_zone->allocated; 394 /* Remove id from parent idr struct */ 395 idr_remove(power_zone->parent_idr, power_zone->id); 396 /* Destroy idrs allocated for this zone */ 397 idr_destroy(&power_zone->idr); 398 kfree(power_zone->name); 399 kfree(power_zone->zone_dev_attrs); 400 kfree(power_zone->constraints); 401 if (power_zone->ops->release) 402 power_zone->ops->release(power_zone); 403 if (allocated) 404 kfree(power_zone); 405 } else { 406 struct powercap_control_type *control_type = 407 to_powercap_control_type(dev); 408 409 /* Store flag as the release() may free memory */ 410 allocated = control_type->allocated; 411 idr_destroy(&control_type->idr); 412 mutex_destroy(&control_type->lock); 413 if (control_type->ops && control_type->ops->release) 414 control_type->ops->release(control_type); 415 if (allocated) 416 kfree(control_type); 417 } 418 } 419 420 static ssize_t enabled_show(struct device *dev, 421 struct device_attribute *attr, 422 char *buf) 423 { 424 bool mode = true; 425 426 /* Default is enabled */ 427 if (dev->parent) { 428 struct powercap_zone *power_zone = to_powercap_zone(dev); 429 if (power_zone->ops->get_enable) 430 if (power_zone->ops->get_enable(power_zone, &mode)) 431 mode = false; 432 } else { 433 struct powercap_control_type *control_type = 434 to_powercap_control_type(dev); 435 if (control_type->ops && control_type->ops->get_enable) 436 if (control_type->ops->get_enable(control_type, &mode)) 437 mode = false; 438 } 439 440 return sysfs_emit(buf, "%d\n", mode); 441 } 442 443 static ssize_t enabled_store(struct device *dev, 444 struct device_attribute *attr, 445 const char *buf, size_t len) 446 { 447 bool mode; 448 449 if (kstrtobool(buf, &mode)) 450 return -EINVAL; 451 if (dev->parent) { 452 struct powercap_zone *power_zone = to_powercap_zone(dev); 453 if (power_zone->ops->set_enable) 454 if (!power_zone->ops->set_enable(power_zone, mode)) 455 return len; 456 } else { 457 struct powercap_control_type *control_type = 458 to_powercap_control_type(dev); 459 if (control_type->ops && control_type->ops->set_enable) 460 if (!control_type->ops->set_enable(control_type, mode)) 461 return len; 462 } 463 464 return -ENOSYS; 465 } 466 467 static DEVICE_ATTR_RW(enabled); 468 469 static struct attribute *powercap_attrs[] = { 470 &dev_attr_enabled.attr, 471 NULL, 472 }; 473 ATTRIBUTE_GROUPS(powercap); 474 475 static struct class powercap_class = { 476 .name = "powercap", 477 .dev_release = powercap_release, 478 .dev_groups = powercap_groups, 479 }; 480 481 struct powercap_zone *powercap_register_zone( 482 struct powercap_zone *power_zone, 483 struct powercap_control_type *control_type, 484 const char *name, 485 struct powercap_zone *parent, 486 const struct powercap_zone_ops *ops, 487 int nr_constraints, 488 const struct powercap_zone_constraint_ops *const_ops) 489 { 490 int result; 491 int nr_attrs; 492 493 if (!name || !control_type || !ops || 494 nr_constraints > MAX_CONSTRAINTS_PER_ZONE || 495 (!ops->get_energy_uj && !ops->get_power_uw) || 496 !control_type_valid(control_type)) 497 return ERR_PTR(-EINVAL); 498 499 if (power_zone) { 500 if (!ops->release) 501 return ERR_PTR(-EINVAL); 502 memset(power_zone, 0, sizeof(*power_zone)); 503 } else { 504 power_zone = kzalloc(sizeof(*power_zone), GFP_KERNEL); 505 if (!power_zone) 506 return ERR_PTR(-ENOMEM); 507 power_zone->allocated = true; 508 } 509 power_zone->ops = ops; 510 power_zone->control_type_inst = control_type; 511 if (!parent) { 512 power_zone->dev.parent = &control_type->dev; 513 power_zone->parent_idr = &control_type->idr; 514 } else { 515 power_zone->dev.parent = &parent->dev; 516 power_zone->parent_idr = &parent->idr; 517 } 518 power_zone->dev.class = &powercap_class; 519 520 mutex_lock(&control_type->lock); 521 /* Using idr to get the unique id */ 522 result = idr_alloc(power_zone->parent_idr, NULL, 0, 0, GFP_KERNEL); 523 if (result < 0) 524 goto err_idr_alloc; 525 526 power_zone->id = result; 527 idr_init(&power_zone->idr); 528 result = -ENOMEM; 529 power_zone->name = kstrdup(name, GFP_KERNEL); 530 if (!power_zone->name) 531 goto err_name_alloc; 532 power_zone->constraints = kcalloc(nr_constraints, 533 sizeof(*power_zone->constraints), 534 GFP_KERNEL); 535 if (!power_zone->constraints) 536 goto err_const_alloc; 537 538 nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS + 539 POWERCAP_ZONE_MAX_ATTRS + 1; 540 power_zone->zone_dev_attrs = kcalloc(nr_attrs, sizeof(void *), 541 GFP_KERNEL); 542 if (!power_zone->zone_dev_attrs) 543 goto err_attr_alloc; 544 create_power_zone_common_attributes(power_zone); 545 result = create_constraints(power_zone, nr_constraints, const_ops); 546 if (result) 547 goto err_dev_ret; 548 549 power_zone->zone_dev_attrs[power_zone->zone_attr_count] = NULL; 550 power_zone->dev_zone_attr_group.attrs = power_zone->zone_dev_attrs; 551 power_zone->dev_attr_groups[0] = &power_zone->dev_zone_attr_group; 552 power_zone->dev_attr_groups[1] = NULL; 553 power_zone->dev.groups = power_zone->dev_attr_groups; 554 dev_set_name(&power_zone->dev, "%s:%x", 555 dev_name(power_zone->dev.parent), 556 power_zone->id); 557 result = device_register(&power_zone->dev); 558 if (result) { 559 put_device(&power_zone->dev); 560 mutex_unlock(&control_type->lock); 561 562 return ERR_PTR(result); 563 } 564 565 control_type->nr_zones++; 566 mutex_unlock(&control_type->lock); 567 568 return power_zone; 569 570 err_dev_ret: 571 kfree(power_zone->zone_dev_attrs); 572 err_attr_alloc: 573 kfree(power_zone->constraints); 574 err_const_alloc: 575 kfree(power_zone->name); 576 err_name_alloc: 577 idr_remove(power_zone->parent_idr, power_zone->id); 578 err_idr_alloc: 579 if (power_zone->allocated) 580 kfree(power_zone); 581 mutex_unlock(&control_type->lock); 582 583 return ERR_PTR(result); 584 } 585 EXPORT_SYMBOL_GPL(powercap_register_zone); 586 587 int powercap_unregister_zone(struct powercap_control_type *control_type, 588 struct powercap_zone *power_zone) 589 { 590 if (!power_zone || !control_type) 591 return -EINVAL; 592 593 mutex_lock(&control_type->lock); 594 control_type->nr_zones--; 595 mutex_unlock(&control_type->lock); 596 597 device_unregister(&power_zone->dev); 598 599 return 0; 600 } 601 EXPORT_SYMBOL_GPL(powercap_unregister_zone); 602 603 struct powercap_control_type *powercap_register_control_type( 604 struct powercap_control_type *control_type, 605 const char *name, 606 const struct powercap_control_type_ops *ops) 607 { 608 int result; 609 610 if (!name) 611 return ERR_PTR(-EINVAL); 612 if (control_type) { 613 if (!ops || !ops->release) 614 return ERR_PTR(-EINVAL); 615 memset(control_type, 0, sizeof(*control_type)); 616 } else { 617 control_type = kzalloc(sizeof(*control_type), GFP_KERNEL); 618 if (!control_type) 619 return ERR_PTR(-ENOMEM); 620 control_type->allocated = true; 621 } 622 mutex_init(&control_type->lock); 623 control_type->ops = ops; 624 INIT_LIST_HEAD(&control_type->node); 625 control_type->dev.class = &powercap_class; 626 dev_set_name(&control_type->dev, "%s", name); 627 idr_init(&control_type->idr); 628 629 mutex_lock(&powercap_cntrl_list_lock); 630 list_add_tail(&control_type->node, &powercap_cntrl_list); 631 mutex_unlock(&powercap_cntrl_list_lock); 632 633 result = device_register(&control_type->dev); 634 if (result) { 635 mutex_lock(&powercap_cntrl_list_lock); 636 list_del(&control_type->node); 637 mutex_unlock(&powercap_cntrl_list_lock); 638 639 idr_destroy(&control_type->idr); 640 put_device(&control_type->dev); 641 return ERR_PTR(result); 642 } 643 644 return control_type; 645 } 646 EXPORT_SYMBOL_GPL(powercap_register_control_type); 647 648 int powercap_unregister_control_type(struct powercap_control_type *control_type) 649 { 650 struct powercap_control_type *pos = NULL; 651 652 if (control_type->nr_zones) { 653 dev_err(&control_type->dev, "Zones of this type still not freed\n"); 654 return -EINVAL; 655 } 656 mutex_lock(&powercap_cntrl_list_lock); 657 list_for_each_entry(pos, &powercap_cntrl_list, node) { 658 if (pos == control_type) { 659 list_del(&control_type->node); 660 mutex_unlock(&powercap_cntrl_list_lock); 661 device_unregister(&control_type->dev); 662 return 0; 663 } 664 } 665 mutex_unlock(&powercap_cntrl_list_lock); 666 667 return -ENODEV; 668 } 669 EXPORT_SYMBOL_GPL(powercap_unregister_control_type); 670 671 static int __init powercap_init(void) 672 { 673 int result; 674 675 result = seed_constraint_attributes(); 676 if (result) 677 return result; 678 679 return class_register(&powercap_class); 680 } 681 682 fs_initcall(powercap_init); 683 684 MODULE_DESCRIPTION("PowerCap sysfs Driver"); 685 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 686