1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Generic Counter sysfs interface 4 * Copyright (C) 2020 William Breathitt Gray 5 */ 6 #include <linux/counter.h> 7 #include <linux/device.h> 8 #include <linux/err.h> 9 #include <linux/gfp.h> 10 #include <linux/kernel.h> 11 #include <linux/kfifo.h> 12 #include <linux/kstrtox.h> 13 #include <linux/list.h> 14 #include <linux/mutex.h> 15 #include <linux/spinlock.h> 16 #include <linux/string.h> 17 #include <linux/sysfs.h> 18 #include <linux/types.h> 19 20 #include "counter-sysfs.h" 21 22 static inline struct counter_device *counter_from_dev(struct device *dev) 23 { 24 return container_of(dev, struct counter_device, dev); 25 } 26 27 /** 28 * struct counter_attribute - Counter sysfs attribute 29 * @dev_attr: device attribute for sysfs 30 * @l: node to add Counter attribute to attribute group list 31 * @comp: Counter component callbacks and data 32 * @scope: Counter scope of the attribute 33 * @parent: pointer to the parent component 34 */ 35 struct counter_attribute { 36 struct device_attribute dev_attr; 37 struct list_head l; 38 39 struct counter_comp comp; 40 enum counter_scope scope; 41 void *parent; 42 }; 43 44 #define to_counter_attribute(_dev_attr) \ 45 container_of(_dev_attr, struct counter_attribute, dev_attr) 46 47 /** 48 * struct counter_attribute_group - container for attribute group 49 * @name: name of the attribute group 50 * @attr_list: list to keep track of created attributes 51 * @num_attr: number of attributes 52 */ 53 struct counter_attribute_group { 54 const char *name; 55 struct list_head attr_list; 56 size_t num_attr; 57 }; 58 59 static const char *const counter_function_str[] = { 60 [COUNTER_FUNCTION_INCREASE] = "increase", 61 [COUNTER_FUNCTION_DECREASE] = "decrease", 62 [COUNTER_FUNCTION_PULSE_DIRECTION] = "pulse-direction", 63 [COUNTER_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a", 64 [COUNTER_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b", 65 [COUNTER_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a", 66 [COUNTER_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b", 67 [COUNTER_FUNCTION_QUADRATURE_X4] = "quadrature x4" 68 }; 69 70 static const char *const counter_signal_value_str[] = { 71 [COUNTER_SIGNAL_LEVEL_LOW] = "low", 72 [COUNTER_SIGNAL_LEVEL_HIGH] = "high" 73 }; 74 75 static const char *const counter_synapse_action_str[] = { 76 [COUNTER_SYNAPSE_ACTION_NONE] = "none", 77 [COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge", 78 [COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge", 79 [COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges" 80 }; 81 82 static const char *const counter_count_direction_str[] = { 83 [COUNTER_COUNT_DIRECTION_FORWARD] = "forward", 84 [COUNTER_COUNT_DIRECTION_BACKWARD] = "backward" 85 }; 86 87 static const char *const counter_count_mode_str[] = { 88 [COUNTER_COUNT_MODE_NORMAL] = "normal", 89 [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit", 90 [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle", 91 [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n" 92 }; 93 94 static const char *const counter_signal_polarity_str[] = { 95 [COUNTER_SIGNAL_POLARITY_POSITIVE] = "positive", 96 [COUNTER_SIGNAL_POLARITY_NEGATIVE] = "negative" 97 }; 98 99 static ssize_t counter_comp_u8_show(struct device *dev, 100 struct device_attribute *attr, char *buf) 101 { 102 const struct counter_attribute *const a = to_counter_attribute(attr); 103 struct counter_device *const counter = counter_from_dev(dev); 104 int err; 105 u8 data = 0; 106 107 switch (a->scope) { 108 case COUNTER_SCOPE_DEVICE: 109 err = a->comp.device_u8_read(counter, &data); 110 break; 111 case COUNTER_SCOPE_SIGNAL: 112 err = a->comp.signal_u8_read(counter, a->parent, &data); 113 break; 114 case COUNTER_SCOPE_COUNT: 115 err = a->comp.count_u8_read(counter, a->parent, &data); 116 break; 117 default: 118 return -EINVAL; 119 } 120 if (err < 0) 121 return err; 122 123 if (a->comp.type == COUNTER_COMP_BOOL) 124 /* data should already be boolean but ensure just to be safe */ 125 data = !!data; 126 127 return sysfs_emit(buf, "%u\n", (unsigned int)data); 128 } 129 130 static ssize_t counter_comp_u8_store(struct device *dev, 131 struct device_attribute *attr, 132 const char *buf, size_t len) 133 { 134 const struct counter_attribute *const a = to_counter_attribute(attr); 135 struct counter_device *const counter = counter_from_dev(dev); 136 int err; 137 bool bool_data = 0; 138 u8 data = 0; 139 140 if (a->comp.type == COUNTER_COMP_BOOL) { 141 err = kstrtobool(buf, &bool_data); 142 data = bool_data; 143 } else 144 err = kstrtou8(buf, 0, &data); 145 if (err < 0) 146 return err; 147 148 switch (a->scope) { 149 case COUNTER_SCOPE_DEVICE: 150 err = a->comp.device_u8_write(counter, data); 151 break; 152 case COUNTER_SCOPE_SIGNAL: 153 err = a->comp.signal_u8_write(counter, a->parent, data); 154 break; 155 case COUNTER_SCOPE_COUNT: 156 err = a->comp.count_u8_write(counter, a->parent, data); 157 break; 158 default: 159 return -EINVAL; 160 } 161 if (err < 0) 162 return err; 163 164 return len; 165 } 166 167 static ssize_t counter_comp_u32_show(struct device *dev, 168 struct device_attribute *attr, char *buf) 169 { 170 const struct counter_attribute *const a = to_counter_attribute(attr); 171 struct counter_device *const counter = counter_from_dev(dev); 172 const struct counter_available *const avail = a->comp.priv; 173 int err; 174 u32 data = 0; 175 176 switch (a->scope) { 177 case COUNTER_SCOPE_DEVICE: 178 err = a->comp.device_u32_read(counter, &data); 179 break; 180 case COUNTER_SCOPE_SIGNAL: 181 err = a->comp.signal_u32_read(counter, a->parent, &data); 182 break; 183 case COUNTER_SCOPE_COUNT: 184 if (a->comp.type == COUNTER_COMP_SYNAPSE_ACTION) 185 err = a->comp.action_read(counter, a->parent, 186 a->comp.priv, &data); 187 else 188 err = a->comp.count_u32_read(counter, a->parent, &data); 189 break; 190 default: 191 return -EINVAL; 192 } 193 if (err < 0) 194 return err; 195 196 switch (a->comp.type) { 197 case COUNTER_COMP_FUNCTION: 198 return sysfs_emit(buf, "%s\n", counter_function_str[data]); 199 case COUNTER_COMP_SIGNAL_LEVEL: 200 return sysfs_emit(buf, "%s\n", counter_signal_value_str[data]); 201 case COUNTER_COMP_SYNAPSE_ACTION: 202 return sysfs_emit(buf, "%s\n", counter_synapse_action_str[data]); 203 case COUNTER_COMP_ENUM: 204 return sysfs_emit(buf, "%s\n", avail->strs[data]); 205 case COUNTER_COMP_COUNT_DIRECTION: 206 return sysfs_emit(buf, "%s\n", counter_count_direction_str[data]); 207 case COUNTER_COMP_COUNT_MODE: 208 return sysfs_emit(buf, "%s\n", counter_count_mode_str[data]); 209 case COUNTER_COMP_SIGNAL_POLARITY: 210 return sysfs_emit(buf, "%s\n", counter_signal_polarity_str[data]); 211 default: 212 return sysfs_emit(buf, "%u\n", (unsigned int)data); 213 } 214 } 215 216 static int counter_find_enum(u32 *const enum_item, const u32 *const enums, 217 const size_t num_enums, const char *const buf, 218 const char *const string_array[]) 219 { 220 size_t index; 221 222 for (index = 0; index < num_enums; index++) { 223 *enum_item = enums[index]; 224 if (sysfs_streq(buf, string_array[*enum_item])) 225 return 0; 226 } 227 228 return -EINVAL; 229 } 230 231 static ssize_t counter_comp_u32_store(struct device *dev, 232 struct device_attribute *attr, 233 const char *buf, size_t len) 234 { 235 const struct counter_attribute *const a = to_counter_attribute(attr); 236 struct counter_device *const counter = counter_from_dev(dev); 237 struct counter_count *const count = a->parent; 238 struct counter_synapse *const synapse = a->comp.priv; 239 const struct counter_available *const avail = a->comp.priv; 240 int err; 241 u32 data = 0; 242 243 switch (a->comp.type) { 244 case COUNTER_COMP_FUNCTION: 245 err = counter_find_enum(&data, count->functions_list, 246 count->num_functions, buf, 247 counter_function_str); 248 break; 249 case COUNTER_COMP_SYNAPSE_ACTION: 250 err = counter_find_enum(&data, synapse->actions_list, 251 synapse->num_actions, buf, 252 counter_synapse_action_str); 253 break; 254 case COUNTER_COMP_ENUM: 255 err = __sysfs_match_string(avail->strs, avail->num_items, buf); 256 data = err; 257 break; 258 case COUNTER_COMP_COUNT_MODE: 259 err = counter_find_enum(&data, avail->enums, avail->num_items, 260 buf, counter_count_mode_str); 261 break; 262 case COUNTER_COMP_SIGNAL_POLARITY: 263 err = counter_find_enum(&data, avail->enums, avail->num_items, 264 buf, counter_signal_polarity_str); 265 break; 266 default: 267 err = kstrtou32(buf, 0, &data); 268 break; 269 } 270 if (err < 0) 271 return err; 272 273 switch (a->scope) { 274 case COUNTER_SCOPE_DEVICE: 275 err = a->comp.device_u32_write(counter, data); 276 break; 277 case COUNTER_SCOPE_SIGNAL: 278 err = a->comp.signal_u32_write(counter, a->parent, data); 279 break; 280 case COUNTER_SCOPE_COUNT: 281 if (a->comp.type == COUNTER_COMP_SYNAPSE_ACTION) 282 err = a->comp.action_write(counter, count, synapse, 283 data); 284 else 285 err = a->comp.count_u32_write(counter, count, data); 286 break; 287 default: 288 return -EINVAL; 289 } 290 if (err < 0) 291 return err; 292 293 return len; 294 } 295 296 static ssize_t counter_comp_u64_show(struct device *dev, 297 struct device_attribute *attr, char *buf) 298 { 299 const struct counter_attribute *const a = to_counter_attribute(attr); 300 struct counter_device *const counter = counter_from_dev(dev); 301 int err; 302 u64 data = 0; 303 304 switch (a->scope) { 305 case COUNTER_SCOPE_DEVICE: 306 err = a->comp.device_u64_read(counter, &data); 307 break; 308 case COUNTER_SCOPE_SIGNAL: 309 err = a->comp.signal_u64_read(counter, a->parent, &data); 310 break; 311 case COUNTER_SCOPE_COUNT: 312 err = a->comp.count_u64_read(counter, a->parent, &data); 313 break; 314 default: 315 return -EINVAL; 316 } 317 if (err < 0) 318 return err; 319 320 return sysfs_emit(buf, "%llu\n", (unsigned long long)data); 321 } 322 323 static ssize_t counter_comp_u64_store(struct device *dev, 324 struct device_attribute *attr, 325 const char *buf, size_t len) 326 { 327 const struct counter_attribute *const a = to_counter_attribute(attr); 328 struct counter_device *const counter = counter_from_dev(dev); 329 int err; 330 u64 data = 0; 331 332 err = kstrtou64(buf, 0, &data); 333 if (err < 0) 334 return err; 335 336 switch (a->scope) { 337 case COUNTER_SCOPE_DEVICE: 338 err = a->comp.device_u64_write(counter, data); 339 break; 340 case COUNTER_SCOPE_SIGNAL: 341 err = a->comp.signal_u64_write(counter, a->parent, data); 342 break; 343 case COUNTER_SCOPE_COUNT: 344 err = a->comp.count_u64_write(counter, a->parent, data); 345 break; 346 default: 347 return -EINVAL; 348 } 349 if (err < 0) 350 return err; 351 352 return len; 353 } 354 355 static ssize_t counter_comp_array_u32_show(struct device *dev, 356 struct device_attribute *attr, 357 char *buf) 358 { 359 const struct counter_attribute *const a = to_counter_attribute(attr); 360 struct counter_device *const counter = counter_from_dev(dev); 361 const struct counter_array *const element = a->comp.priv; 362 int err; 363 u32 data = 0; 364 365 if (a->scope != COUNTER_SCOPE_SIGNAL || 366 element->type != COUNTER_COMP_SIGNAL_POLARITY) 367 return -EINVAL; 368 369 err = a->comp.signal_array_u32_read(counter, a->parent, element->idx, 370 &data); 371 if (err < 0) 372 return err; 373 374 return sysfs_emit(buf, "%s\n", counter_signal_polarity_str[data]); 375 } 376 377 static ssize_t counter_comp_array_u32_store(struct device *dev, 378 struct device_attribute *attr, 379 const char *buf, size_t len) 380 { 381 const struct counter_attribute *const a = to_counter_attribute(attr); 382 struct counter_device *const counter = counter_from_dev(dev); 383 const struct counter_array *const element = a->comp.priv; 384 int err; 385 u32 data = 0; 386 387 if (element->type != COUNTER_COMP_SIGNAL_POLARITY || 388 a->scope != COUNTER_SCOPE_SIGNAL) 389 return -EINVAL; 390 391 err = counter_find_enum(&data, element->avail->enums, 392 element->avail->num_items, buf, 393 counter_signal_polarity_str); 394 if (err < 0) 395 return err; 396 397 err = a->comp.signal_array_u32_write(counter, a->parent, element->idx, 398 data); 399 if (err < 0) 400 return err; 401 402 return len; 403 } 404 405 static ssize_t counter_comp_array_u64_show(struct device *dev, 406 struct device_attribute *attr, 407 char *buf) 408 { 409 const struct counter_attribute *const a = to_counter_attribute(attr); 410 struct counter_device *const counter = counter_from_dev(dev); 411 const struct counter_array *const element = a->comp.priv; 412 int err; 413 u64 data = 0; 414 415 switch (a->scope) { 416 case COUNTER_SCOPE_DEVICE: 417 err = a->comp.device_array_u64_read(counter, element->idx, 418 &data); 419 break; 420 case COUNTER_SCOPE_SIGNAL: 421 err = a->comp.signal_array_u64_read(counter, a->parent, 422 element->idx, &data); 423 break; 424 case COUNTER_SCOPE_COUNT: 425 err = a->comp.count_array_u64_read(counter, a->parent, 426 element->idx, &data); 427 break; 428 default: 429 return -EINVAL; 430 } 431 if (err < 0) 432 return err; 433 434 return sysfs_emit(buf, "%llu\n", (unsigned long long)data); 435 } 436 437 static ssize_t counter_comp_array_u64_store(struct device *dev, 438 struct device_attribute *attr, 439 const char *buf, size_t len) 440 { 441 const struct counter_attribute *const a = to_counter_attribute(attr); 442 struct counter_device *const counter = counter_from_dev(dev); 443 const struct counter_array *const element = a->comp.priv; 444 int err; 445 u64 data = 0; 446 447 err = kstrtou64(buf, 0, &data); 448 if (err < 0) 449 return err; 450 451 switch (a->scope) { 452 case COUNTER_SCOPE_DEVICE: 453 err = a->comp.device_array_u64_write(counter, element->idx, 454 data); 455 break; 456 case COUNTER_SCOPE_SIGNAL: 457 err = a->comp.signal_array_u64_write(counter, a->parent, 458 element->idx, data); 459 break; 460 case COUNTER_SCOPE_COUNT: 461 err = a->comp.count_array_u64_write(counter, a->parent, 462 element->idx, data); 463 break; 464 default: 465 return -EINVAL; 466 } 467 if (err < 0) 468 return err; 469 470 return len; 471 } 472 473 static ssize_t enums_available_show(const u32 *const enums, 474 const size_t num_enums, 475 const char *const strs[], char *buf) 476 { 477 size_t len = 0; 478 size_t index; 479 480 for (index = 0; index < num_enums; index++) 481 len += sysfs_emit_at(buf, len, "%s\n", strs[enums[index]]); 482 483 return len; 484 } 485 486 static ssize_t strs_available_show(const struct counter_available *const avail, 487 char *buf) 488 { 489 size_t len = 0; 490 size_t index; 491 492 for (index = 0; index < avail->num_items; index++) 493 len += sysfs_emit_at(buf, len, "%s\n", avail->strs[index]); 494 495 return len; 496 } 497 498 static ssize_t counter_comp_available_show(struct device *dev, 499 struct device_attribute *attr, 500 char *buf) 501 { 502 const struct counter_attribute *const a = to_counter_attribute(attr); 503 const struct counter_count *const count = a->parent; 504 const struct counter_synapse *const synapse = a->comp.priv; 505 const struct counter_available *const avail = a->comp.priv; 506 507 switch (a->comp.type) { 508 case COUNTER_COMP_FUNCTION: 509 return enums_available_show(count->functions_list, 510 count->num_functions, 511 counter_function_str, buf); 512 case COUNTER_COMP_SYNAPSE_ACTION: 513 return enums_available_show(synapse->actions_list, 514 synapse->num_actions, 515 counter_synapse_action_str, buf); 516 case COUNTER_COMP_ENUM: 517 return strs_available_show(avail, buf); 518 case COUNTER_COMP_COUNT_MODE: 519 return enums_available_show(avail->enums, avail->num_items, 520 counter_count_mode_str, buf); 521 default: 522 return -EINVAL; 523 } 524 } 525 526 static int counter_avail_attr_create(struct device *const dev, 527 struct counter_attribute_group *const group, 528 const struct counter_comp *const comp, void *const parent) 529 { 530 struct counter_attribute *counter_attr; 531 struct device_attribute *dev_attr; 532 533 counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 534 if (!counter_attr) 535 return -ENOMEM; 536 537 /* Configure Counter attribute */ 538 counter_attr->comp.type = comp->type; 539 counter_attr->comp.priv = comp->priv; 540 counter_attr->parent = parent; 541 542 /* Initialize sysfs attribute */ 543 dev_attr = &counter_attr->dev_attr; 544 sysfs_attr_init(&dev_attr->attr); 545 546 /* Configure device attribute */ 547 dev_attr->attr.name = devm_kasprintf(dev, GFP_KERNEL, "%s_available", 548 comp->name); 549 if (!dev_attr->attr.name) 550 return -ENOMEM; 551 dev_attr->attr.mode = 0444; 552 dev_attr->show = counter_comp_available_show; 553 554 /* Store list node */ 555 list_add(&counter_attr->l, &group->attr_list); 556 group->num_attr++; 557 558 return 0; 559 } 560 561 static int counter_attr_create(struct device *const dev, 562 struct counter_attribute_group *const group, 563 const struct counter_comp *const comp, 564 const enum counter_scope scope, 565 void *const parent) 566 { 567 const struct counter_array *const array = comp->priv; 568 struct counter_attribute *counter_attr; 569 struct device_attribute *dev_attr; 570 571 counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 572 if (!counter_attr) 573 return -ENOMEM; 574 575 /* Configure Counter attribute */ 576 counter_attr->comp = *comp; 577 counter_attr->scope = scope; 578 counter_attr->parent = parent; 579 580 /* Configure device attribute */ 581 dev_attr = &counter_attr->dev_attr; 582 sysfs_attr_init(&dev_attr->attr); 583 dev_attr->attr.name = comp->name; 584 switch (comp->type) { 585 case COUNTER_COMP_U8: 586 case COUNTER_COMP_BOOL: 587 if (comp->device_u8_read) { 588 dev_attr->attr.mode |= 0444; 589 dev_attr->show = counter_comp_u8_show; 590 } 591 if (comp->device_u8_write) { 592 dev_attr->attr.mode |= 0200; 593 dev_attr->store = counter_comp_u8_store; 594 } 595 break; 596 case COUNTER_COMP_SIGNAL_LEVEL: 597 case COUNTER_COMP_FUNCTION: 598 case COUNTER_COMP_SYNAPSE_ACTION: 599 case COUNTER_COMP_ENUM: 600 case COUNTER_COMP_COUNT_DIRECTION: 601 case COUNTER_COMP_COUNT_MODE: 602 case COUNTER_COMP_SIGNAL_POLARITY: 603 if (comp->device_u32_read) { 604 dev_attr->attr.mode |= 0444; 605 dev_attr->show = counter_comp_u32_show; 606 } 607 if (comp->device_u32_write) { 608 dev_attr->attr.mode |= 0200; 609 dev_attr->store = counter_comp_u32_store; 610 } 611 break; 612 case COUNTER_COMP_U64: 613 if (comp->device_u64_read) { 614 dev_attr->attr.mode |= 0444; 615 dev_attr->show = counter_comp_u64_show; 616 } 617 if (comp->device_u64_write) { 618 dev_attr->attr.mode |= 0200; 619 dev_attr->store = counter_comp_u64_store; 620 } 621 break; 622 case COUNTER_COMP_ARRAY: 623 switch (array->type) { 624 case COUNTER_COMP_SIGNAL_POLARITY: 625 if (comp->signal_array_u32_read) { 626 dev_attr->attr.mode |= 0444; 627 dev_attr->show = counter_comp_array_u32_show; 628 } 629 if (comp->signal_array_u32_write) { 630 dev_attr->attr.mode |= 0200; 631 dev_attr->store = counter_comp_array_u32_store; 632 } 633 break; 634 case COUNTER_COMP_U64: 635 if (comp->device_array_u64_read) { 636 dev_attr->attr.mode |= 0444; 637 dev_attr->show = counter_comp_array_u64_show; 638 } 639 if (comp->device_array_u64_write) { 640 dev_attr->attr.mode |= 0200; 641 dev_attr->store = counter_comp_array_u64_store; 642 } 643 break; 644 default: 645 return -EINVAL; 646 } 647 break; 648 default: 649 return -EINVAL; 650 } 651 652 /* Store list node */ 653 list_add(&counter_attr->l, &group->attr_list); 654 group->num_attr++; 655 656 /* Create "*_available" attribute if needed */ 657 switch (comp->type) { 658 case COUNTER_COMP_FUNCTION: 659 case COUNTER_COMP_SYNAPSE_ACTION: 660 case COUNTER_COMP_ENUM: 661 case COUNTER_COMP_COUNT_MODE: 662 return counter_avail_attr_create(dev, group, comp, parent); 663 default: 664 return 0; 665 } 666 } 667 668 static ssize_t counter_comp_name_show(struct device *dev, 669 struct device_attribute *attr, char *buf) 670 { 671 return sysfs_emit(buf, "%s\n", to_counter_attribute(attr)->comp.name); 672 } 673 674 static int counter_name_attr_create(struct device *const dev, 675 struct counter_attribute_group *const group, 676 const char *const name) 677 { 678 struct counter_attribute *counter_attr; 679 680 counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 681 if (!counter_attr) 682 return -ENOMEM; 683 684 /* Configure Counter attribute */ 685 counter_attr->comp.name = name; 686 687 /* Configure device attribute */ 688 sysfs_attr_init(&counter_attr->dev_attr.attr); 689 counter_attr->dev_attr.attr.name = "name"; 690 counter_attr->dev_attr.attr.mode = 0444; 691 counter_attr->dev_attr.show = counter_comp_name_show; 692 693 /* Store list node */ 694 list_add(&counter_attr->l, &group->attr_list); 695 group->num_attr++; 696 697 return 0; 698 } 699 700 static ssize_t counter_comp_id_show(struct device *dev, 701 struct device_attribute *attr, char *buf) 702 { 703 const size_t id = (size_t)to_counter_attribute(attr)->comp.priv; 704 705 return sysfs_emit(buf, "%zu\n", id); 706 } 707 708 static int counter_comp_id_attr_create(struct device *const dev, 709 struct counter_attribute_group *const group, 710 const char *name, const size_t id) 711 { 712 struct counter_attribute *counter_attr; 713 714 /* Allocate Counter attribute */ 715 counter_attr = devm_kzalloc(dev, sizeof(*counter_attr), GFP_KERNEL); 716 if (!counter_attr) 717 return -ENOMEM; 718 719 /* Generate component ID name */ 720 name = devm_kasprintf(dev, GFP_KERNEL, "%s_component_id", name); 721 if (!name) 722 return -ENOMEM; 723 724 /* Configure Counter attribute */ 725 counter_attr->comp.priv = (void *)id; 726 727 /* Configure device attribute */ 728 sysfs_attr_init(&counter_attr->dev_attr.attr); 729 counter_attr->dev_attr.attr.name = name; 730 counter_attr->dev_attr.attr.mode = 0444; 731 counter_attr->dev_attr.show = counter_comp_id_show; 732 733 /* Store list node */ 734 list_add(&counter_attr->l, &group->attr_list); 735 group->num_attr++; 736 737 return 0; 738 } 739 740 static int counter_ext_attrs_create(struct device *const dev, 741 struct counter_attribute_group *const group, 742 const struct counter_comp *const ext, 743 const enum counter_scope scope, 744 void *const parent, const size_t id) 745 { 746 int err; 747 748 /* Create main extension attribute */ 749 err = counter_attr_create(dev, group, ext, scope, parent); 750 if (err < 0) 751 return err; 752 753 /* Create extension id attribute */ 754 return counter_comp_id_attr_create(dev, group, ext->name, id); 755 } 756 757 static int counter_array_attrs_create(struct device *const dev, 758 struct counter_attribute_group *const group, 759 const struct counter_comp *const comp, 760 const enum counter_scope scope, 761 void *const parent, const size_t id) 762 { 763 const struct counter_array *const array = comp->priv; 764 struct counter_comp ext = *comp; 765 struct counter_array *element; 766 size_t idx; 767 int err; 768 769 /* Create an attribute for each array element */ 770 for (idx = 0; idx < array->length; idx++) { 771 /* Generate array element attribute name */ 772 ext.name = devm_kasprintf(dev, GFP_KERNEL, "%s%zu", comp->name, 773 idx); 774 if (!ext.name) 775 return -ENOMEM; 776 777 /* Allocate and configure array element */ 778 element = devm_kzalloc(dev, sizeof(*element), GFP_KERNEL); 779 if (!element) 780 return -ENOMEM; 781 element->type = array->type; 782 element->avail = array->avail; 783 element->idx = idx; 784 ext.priv = element; 785 786 /* Create all attributes associated with the array element */ 787 err = counter_ext_attrs_create(dev, group, &ext, scope, parent, 788 id + idx); 789 if (err < 0) 790 return err; 791 } 792 793 return 0; 794 } 795 796 static int counter_sysfs_exts_add(struct device *const dev, 797 struct counter_attribute_group *const group, 798 const struct counter_comp *const exts, 799 const size_t num_ext, 800 const enum counter_scope scope, 801 void *const parent) 802 { 803 size_t i; 804 const struct counter_comp *ext; 805 int err; 806 size_t id = 0; 807 const struct counter_array *array; 808 809 /* Create attributes for each extension */ 810 for (i = 0; i < num_ext; i++) { 811 ext = &exts[i]; 812 if (ext->type == COUNTER_COMP_ARRAY) { 813 err = counter_array_attrs_create(dev, group, ext, scope, 814 parent, id); 815 array = ext->priv; 816 id += array->length; 817 } else { 818 err = counter_ext_attrs_create(dev, group, ext, scope, 819 parent, id); 820 id++; 821 } 822 if (err < 0) 823 return err; 824 } 825 826 return 0; 827 } 828 829 static struct counter_comp counter_signal_comp = { 830 .type = COUNTER_COMP_SIGNAL_LEVEL, 831 .name = "signal", 832 }; 833 834 static int counter_signal_attrs_create(struct counter_device *const counter, 835 struct counter_attribute_group *const cattr_group, 836 struct counter_signal *const signal) 837 { 838 const enum counter_scope scope = COUNTER_SCOPE_SIGNAL; 839 struct device *const dev = &counter->dev; 840 int err; 841 struct counter_comp comp; 842 843 /* Create main Signal attribute */ 844 comp = counter_signal_comp; 845 comp.signal_u32_read = counter->ops->signal_read; 846 err = counter_attr_create(dev, cattr_group, &comp, scope, signal); 847 if (err < 0) 848 return err; 849 850 /* Create Signal name attribute */ 851 err = counter_name_attr_create(dev, cattr_group, signal->name); 852 if (err < 0) 853 return err; 854 855 /* Add Signal extensions */ 856 return counter_sysfs_exts_add(dev, cattr_group, signal->ext, 857 signal->num_ext, scope, signal); 858 } 859 860 static int counter_sysfs_signals_add(struct counter_device *const counter, 861 struct counter_attribute_group *const groups) 862 { 863 size_t i; 864 int err; 865 866 /* Add each Signal */ 867 for (i = 0; i < counter->num_signals; i++) { 868 /* Generate Signal attribute directory name */ 869 groups[i].name = devm_kasprintf(&counter->dev, GFP_KERNEL, 870 "signal%zu", i); 871 if (!groups[i].name) 872 return -ENOMEM; 873 874 /* Create all attributes associated with Signal */ 875 err = counter_signal_attrs_create(counter, groups + i, 876 counter->signals + i); 877 if (err < 0) 878 return err; 879 } 880 881 return 0; 882 } 883 884 static int counter_sysfs_synapses_add(struct counter_device *const counter, 885 struct counter_attribute_group *const group, 886 struct counter_count *const count) 887 { 888 size_t i; 889 890 /* Add each Synapse */ 891 for (i = 0; i < count->num_synapses; i++) { 892 struct device *const dev = &counter->dev; 893 struct counter_synapse *synapse; 894 size_t id; 895 struct counter_comp comp; 896 int err; 897 898 synapse = count->synapses + i; 899 900 /* Generate Synapse action name */ 901 id = synapse->signal - counter->signals; 902 comp.name = devm_kasprintf(dev, GFP_KERNEL, "signal%zu_action", 903 id); 904 if (!comp.name) 905 return -ENOMEM; 906 907 /* Create action attribute */ 908 comp.type = COUNTER_COMP_SYNAPSE_ACTION; 909 comp.action_read = counter->ops->action_read; 910 comp.action_write = counter->ops->action_write; 911 comp.priv = synapse; 912 err = counter_attr_create(dev, group, &comp, 913 COUNTER_SCOPE_COUNT, count); 914 if (err < 0) 915 return err; 916 917 /* Create Synapse component ID attribute */ 918 err = counter_comp_id_attr_create(dev, group, comp.name, i); 919 if (err < 0) 920 return err; 921 } 922 923 return 0; 924 } 925 926 static struct counter_comp counter_count_comp = 927 COUNTER_COMP_COUNT_U64("count", NULL, NULL); 928 929 static struct counter_comp counter_function_comp = { 930 .type = COUNTER_COMP_FUNCTION, 931 .name = "function", 932 }; 933 934 static int counter_count_attrs_create(struct counter_device *const counter, 935 struct counter_attribute_group *const cattr_group, 936 struct counter_count *const count) 937 { 938 const enum counter_scope scope = COUNTER_SCOPE_COUNT; 939 struct device *const dev = &counter->dev; 940 int err; 941 struct counter_comp comp; 942 943 /* Create main Count attribute */ 944 comp = counter_count_comp; 945 comp.count_u64_read = counter->ops->count_read; 946 comp.count_u64_write = counter->ops->count_write; 947 err = counter_attr_create(dev, cattr_group, &comp, scope, count); 948 if (err < 0) 949 return err; 950 951 /* Create Count name attribute */ 952 err = counter_name_attr_create(dev, cattr_group, count->name); 953 if (err < 0) 954 return err; 955 956 /* Create Count function attribute */ 957 comp = counter_function_comp; 958 comp.count_u32_read = counter->ops->function_read; 959 comp.count_u32_write = counter->ops->function_write; 960 err = counter_attr_create(dev, cattr_group, &comp, scope, count); 961 if (err < 0) 962 return err; 963 964 /* Add Count extensions */ 965 return counter_sysfs_exts_add(dev, cattr_group, count->ext, 966 count->num_ext, scope, count); 967 } 968 969 static int counter_sysfs_counts_add(struct counter_device *const counter, 970 struct counter_attribute_group *const groups) 971 { 972 size_t i; 973 struct counter_count *count; 974 int err; 975 976 /* Add each Count */ 977 for (i = 0; i < counter->num_counts; i++) { 978 count = counter->counts + i; 979 980 /* Generate Count attribute directory name */ 981 groups[i].name = devm_kasprintf(&counter->dev, GFP_KERNEL, 982 "count%zu", i); 983 if (!groups[i].name) 984 return -ENOMEM; 985 986 /* Add sysfs attributes of the Synapses */ 987 err = counter_sysfs_synapses_add(counter, groups + i, count); 988 if (err < 0) 989 return err; 990 991 /* Create all attributes associated with Count */ 992 err = counter_count_attrs_create(counter, groups + i, count); 993 if (err < 0) 994 return err; 995 } 996 997 return 0; 998 } 999 1000 static int counter_num_signals_read(struct counter_device *counter, u8 *val) 1001 { 1002 *val = counter->num_signals; 1003 return 0; 1004 } 1005 1006 static int counter_num_counts_read(struct counter_device *counter, u8 *val) 1007 { 1008 *val = counter->num_counts; 1009 return 0; 1010 } 1011 1012 static int counter_events_queue_size_read(struct counter_device *counter, 1013 u64 *val) 1014 { 1015 *val = kfifo_size(&counter->events); 1016 return 0; 1017 } 1018 1019 static int counter_events_queue_size_write(struct counter_device *counter, 1020 u64 val) 1021 { 1022 DECLARE_KFIFO_PTR(events, struct counter_event); 1023 int err; 1024 unsigned long flags; 1025 1026 /* Allocate new events queue */ 1027 err = kfifo_alloc(&events, val, GFP_KERNEL); 1028 if (err) 1029 return err; 1030 1031 /* Swap in new events queue */ 1032 mutex_lock(&counter->events_out_lock); 1033 spin_lock_irqsave(&counter->events_in_lock, flags); 1034 kfifo_free(&counter->events); 1035 counter->events.kfifo = events.kfifo; 1036 spin_unlock_irqrestore(&counter->events_in_lock, flags); 1037 mutex_unlock(&counter->events_out_lock); 1038 1039 return 0; 1040 } 1041 1042 static struct counter_comp counter_num_signals_comp = 1043 COUNTER_COMP_DEVICE_U8("num_signals", counter_num_signals_read, NULL); 1044 1045 static struct counter_comp counter_num_counts_comp = 1046 COUNTER_COMP_DEVICE_U8("num_counts", counter_num_counts_read, NULL); 1047 1048 static struct counter_comp counter_events_queue_size_comp = 1049 COUNTER_COMP_DEVICE_U64("events_queue_size", 1050 counter_events_queue_size_read, 1051 counter_events_queue_size_write); 1052 1053 static int counter_sysfs_attr_add(struct counter_device *const counter, 1054 struct counter_attribute_group *cattr_group) 1055 { 1056 const enum counter_scope scope = COUNTER_SCOPE_DEVICE; 1057 struct device *const dev = &counter->dev; 1058 int err; 1059 1060 /* Add Signals sysfs attributes */ 1061 err = counter_sysfs_signals_add(counter, cattr_group); 1062 if (err < 0) 1063 return err; 1064 cattr_group += counter->num_signals; 1065 1066 /* Add Counts sysfs attributes */ 1067 err = counter_sysfs_counts_add(counter, cattr_group); 1068 if (err < 0) 1069 return err; 1070 cattr_group += counter->num_counts; 1071 1072 /* Create name attribute */ 1073 err = counter_name_attr_create(dev, cattr_group, counter->name); 1074 if (err < 0) 1075 return err; 1076 1077 /* Create num_signals attribute */ 1078 err = counter_attr_create(dev, cattr_group, &counter_num_signals_comp, 1079 scope, NULL); 1080 if (err < 0) 1081 return err; 1082 1083 /* Create num_counts attribute */ 1084 err = counter_attr_create(dev, cattr_group, &counter_num_counts_comp, 1085 scope, NULL); 1086 if (err < 0) 1087 return err; 1088 1089 /* Create events_queue_size attribute */ 1090 err = counter_attr_create(dev, cattr_group, 1091 &counter_events_queue_size_comp, scope, NULL); 1092 if (err < 0) 1093 return err; 1094 1095 /* Add device extensions */ 1096 return counter_sysfs_exts_add(dev, cattr_group, counter->ext, 1097 counter->num_ext, scope, NULL); 1098 1099 return 0; 1100 } 1101 1102 /** 1103 * counter_sysfs_add - Adds Counter sysfs attributes to the device structure 1104 * @counter: Pointer to the Counter device structure 1105 * 1106 * Counter sysfs attributes are created and added to the respective device 1107 * structure for later registration to the system. Resource-managed memory 1108 * allocation is performed by this function, and this memory should be freed 1109 * when no longer needed (automatically by a device_unregister call, or 1110 * manually by a devres_release_all call). 1111 */ 1112 int counter_sysfs_add(struct counter_device *const counter) 1113 { 1114 struct device *const dev = &counter->dev; 1115 const size_t num_groups = counter->num_signals + counter->num_counts + 1; 1116 struct counter_attribute_group *cattr_groups; 1117 size_t i, j; 1118 int err; 1119 struct attribute_group *groups; 1120 struct counter_attribute *p; 1121 1122 /* Allocate space for attribute groups (signals, counts, and ext) */ 1123 cattr_groups = devm_kcalloc(dev, num_groups, sizeof(*cattr_groups), 1124 GFP_KERNEL); 1125 if (!cattr_groups) 1126 return -ENOMEM; 1127 1128 /* Initialize attribute lists */ 1129 for (i = 0; i < num_groups; i++) 1130 INIT_LIST_HEAD(&cattr_groups[i].attr_list); 1131 1132 /* Add Counter device sysfs attributes */ 1133 err = counter_sysfs_attr_add(counter, cattr_groups); 1134 if (err < 0) 1135 return err; 1136 1137 /* Allocate attribute group pointers for association with device */ 1138 dev->groups = devm_kcalloc(dev, num_groups + 1, sizeof(*dev->groups), 1139 GFP_KERNEL); 1140 if (!dev->groups) 1141 return -ENOMEM; 1142 1143 /* Allocate space for attribute groups */ 1144 groups = devm_kcalloc(dev, num_groups, sizeof(*groups), GFP_KERNEL); 1145 if (!groups) 1146 return -ENOMEM; 1147 1148 /* Prepare each group of attributes for association */ 1149 for (i = 0; i < num_groups; i++) { 1150 groups[i].name = cattr_groups[i].name; 1151 1152 /* Allocate space for attribute pointers */ 1153 groups[i].attrs = devm_kcalloc(dev, 1154 cattr_groups[i].num_attr + 1, 1155 sizeof(*groups[i].attrs), 1156 GFP_KERNEL); 1157 if (!groups[i].attrs) 1158 return -ENOMEM; 1159 1160 /* Add attribute pointers to attribute group */ 1161 j = 0; 1162 list_for_each_entry(p, &cattr_groups[i].attr_list, l) 1163 groups[i].attrs[j++] = &p->dev_attr.attr; 1164 1165 /* Associate attribute group */ 1166 dev->groups[i] = &groups[i]; 1167 } 1168 1169 return 0; 1170 } 1171