Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Generic Counter interface
   4 * Copyright (C) 2018 William Breathitt Gray
   5 */
   6#include <linux/counter.h>
   7#include <linux/device.h>
   8#include <linux/err.h>
   9#include <linux/export.h>
  10#include <linux/fs.h>
  11#include <linux/gfp.h>
  12#include <linux/idr.h>
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/list.h>
  16#include <linux/module.h>
  17#include <linux/printk.h>
  18#include <linux/slab.h>
  19#include <linux/string.h>
  20#include <linux/sysfs.h>
  21#include <linux/types.h>
  22
  23const char *const counter_count_direction_str[2] = {
  24	[COUNTER_COUNT_DIRECTION_FORWARD] = "forward",
  25	[COUNTER_COUNT_DIRECTION_BACKWARD] = "backward"
  26};
  27EXPORT_SYMBOL_GPL(counter_count_direction_str);
  28
  29const char *const counter_count_mode_str[4] = {
  30	[COUNTER_COUNT_MODE_NORMAL] = "normal",
  31	[COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
  32	[COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
  33	[COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
  34};
  35EXPORT_SYMBOL_GPL(counter_count_mode_str);
  36
  37ssize_t counter_signal_enum_read(struct counter_device *counter,
  38				 struct counter_signal *signal, void *priv,
  39				 char *buf)
  40{
  41	const struct counter_signal_enum_ext *const e = priv;
  42	int err;
  43	size_t index;
  44
  45	if (!e->get)
  46		return -EINVAL;
  47
  48	err = e->get(counter, signal, &index);
  49	if (err)
  50		return err;
  51
  52	if (index >= e->num_items)
  53		return -EINVAL;
  54
  55	return sprintf(buf, "%s\n", e->items[index]);
  56}
  57EXPORT_SYMBOL_GPL(counter_signal_enum_read);
  58
  59ssize_t counter_signal_enum_write(struct counter_device *counter,
  60				  struct counter_signal *signal, void *priv,
  61				  const char *buf, size_t len)
  62{
  63	const struct counter_signal_enum_ext *const e = priv;
  64	ssize_t index;
  65	int err;
  66
  67	if (!e->set)
  68		return -EINVAL;
  69
  70	index = __sysfs_match_string(e->items, e->num_items, buf);
  71	if (index < 0)
  72		return index;
  73
  74	err = e->set(counter, signal, index);
  75	if (err)
  76		return err;
  77
  78	return len;
  79}
  80EXPORT_SYMBOL_GPL(counter_signal_enum_write);
  81
  82ssize_t counter_signal_enum_available_read(struct counter_device *counter,
  83					   struct counter_signal *signal,
  84					   void *priv, char *buf)
  85{
  86	const struct counter_signal_enum_ext *const e = priv;
  87	size_t i;
  88	size_t len = 0;
  89
  90	if (!e->num_items)
  91		return 0;
  92
  93	for (i = 0; i < e->num_items; i++)
  94		len += sprintf(buf + len, "%s\n", e->items[i]);
  95
  96	return len;
  97}
  98EXPORT_SYMBOL_GPL(counter_signal_enum_available_read);
  99
 100ssize_t counter_count_enum_read(struct counter_device *counter,
 101				struct counter_count *count, void *priv,
 102				char *buf)
 103{
 104	const struct counter_count_enum_ext *const e = priv;
 105	int err;
 106	size_t index;
 107
 108	if (!e->get)
 109		return -EINVAL;
 110
 111	err = e->get(counter, count, &index);
 112	if (err)
 113		return err;
 114
 115	if (index >= e->num_items)
 116		return -EINVAL;
 117
 118	return sprintf(buf, "%s\n", e->items[index]);
 119}
 120EXPORT_SYMBOL_GPL(counter_count_enum_read);
 121
 122ssize_t counter_count_enum_write(struct counter_device *counter,
 123				 struct counter_count *count, void *priv,
 124				 const char *buf, size_t len)
 125{
 126	const struct counter_count_enum_ext *const e = priv;
 127	ssize_t index;
 128	int err;
 129
 130	if (!e->set)
 131		return -EINVAL;
 132
 133	index = __sysfs_match_string(e->items, e->num_items, buf);
 134	if (index < 0)
 135		return index;
 136
 137	err = e->set(counter, count, index);
 138	if (err)
 139		return err;
 140
 141	return len;
 142}
 143EXPORT_SYMBOL_GPL(counter_count_enum_write);
 144
 145ssize_t counter_count_enum_available_read(struct counter_device *counter,
 146					  struct counter_count *count,
 147					  void *priv, char *buf)
 148{
 149	const struct counter_count_enum_ext *const e = priv;
 150	size_t i;
 151	size_t len = 0;
 152
 153	if (!e->num_items)
 154		return 0;
 155
 156	for (i = 0; i < e->num_items; i++)
 157		len += sprintf(buf + len, "%s\n", e->items[i]);
 158
 159	return len;
 160}
 161EXPORT_SYMBOL_GPL(counter_count_enum_available_read);
 162
 163ssize_t counter_device_enum_read(struct counter_device *counter, void *priv,
 164				 char *buf)
 165{
 166	const struct counter_device_enum_ext *const e = priv;
 167	int err;
 168	size_t index;
 169
 170	if (!e->get)
 171		return -EINVAL;
 172
 173	err = e->get(counter, &index);
 174	if (err)
 175		return err;
 176
 177	if (index >= e->num_items)
 178		return -EINVAL;
 179
 180	return sprintf(buf, "%s\n", e->items[index]);
 181}
 182EXPORT_SYMBOL_GPL(counter_device_enum_read);
 183
 184ssize_t counter_device_enum_write(struct counter_device *counter, void *priv,
 185				  const char *buf, size_t len)
 186{
 187	const struct counter_device_enum_ext *const e = priv;
 188	ssize_t index;
 189	int err;
 190
 191	if (!e->set)
 192		return -EINVAL;
 193
 194	index = __sysfs_match_string(e->items, e->num_items, buf);
 195	if (index < 0)
 196		return index;
 197
 198	err = e->set(counter, index);
 199	if (err)
 200		return err;
 201
 202	return len;
 203}
 204EXPORT_SYMBOL_GPL(counter_device_enum_write);
 205
 206ssize_t counter_device_enum_available_read(struct counter_device *counter,
 207					   void *priv, char *buf)
 208{
 209	const struct counter_device_enum_ext *const e = priv;
 210	size_t i;
 211	size_t len = 0;
 212
 213	if (!e->num_items)
 214		return 0;
 215
 216	for (i = 0; i < e->num_items; i++)
 217		len += sprintf(buf + len, "%s\n", e->items[i]);
 218
 219	return len;
 220}
 221EXPORT_SYMBOL_GPL(counter_device_enum_available_read);
 222
 223static const char *const counter_signal_level_str[] = {
 224	[COUNTER_SIGNAL_LEVEL_LOW] = "low",
 225	[COUNTER_SIGNAL_LEVEL_HIGH] = "high"
 226};
 227
 228/**
 229 * counter_signal_read_value_set - set counter_signal_read_value data
 230 * @val:	counter_signal_read_value structure to set
 231 * @type:	property Signal data represents
 232 * @data:	Signal data
 233 *
 234 * This function sets an opaque counter_signal_read_value structure with the
 235 * provided Signal data.
 236 */
 237void counter_signal_read_value_set(struct counter_signal_read_value *const val,
 238				   const enum counter_signal_value_type type,
 239				   void *const data)
 240{
 241	if (type == COUNTER_SIGNAL_LEVEL)
 242		val->len = sprintf(val->buf, "%s\n",
 243				   counter_signal_level_str[*(enum counter_signal_level *)data]);
 244	else
 245		val->len = 0;
 246}
 247EXPORT_SYMBOL_GPL(counter_signal_read_value_set);
 248
 249/**
 250 * counter_count_read_value_set - set counter_count_read_value data
 251 * @val:	counter_count_read_value structure to set
 252 * @type:	property Count data represents
 253 * @data:	Count data
 254 *
 255 * This function sets an opaque counter_count_read_value structure with the
 256 * provided Count data.
 257 */
 258void counter_count_read_value_set(struct counter_count_read_value *const val,
 259				  const enum counter_count_value_type type,
 260				  void *const data)
 261{
 262	switch (type) {
 263	case COUNTER_COUNT_POSITION:
 264		val->len = sprintf(val->buf, "%lu\n", *(unsigned long *)data);
 265		break;
 266	default:
 267		val->len = 0;
 268	}
 269}
 270EXPORT_SYMBOL_GPL(counter_count_read_value_set);
 271
 272/**
 273 * counter_count_write_value_get - get counter_count_write_value data
 274 * @data:	Count data
 275 * @type:	property Count data represents
 276 * @val:	counter_count_write_value structure containing data
 277 *
 278 * This function extracts Count data from the provided opaque
 279 * counter_count_write_value structure and stores it at the address provided by
 280 * @data.
 281 *
 282 * RETURNS:
 283 * 0 on success, negative error number on failure.
 284 */
 285int counter_count_write_value_get(void *const data,
 286				  const enum counter_count_value_type type,
 287				  const struct counter_count_write_value *const val)
 288{
 289	int err;
 290
 291	switch (type) {
 292	case COUNTER_COUNT_POSITION:
 293		err = kstrtoul(val->buf, 0, data);
 294		if (err)
 295			return err;
 296		break;
 297	}
 298
 299	return 0;
 300}
 301EXPORT_SYMBOL_GPL(counter_count_write_value_get);
 302
 303struct counter_attr_parm {
 304	struct counter_device_attr_group *group;
 305	const char *prefix;
 306	const char *name;
 307	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 308			char *buf);
 309	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 310			 const char *buf, size_t len);
 311	void *component;
 312};
 313
 314struct counter_device_attr {
 315	struct device_attribute dev_attr;
 316	struct list_head l;
 317	void *component;
 318};
 319
 320static int counter_attribute_create(const struct counter_attr_parm *const parm)
 321{
 322	struct counter_device_attr *counter_attr;
 323	struct device_attribute *dev_attr;
 324	int err;
 325	struct list_head *const attr_list = &parm->group->attr_list;
 326
 327	/* Allocate a Counter device attribute */
 328	counter_attr = kzalloc(sizeof(*counter_attr), GFP_KERNEL);
 329	if (!counter_attr)
 330		return -ENOMEM;
 331	dev_attr = &counter_attr->dev_attr;
 332
 333	sysfs_attr_init(&dev_attr->attr);
 334
 335	/* Configure device attribute */
 336	dev_attr->attr.name = kasprintf(GFP_KERNEL, "%s%s", parm->prefix,
 337					parm->name);
 338	if (!dev_attr->attr.name) {
 339		err = -ENOMEM;
 340		goto err_free_counter_attr;
 341	}
 342	if (parm->show) {
 343		dev_attr->attr.mode |= 0444;
 344		dev_attr->show = parm->show;
 345	}
 346	if (parm->store) {
 347		dev_attr->attr.mode |= 0200;
 348		dev_attr->store = parm->store;
 349	}
 350
 351	/* Store associated Counter component with attribute */
 352	counter_attr->component = parm->component;
 353
 354	/* Keep track of the attribute for later cleanup */
 355	list_add(&counter_attr->l, attr_list);
 356	parm->group->num_attr++;
 357
 358	return 0;
 359
 360err_free_counter_attr:
 361	kfree(counter_attr);
 362	return err;
 363}
 364
 365#define to_counter_attr(_dev_attr) \
 366	container_of(_dev_attr, struct counter_device_attr, dev_attr)
 367
 368struct counter_signal_unit {
 369	struct counter_signal *signal;
 370};
 371
 372static ssize_t counter_signal_show(struct device *dev,
 373				   struct device_attribute *attr, char *buf)
 374{
 375	struct counter_device *const counter = dev_get_drvdata(dev);
 376	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 377	const struct counter_signal_unit *const component = devattr->component;
 378	struct counter_signal *const signal = component->signal;
 379	int err;
 380	struct counter_signal_read_value val = { .buf = buf };
 381
 382	err = counter->ops->signal_read(counter, signal, &val);
 383	if (err)
 384		return err;
 385
 386	return val.len;
 387}
 388
 389struct counter_name_unit {
 390	const char *name;
 391};
 392
 393static ssize_t counter_device_attr_name_show(struct device *dev,
 394					     struct device_attribute *attr,
 395					     char *buf)
 396{
 397	const struct counter_name_unit *const comp = to_counter_attr(attr)->component;
 398
 399	return sprintf(buf, "%s\n", comp->name);
 400}
 401
 402static int counter_name_attribute_create(
 403	struct counter_device_attr_group *const group,
 404	const char *const name)
 405{
 406	struct counter_name_unit *name_comp;
 407	struct counter_attr_parm parm;
 408	int err;
 409
 410	/* Skip if no name */
 411	if (!name)
 412		return 0;
 413
 414	/* Allocate name attribute component */
 415	name_comp = kmalloc(sizeof(*name_comp), GFP_KERNEL);
 416	if (!name_comp)
 417		return -ENOMEM;
 418	name_comp->name = name;
 419
 420	/* Allocate Signal name attribute */
 421	parm.group = group;
 422	parm.prefix = "";
 423	parm.name = "name";
 424	parm.show = counter_device_attr_name_show;
 425	parm.store = NULL;
 426	parm.component = name_comp;
 427	err = counter_attribute_create(&parm);
 428	if (err)
 429		goto err_free_name_comp;
 430
 431	return 0;
 432
 433err_free_name_comp:
 434	kfree(name_comp);
 435	return err;
 436}
 437
 438struct counter_signal_ext_unit {
 439	struct counter_signal *signal;
 440	const struct counter_signal_ext *ext;
 441};
 442
 443static ssize_t counter_signal_ext_show(struct device *dev,
 444				       struct device_attribute *attr, char *buf)
 445{
 446	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 447	const struct counter_signal_ext_unit *const comp = devattr->component;
 448	const struct counter_signal_ext *const ext = comp->ext;
 449
 450	return ext->read(dev_get_drvdata(dev), comp->signal, ext->priv, buf);
 451}
 452
 453static ssize_t counter_signal_ext_store(struct device *dev,
 454					struct device_attribute *attr,
 455					const char *buf, size_t len)
 456{
 457	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 458	const struct counter_signal_ext_unit *const comp = devattr->component;
 459	const struct counter_signal_ext *const ext = comp->ext;
 460
 461	return ext->write(dev_get_drvdata(dev), comp->signal, ext->priv, buf,
 462		len);
 463}
 464
 465static void counter_device_attr_list_free(struct list_head *attr_list)
 466{
 467	struct counter_device_attr *p, *n;
 468
 469	list_for_each_entry_safe(p, n, attr_list, l) {
 470		/* free attribute name and associated component memory */
 471		kfree(p->dev_attr.attr.name);
 472		kfree(p->component);
 473		list_del(&p->l);
 474		kfree(p);
 475	}
 476}
 477
 478static int counter_signal_ext_register(
 479	struct counter_device_attr_group *const group,
 480	struct counter_signal *const signal)
 481{
 482	const size_t num_ext = signal->num_ext;
 483	size_t i;
 484	const struct counter_signal_ext *ext;
 485	struct counter_signal_ext_unit *signal_ext_comp;
 486	struct counter_attr_parm parm;
 487	int err;
 488
 489	/* Create an attribute for each extension */
 490	for (i = 0 ; i < num_ext; i++) {
 491		ext = signal->ext + i;
 492
 493		/* Allocate signal_ext attribute component */
 494		signal_ext_comp = kmalloc(sizeof(*signal_ext_comp), GFP_KERNEL);
 495		if (!signal_ext_comp) {
 496			err = -ENOMEM;
 497			goto err_free_attr_list;
 498		}
 499		signal_ext_comp->signal = signal;
 500		signal_ext_comp->ext = ext;
 501
 502		/* Allocate a Counter device attribute */
 503		parm.group = group;
 504		parm.prefix = "";
 505		parm.name = ext->name;
 506		parm.show = (ext->read) ? counter_signal_ext_show : NULL;
 507		parm.store = (ext->write) ? counter_signal_ext_store : NULL;
 508		parm.component = signal_ext_comp;
 509		err = counter_attribute_create(&parm);
 510		if (err) {
 511			kfree(signal_ext_comp);
 512			goto err_free_attr_list;
 513		}
 514	}
 515
 516	return 0;
 517
 518err_free_attr_list:
 519	counter_device_attr_list_free(&group->attr_list);
 520	return err;
 521}
 522
 523static int counter_signal_attributes_create(
 524	struct counter_device_attr_group *const group,
 525	const struct counter_device *const counter,
 526	struct counter_signal *const signal)
 527{
 528	struct counter_signal_unit *signal_comp;
 529	struct counter_attr_parm parm;
 530	int err;
 531
 532	/* Allocate Signal attribute component */
 533	signal_comp = kmalloc(sizeof(*signal_comp), GFP_KERNEL);
 534	if (!signal_comp)
 535		return -ENOMEM;
 536	signal_comp->signal = signal;
 537
 538	/* Create main Signal attribute */
 539	parm.group = group;
 540	parm.prefix = "";
 541	parm.name = "signal";
 542	parm.show = (counter->ops->signal_read) ? counter_signal_show : NULL;
 543	parm.store = NULL;
 544	parm.component = signal_comp;
 545	err = counter_attribute_create(&parm);
 546	if (err) {
 547		kfree(signal_comp);
 548		return err;
 549	}
 550
 551	/* Create Signal name attribute */
 552	err = counter_name_attribute_create(group, signal->name);
 553	if (err)
 554		goto err_free_attr_list;
 555
 556	/* Register Signal extension attributes */
 557	err = counter_signal_ext_register(group, signal);
 558	if (err)
 559		goto err_free_attr_list;
 560
 561	return 0;
 562
 563err_free_attr_list:
 564	counter_device_attr_list_free(&group->attr_list);
 565	return err;
 566}
 567
 568static int counter_signals_register(
 569	struct counter_device_attr_group *const groups_list,
 570	const struct counter_device *const counter)
 571{
 572	const size_t num_signals = counter->num_signals;
 573	size_t i;
 574	struct counter_signal *signal;
 575	const char *name;
 576	int err;
 577
 578	/* Register each Signal */
 579	for (i = 0; i < num_signals; i++) {
 580		signal = counter->signals + i;
 581
 582		/* Generate Signal attribute directory name */
 583		name = kasprintf(GFP_KERNEL, "signal%d", signal->id);
 584		if (!name) {
 585			err = -ENOMEM;
 586			goto err_free_attr_groups;
 587		}
 588		groups_list[i].attr_group.name = name;
 589
 590		/* Create all attributes associated with Signal */
 591		err = counter_signal_attributes_create(groups_list + i, counter,
 592						       signal);
 593		if (err)
 594			goto err_free_attr_groups;
 595	}
 596
 597	return 0;
 598
 599err_free_attr_groups:
 600	do {
 601		kfree(groups_list[i].attr_group.name);
 602		counter_device_attr_list_free(&groups_list[i].attr_list);
 603	} while (i--);
 604	return err;
 605}
 606
 607static const char *const counter_synapse_action_str[] = {
 608	[COUNTER_SYNAPSE_ACTION_NONE] = "none",
 609	[COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge",
 610	[COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge",
 611	[COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges"
 612};
 613
 614struct counter_action_unit {
 615	struct counter_synapse *synapse;
 616	struct counter_count *count;
 617};
 618
 619static ssize_t counter_action_show(struct device *dev,
 620				   struct device_attribute *attr, char *buf)
 621{
 622	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 623	int err;
 624	struct counter_device *const counter = dev_get_drvdata(dev);
 625	const struct counter_action_unit *const component = devattr->component;
 626	struct counter_count *const count = component->count;
 627	struct counter_synapse *const synapse = component->synapse;
 628	size_t action_index;
 629	enum counter_synapse_action action;
 630
 631	err = counter->ops->action_get(counter, count, synapse, &action_index);
 632	if (err)
 633		return err;
 634
 635	synapse->action = action_index;
 636
 637	action = synapse->actions_list[action_index];
 638	return sprintf(buf, "%s\n", counter_synapse_action_str[action]);
 639}
 640
 641static ssize_t counter_action_store(struct device *dev,
 642				    struct device_attribute *attr,
 643				    const char *buf, size_t len)
 644{
 645	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 646	const struct counter_action_unit *const component = devattr->component;
 647	struct counter_synapse *const synapse = component->synapse;
 648	size_t action_index;
 649	const size_t num_actions = synapse->num_actions;
 650	enum counter_synapse_action action;
 651	int err;
 652	struct counter_device *const counter = dev_get_drvdata(dev);
 653	struct counter_count *const count = component->count;
 654
 655	/* Find requested action mode */
 656	for (action_index = 0; action_index < num_actions; action_index++) {
 657		action = synapse->actions_list[action_index];
 658		if (sysfs_streq(buf, counter_synapse_action_str[action]))
 659			break;
 660	}
 661	/* If requested action mode not found */
 662	if (action_index >= num_actions)
 663		return -EINVAL;
 664
 665	err = counter->ops->action_set(counter, count, synapse, action_index);
 666	if (err)
 667		return err;
 668
 669	synapse->action = action_index;
 670
 671	return len;
 672}
 673
 674struct counter_action_avail_unit {
 675	const enum counter_synapse_action *actions_list;
 676	size_t num_actions;
 677};
 678
 679static ssize_t counter_synapse_action_available_show(struct device *dev,
 680	struct device_attribute *attr, char *buf)
 681{
 682	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 683	const struct counter_action_avail_unit *const component = devattr->component;
 684	size_t i;
 685	enum counter_synapse_action action;
 686	ssize_t len = 0;
 687
 688	for (i = 0; i < component->num_actions; i++) {
 689		action = component->actions_list[i];
 690		len += sprintf(buf + len, "%s\n",
 691			       counter_synapse_action_str[action]);
 692	}
 693
 694	return len;
 695}
 696
 697static int counter_synapses_register(
 698	struct counter_device_attr_group *const group,
 699	const struct counter_device *const counter,
 700	struct counter_count *const count, const char *const count_attr_name)
 701{
 702	size_t i;
 703	struct counter_synapse *synapse;
 704	const char *prefix;
 705	struct counter_action_unit *action_comp;
 706	struct counter_attr_parm parm;
 707	int err;
 708	struct counter_action_avail_unit *avail_comp;
 709
 710	/* Register each Synapse */
 711	for (i = 0; i < count->num_synapses; i++) {
 712		synapse = count->synapses + i;
 713
 714		/* Generate attribute prefix */
 715		prefix = kasprintf(GFP_KERNEL, "signal%d_",
 716				   synapse->signal->id);
 717		if (!prefix) {
 718			err = -ENOMEM;
 719			goto err_free_attr_list;
 720		}
 721
 722		/* Allocate action attribute component */
 723		action_comp = kmalloc(sizeof(*action_comp), GFP_KERNEL);
 724		if (!action_comp) {
 725			err = -ENOMEM;
 726			goto err_free_prefix;
 727		}
 728		action_comp->synapse = synapse;
 729		action_comp->count = count;
 730
 731		/* Create action attribute */
 732		parm.group = group;
 733		parm.prefix = prefix;
 734		parm.name = "action";
 735		parm.show = (counter->ops->action_get) ? counter_action_show : NULL;
 736		parm.store = (counter->ops->action_set) ? counter_action_store : NULL;
 737		parm.component = action_comp;
 738		err = counter_attribute_create(&parm);
 739		if (err) {
 740			kfree(action_comp);
 741			goto err_free_prefix;
 742		}
 743
 744		/* Allocate action available attribute component */
 745		avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
 746		if (!avail_comp) {
 747			err = -ENOMEM;
 748			goto err_free_prefix;
 749		}
 750		avail_comp->actions_list = synapse->actions_list;
 751		avail_comp->num_actions = synapse->num_actions;
 752
 753		/* Create action_available attribute */
 754		parm.group = group;
 755		parm.prefix = prefix;
 756		parm.name = "action_available";
 757		parm.show = counter_synapse_action_available_show;
 758		parm.store = NULL;
 759		parm.component = avail_comp;
 760		err = counter_attribute_create(&parm);
 761		if (err) {
 762			kfree(avail_comp);
 763			goto err_free_prefix;
 764		}
 765
 766		kfree(prefix);
 767	}
 768
 769	return 0;
 770
 771err_free_prefix:
 772	kfree(prefix);
 773err_free_attr_list:
 774	counter_device_attr_list_free(&group->attr_list);
 775	return err;
 776}
 777
 778struct counter_count_unit {
 779	struct counter_count *count;
 780};
 781
 782static ssize_t counter_count_show(struct device *dev,
 783				  struct device_attribute *attr,
 784				  char *buf)
 785{
 786	struct counter_device *const counter = dev_get_drvdata(dev);
 787	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 788	const struct counter_count_unit *const component = devattr->component;
 789	struct counter_count *const count = component->count;
 790	int err;
 791	struct counter_count_read_value val = { .buf = buf };
 792
 793	err = counter->ops->count_read(counter, count, &val);
 794	if (err)
 795		return err;
 796
 797	return val.len;
 798}
 799
 800static ssize_t counter_count_store(struct device *dev,
 801				   struct device_attribute *attr,
 802				   const char *buf, size_t len)
 803{
 804	struct counter_device *const counter = dev_get_drvdata(dev);
 805	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 806	const struct counter_count_unit *const component = devattr->component;
 807	struct counter_count *const count = component->count;
 808	int err;
 809	struct counter_count_write_value val = { .buf = buf };
 810
 811	err = counter->ops->count_write(counter, count, &val);
 812	if (err)
 813		return err;
 814
 815	return len;
 816}
 817
 818static const char *const counter_count_function_str[] = {
 819	[COUNTER_COUNT_FUNCTION_INCREASE] = "increase",
 820	[COUNTER_COUNT_FUNCTION_DECREASE] = "decrease",
 821	[COUNTER_COUNT_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
 822	[COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
 823	[COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
 824	[COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
 825	[COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
 826	[COUNTER_COUNT_FUNCTION_QUADRATURE_X4] = "quadrature x4"
 827};
 828
 829static ssize_t counter_function_show(struct device *dev,
 830				     struct device_attribute *attr, char *buf)
 831{
 832	int err;
 833	struct counter_device *const counter = dev_get_drvdata(dev);
 834	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 835	const struct counter_count_unit *const component = devattr->component;
 836	struct counter_count *const count = component->count;
 837	size_t func_index;
 838	enum counter_count_function function;
 839
 840	err = counter->ops->function_get(counter, count, &func_index);
 841	if (err)
 842		return err;
 843
 844	count->function = func_index;
 845
 846	function = count->functions_list[func_index];
 847	return sprintf(buf, "%s\n", counter_count_function_str[function]);
 848}
 849
 850static ssize_t counter_function_store(struct device *dev,
 851				      struct device_attribute *attr,
 852				      const char *buf, size_t len)
 853{
 854	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 855	const struct counter_count_unit *const component = devattr->component;
 856	struct counter_count *const count = component->count;
 857	const size_t num_functions = count->num_functions;
 858	size_t func_index;
 859	enum counter_count_function function;
 860	int err;
 861	struct counter_device *const counter = dev_get_drvdata(dev);
 862
 863	/* Find requested Count function mode */
 864	for (func_index = 0; func_index < num_functions; func_index++) {
 865		function = count->functions_list[func_index];
 866		if (sysfs_streq(buf, counter_count_function_str[function]))
 867			break;
 868	}
 869	/* Return error if requested Count function mode not found */
 870	if (func_index >= num_functions)
 871		return -EINVAL;
 872
 873	err = counter->ops->function_set(counter, count, func_index);
 874	if (err)
 875		return err;
 876
 877	count->function = func_index;
 878
 879	return len;
 880}
 881
 882struct counter_count_ext_unit {
 883	struct counter_count *count;
 884	const struct counter_count_ext *ext;
 885};
 886
 887static ssize_t counter_count_ext_show(struct device *dev,
 888				      struct device_attribute *attr, char *buf)
 889{
 890	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 891	const struct counter_count_ext_unit *const comp = devattr->component;
 892	const struct counter_count_ext *const ext = comp->ext;
 893
 894	return ext->read(dev_get_drvdata(dev), comp->count, ext->priv, buf);
 895}
 896
 897static ssize_t counter_count_ext_store(struct device *dev,
 898				       struct device_attribute *attr,
 899				       const char *buf, size_t len)
 900{
 901	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 902	const struct counter_count_ext_unit *const comp = devattr->component;
 903	const struct counter_count_ext *const ext = comp->ext;
 904
 905	return ext->write(dev_get_drvdata(dev), comp->count, ext->priv, buf,
 906		len);
 907}
 908
 909static int counter_count_ext_register(
 910	struct counter_device_attr_group *const group,
 911	struct counter_count *const count)
 912{
 913	size_t i;
 914	const struct counter_count_ext *ext;
 915	struct counter_count_ext_unit *count_ext_comp;
 916	struct counter_attr_parm parm;
 917	int err;
 918
 919	/* Create an attribute for each extension */
 920	for (i = 0 ; i < count->num_ext; i++) {
 921		ext = count->ext + i;
 922
 923		/* Allocate count_ext attribute component */
 924		count_ext_comp = kmalloc(sizeof(*count_ext_comp), GFP_KERNEL);
 925		if (!count_ext_comp) {
 926			err = -ENOMEM;
 927			goto err_free_attr_list;
 928		}
 929		count_ext_comp->count = count;
 930		count_ext_comp->ext = ext;
 931
 932		/* Allocate count_ext attribute */
 933		parm.group = group;
 934		parm.prefix = "";
 935		parm.name = ext->name;
 936		parm.show = (ext->read) ? counter_count_ext_show : NULL;
 937		parm.store = (ext->write) ? counter_count_ext_store : NULL;
 938		parm.component = count_ext_comp;
 939		err = counter_attribute_create(&parm);
 940		if (err) {
 941			kfree(count_ext_comp);
 942			goto err_free_attr_list;
 943		}
 944	}
 945
 946	return 0;
 947
 948err_free_attr_list:
 949	counter_device_attr_list_free(&group->attr_list);
 950	return err;
 951}
 952
 953struct counter_func_avail_unit {
 954	const enum counter_count_function *functions_list;
 955	size_t num_functions;
 956};
 957
 958static ssize_t counter_count_function_available_show(struct device *dev,
 959	struct device_attribute *attr, char *buf)
 960{
 961	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 962	const struct counter_func_avail_unit *const component = devattr->component;
 963	const enum counter_count_function *const func_list = component->functions_list;
 964	const size_t num_functions = component->num_functions;
 965	size_t i;
 966	enum counter_count_function function;
 967	ssize_t len = 0;
 968
 969	for (i = 0; i < num_functions; i++) {
 970		function = func_list[i];
 971		len += sprintf(buf + len, "%s\n",
 972			       counter_count_function_str[function]);
 973	}
 974
 975	return len;
 976}
 977
 978static int counter_count_attributes_create(
 979	struct counter_device_attr_group *const group,
 980	const struct counter_device *const counter,
 981	struct counter_count *const count)
 982{
 983	struct counter_count_unit *count_comp;
 984	struct counter_attr_parm parm;
 985	int err;
 986	struct counter_count_unit *func_comp;
 987	struct counter_func_avail_unit *avail_comp;
 988
 989	/* Allocate count attribute component */
 990	count_comp = kmalloc(sizeof(*count_comp), GFP_KERNEL);
 991	if (!count_comp)
 992		return -ENOMEM;
 993	count_comp->count = count;
 994
 995	/* Create main Count attribute */
 996	parm.group = group;
 997	parm.prefix = "";
 998	parm.name = "count";
 999	parm.show = (counter->ops->count_read) ? counter_count_show : NULL;
1000	parm.store = (counter->ops->count_write) ? counter_count_store : NULL;
1001	parm.component = count_comp;
1002	err = counter_attribute_create(&parm);
1003	if (err) {
1004		kfree(count_comp);
1005		return err;
1006	}
1007
1008	/* Allocate function attribute component */
1009	func_comp = kmalloc(sizeof(*func_comp), GFP_KERNEL);
1010	if (!func_comp) {
1011		err = -ENOMEM;
1012		goto err_free_attr_list;
1013	}
1014	func_comp->count = count;
1015
1016	/* Create Count function attribute */
1017	parm.group = group;
1018	parm.prefix = "";
1019	parm.name = "function";
1020	parm.show = (counter->ops->function_get) ? counter_function_show : NULL;
1021	parm.store = (counter->ops->function_set) ? counter_function_store : NULL;
1022	parm.component = func_comp;
1023	err = counter_attribute_create(&parm);
1024	if (err) {
1025		kfree(func_comp);
1026		goto err_free_attr_list;
1027	}
1028
1029	/* Allocate function available attribute component */
1030	avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
1031	if (!avail_comp) {
1032		err = -ENOMEM;
1033		goto err_free_attr_list;
1034	}
1035	avail_comp->functions_list = count->functions_list;
1036	avail_comp->num_functions = count->num_functions;
1037
1038	/* Create Count function_available attribute */
1039	parm.group = group;
1040	parm.prefix = "";
1041	parm.name = "function_available";
1042	parm.show = counter_count_function_available_show;
1043	parm.store = NULL;
1044	parm.component = avail_comp;
1045	err = counter_attribute_create(&parm);
1046	if (err) {
1047		kfree(avail_comp);
1048		goto err_free_attr_list;
1049	}
1050
1051	/* Create Count name attribute */
1052	err = counter_name_attribute_create(group, count->name);
1053	if (err)
1054		goto err_free_attr_list;
1055
1056	/* Register Count extension attributes */
1057	err = counter_count_ext_register(group, count);
1058	if (err)
1059		goto err_free_attr_list;
1060
1061	return 0;
1062
1063err_free_attr_list:
1064	counter_device_attr_list_free(&group->attr_list);
1065	return err;
1066}
1067
1068static int counter_counts_register(
1069	struct counter_device_attr_group *const groups_list,
1070	const struct counter_device *const counter)
1071{
1072	size_t i;
1073	struct counter_count *count;
1074	const char *name;
1075	int err;
1076
1077	/* Register each Count */
1078	for (i = 0; i < counter->num_counts; i++) {
1079		count = counter->counts + i;
1080
1081		/* Generate Count attribute directory name */
1082		name = kasprintf(GFP_KERNEL, "count%d", count->id);
1083		if (!name) {
1084			err = -ENOMEM;
1085			goto err_free_attr_groups;
1086		}
1087		groups_list[i].attr_group.name = name;
1088
1089		/* Register the Synapses associated with each Count */
1090		err = counter_synapses_register(groups_list + i, counter, count,
1091						name);
1092		if (err)
1093			goto err_free_attr_groups;
1094
1095		/* Create all attributes associated with Count */
1096		err = counter_count_attributes_create(groups_list + i, counter,
1097						      count);
1098		if (err)
1099			goto err_free_attr_groups;
1100	}
1101
1102	return 0;
1103
1104err_free_attr_groups:
1105	do {
1106		kfree(groups_list[i].attr_group.name);
1107		counter_device_attr_list_free(&groups_list[i].attr_list);
1108	} while (i--);
1109	return err;
1110}
1111
1112struct counter_size_unit {
1113	size_t size;
1114};
1115
1116static ssize_t counter_device_attr_size_show(struct device *dev,
1117					     struct device_attribute *attr,
1118					     char *buf)
1119{
1120	const struct counter_size_unit *const comp = to_counter_attr(attr)->component;
1121
1122	return sprintf(buf, "%zu\n", comp->size);
1123}
1124
1125static int counter_size_attribute_create(
1126	struct counter_device_attr_group *const group,
1127	const size_t size, const char *const name)
1128{
1129	struct counter_size_unit *size_comp;
1130	struct counter_attr_parm parm;
1131	int err;
1132
1133	/* Allocate size attribute component */
1134	size_comp = kmalloc(sizeof(*size_comp), GFP_KERNEL);
1135	if (!size_comp)
1136		return -ENOMEM;
1137	size_comp->size = size;
1138
1139	parm.group = group;
1140	parm.prefix = "";
1141	parm.name = name;
1142	parm.show = counter_device_attr_size_show;
1143	parm.store = NULL;
1144	parm.component = size_comp;
1145	err = counter_attribute_create(&parm);
1146	if (err)
1147		goto err_free_size_comp;
1148
1149	return 0;
1150
1151err_free_size_comp:
1152	kfree(size_comp);
1153	return err;
1154}
1155
1156struct counter_ext_unit {
1157	const struct counter_device_ext *ext;
1158};
1159
1160static ssize_t counter_device_ext_show(struct device *dev,
1161				       struct device_attribute *attr, char *buf)
1162{
1163	const struct counter_device_attr *const devattr = to_counter_attr(attr);
1164	const struct counter_ext_unit *const component = devattr->component;
1165	const struct counter_device_ext *const ext = component->ext;
1166
1167	return ext->read(dev_get_drvdata(dev), ext->priv, buf);
1168}
1169
1170static ssize_t counter_device_ext_store(struct device *dev,
1171					struct device_attribute *attr,
1172					const char *buf, size_t len)
1173{
1174	const struct counter_device_attr *const devattr = to_counter_attr(attr);
1175	const struct counter_ext_unit *const component = devattr->component;
1176	const struct counter_device_ext *const ext = component->ext;
1177
1178	return ext->write(dev_get_drvdata(dev), ext->priv, buf, len);
1179}
1180
1181static int counter_device_ext_register(
1182	struct counter_device_attr_group *const group,
1183	struct counter_device *const counter)
1184{
1185	size_t i;
1186	struct counter_ext_unit *ext_comp;
1187	struct counter_attr_parm parm;
1188	int err;
1189
1190	/* Create an attribute for each extension */
1191	for (i = 0 ; i < counter->num_ext; i++) {
1192		/* Allocate extension attribute component */
1193		ext_comp = kmalloc(sizeof(*ext_comp), GFP_KERNEL);
1194		if (!ext_comp) {
1195			err = -ENOMEM;
1196			goto err_free_attr_list;
1197		}
1198
1199		ext_comp->ext = counter->ext + i;
1200
1201		/* Allocate extension attribute */
1202		parm.group = group;
1203		parm.prefix = "";
1204		parm.name = counter->ext[i].name;
1205		parm.show = (counter->ext[i].read) ? counter_device_ext_show : NULL;
1206		parm.store = (counter->ext[i].write) ? counter_device_ext_store : NULL;
1207		parm.component = ext_comp;
1208		err = counter_attribute_create(&parm);
1209		if (err) {
1210			kfree(ext_comp);
1211			goto err_free_attr_list;
1212		}
1213	}
1214
1215	return 0;
1216
1217err_free_attr_list:
1218	counter_device_attr_list_free(&group->attr_list);
1219	return err;
1220}
1221
1222static int counter_global_attr_register(
1223	struct counter_device_attr_group *const group,
1224	struct counter_device *const counter)
1225{
1226	int err;
1227
1228	/* Create name attribute */
1229	err = counter_name_attribute_create(group, counter->name);
1230	if (err)
1231		return err;
1232
1233	/* Create num_counts attribute */
1234	err = counter_size_attribute_create(group, counter->num_counts,
1235					    "num_counts");
1236	if (err)
1237		goto err_free_attr_list;
1238
1239	/* Create num_signals attribute */
1240	err = counter_size_attribute_create(group, counter->num_signals,
1241					    "num_signals");
1242	if (err)
1243		goto err_free_attr_list;
1244
1245	/* Register Counter device extension attributes */
1246	err = counter_device_ext_register(group, counter);
1247	if (err)
1248		goto err_free_attr_list;
1249
1250	return 0;
1251
1252err_free_attr_list:
1253	counter_device_attr_list_free(&group->attr_list);
1254	return err;
1255}
1256
1257static void counter_device_groups_list_free(
1258	struct counter_device_attr_group *const groups_list,
1259	const size_t num_groups)
1260{
1261	struct counter_device_attr_group *group;
1262	size_t i;
1263
1264	/* loop through all attribute groups (signals, counts, global, etc.) */
1265	for (i = 0; i < num_groups; i++) {
1266		group = groups_list + i;
1267
1268		/* free all attribute group and associated attributes memory */
1269		kfree(group->attr_group.name);
1270		kfree(group->attr_group.attrs);
1271		counter_device_attr_list_free(&group->attr_list);
1272	}
1273
1274	kfree(groups_list);
1275}
1276
1277static int counter_device_groups_list_prepare(
1278	struct counter_device *const counter)
1279{
1280	const size_t total_num_groups =
1281		counter->num_signals + counter->num_counts + 1;
1282	struct counter_device_attr_group *groups_list;
1283	size_t i;
1284	int err;
1285	size_t num_groups = 0;
1286
1287	/* Allocate space for attribute groups (signals, counts, and ext) */
1288	groups_list = kcalloc(total_num_groups, sizeof(*groups_list),
1289			      GFP_KERNEL);
1290	if (!groups_list)
1291		return -ENOMEM;
1292
1293	/* Initialize attribute lists */
1294	for (i = 0; i < total_num_groups; i++)
1295		INIT_LIST_HEAD(&groups_list[i].attr_list);
1296
1297	/* Register Signals */
1298	err = counter_signals_register(groups_list, counter);
1299	if (err)
1300		goto err_free_groups_list;
1301	num_groups += counter->num_signals;
1302
1303	/* Register Counts and respective Synapses */
1304	err = counter_counts_register(groups_list + num_groups, counter);
1305	if (err)
1306		goto err_free_groups_list;
1307	num_groups += counter->num_counts;
1308
1309	/* Register Counter global attributes */
1310	err = counter_global_attr_register(groups_list + num_groups, counter);
1311	if (err)
1312		goto err_free_groups_list;
1313	num_groups++;
1314
1315	/* Store groups_list in device_state */
1316	counter->device_state->groups_list = groups_list;
1317	counter->device_state->num_groups = num_groups;
1318
1319	return 0;
1320
1321err_free_groups_list:
1322	counter_device_groups_list_free(groups_list, num_groups);
1323	return err;
1324}
1325
1326static int counter_device_groups_prepare(
1327	struct counter_device_state *const device_state)
1328{
1329	size_t i, j;
1330	struct counter_device_attr_group *group;
1331	int err;
1332	struct counter_device_attr *p;
1333
1334	/* Allocate attribute groups for association with device */
1335	device_state->groups = kcalloc(device_state->num_groups + 1,
1336				       sizeof(*device_state->groups),
1337				       GFP_KERNEL);
1338	if (!device_state->groups)
1339		return -ENOMEM;
1340
1341	/* Prepare each group of attributes for association */
1342	for (i = 0; i < device_state->num_groups; i++) {
1343		group = device_state->groups_list + i;
1344
1345		/* Allocate space for attribute pointers in attribute group */
1346		group->attr_group.attrs = kcalloc(group->num_attr + 1,
1347			sizeof(*group->attr_group.attrs), GFP_KERNEL);
1348		if (!group->attr_group.attrs) {
1349			err = -ENOMEM;
1350			goto err_free_groups;
1351		}
1352
1353		/* Add attribute pointers to attribute group */
1354		j = 0;
1355		list_for_each_entry(p, &group->attr_list, l)
1356			group->attr_group.attrs[j++] = &p->dev_attr.attr;
1357
1358		/* Group attributes in attribute group */
1359		device_state->groups[i] = &group->attr_group;
1360	}
1361	/* Associate attributes with device */
1362	device_state->dev.groups = device_state->groups;
1363
1364	return 0;
1365
1366err_free_groups:
1367	do {
1368		group = device_state->groups_list + i;
1369		kfree(group->attr_group.attrs);
1370		group->attr_group.attrs = NULL;
1371	} while (i--);
1372	kfree(device_state->groups);
1373	return err;
1374}
1375
1376/* Provides a unique ID for each counter device */
1377static DEFINE_IDA(counter_ida);
1378
1379static void counter_device_release(struct device *dev)
1380{
1381	struct counter_device *const counter = dev_get_drvdata(dev);
1382	struct counter_device_state *const device_state = counter->device_state;
1383
1384	kfree(device_state->groups);
1385	counter_device_groups_list_free(device_state->groups_list,
1386					device_state->num_groups);
1387	ida_simple_remove(&counter_ida, device_state->id);
1388	kfree(device_state);
1389}
1390
1391static struct device_type counter_device_type = {
1392	.name = "counter_device",
1393	.release = counter_device_release
1394};
1395
1396static struct bus_type counter_bus_type = {
1397	.name = "counter"
1398};
1399
1400/**
1401 * counter_register - register Counter to the system
1402 * @counter:	pointer to Counter to register
1403 *
1404 * This function registers a Counter to the system. A sysfs "counter" directory
1405 * will be created and populated with sysfs attributes correlating with the
1406 * Counter Signals, Synapses, and Counts respectively.
1407 */
1408int counter_register(struct counter_device *const counter)
1409{
1410	struct counter_device_state *device_state;
1411	int err;
1412
1413	/* Allocate internal state container for Counter device */
1414	device_state = kzalloc(sizeof(*device_state), GFP_KERNEL);
1415	if (!device_state)
1416		return -ENOMEM;
1417	counter->device_state = device_state;
1418
1419	/* Acquire unique ID */
1420	device_state->id = ida_simple_get(&counter_ida, 0, 0, GFP_KERNEL);
1421	if (device_state->id < 0) {
1422		err = device_state->id;
1423		goto err_free_device_state;
1424	}
1425
1426	/* Configure device structure for Counter */
1427	device_state->dev.type = &counter_device_type;
1428	device_state->dev.bus = &counter_bus_type;
1429	if (counter->parent) {
1430		device_state->dev.parent = counter->parent;
1431		device_state->dev.of_node = counter->parent->of_node;
1432	}
1433	dev_set_name(&device_state->dev, "counter%d", device_state->id);
1434	device_initialize(&device_state->dev);
1435	dev_set_drvdata(&device_state->dev, counter);
1436
1437	/* Prepare device attributes */
1438	err = counter_device_groups_list_prepare(counter);
1439	if (err)
1440		goto err_free_id;
1441
1442	/* Organize device attributes to groups and match to device */
1443	err = counter_device_groups_prepare(device_state);
1444	if (err)
1445		goto err_free_groups_list;
1446
1447	/* Add device to system */
1448	err = device_add(&device_state->dev);
1449	if (err)
1450		goto err_free_groups;
1451
1452	return 0;
1453
1454err_free_groups:
1455	kfree(device_state->groups);
1456err_free_groups_list:
1457	counter_device_groups_list_free(device_state->groups_list,
1458					device_state->num_groups);
1459err_free_id:
1460	ida_simple_remove(&counter_ida, device_state->id);
1461err_free_device_state:
1462	kfree(device_state);
1463	return err;
1464}
1465EXPORT_SYMBOL_GPL(counter_register);
1466
1467/**
1468 * counter_unregister - unregister Counter from the system
1469 * @counter:	pointer to Counter to unregister
1470 *
1471 * The Counter is unregistered from the system; all allocated memory is freed.
1472 */
1473void counter_unregister(struct counter_device *const counter)
1474{
1475	if (counter)
1476		device_del(&counter->device_state->dev);
1477}
1478EXPORT_SYMBOL_GPL(counter_unregister);
1479
1480static void devm_counter_unreg(struct device *dev, void *res)
1481{
1482	counter_unregister(*(struct counter_device **)res);
1483}
1484
1485/**
1486 * devm_counter_register - Resource-managed counter_register
1487 * @dev:	device to allocate counter_device for
1488 * @counter:	pointer to Counter to register
1489 *
1490 * Managed counter_register. The Counter registered with this function is
1491 * automatically unregistered on driver detach. This function calls
1492 * counter_register internally. Refer to that function for more information.
1493 *
1494 * If an Counter registered with this function needs to be unregistered
1495 * separately, devm_counter_unregister must be used.
1496 *
1497 * RETURNS:
1498 * 0 on success, negative error number on failure.
1499 */
1500int devm_counter_register(struct device *dev,
1501			  struct counter_device *const counter)
1502{
1503	struct counter_device **ptr;
1504	int ret;
1505
1506	ptr = devres_alloc(devm_counter_unreg, sizeof(*ptr), GFP_KERNEL);
1507	if (!ptr)
1508		return -ENOMEM;
1509
1510	ret = counter_register(counter);
1511	if (!ret) {
1512		*ptr = counter;
1513		devres_add(dev, ptr);
1514	} else {
1515		devres_free(ptr);
1516	}
1517
1518	return ret;
1519}
1520EXPORT_SYMBOL_GPL(devm_counter_register);
1521
1522static int devm_counter_match(struct device *dev, void *res, void *data)
1523{
1524	struct counter_device **r = res;
1525
1526	if (!r || !*r) {
1527		WARN_ON(!r || !*r);
1528		return 0;
1529	}
1530
1531	return *r == data;
1532}
1533
1534/**
1535 * devm_counter_unregister - Resource-managed counter_unregister
1536 * @dev:	device this counter_device belongs to
1537 * @counter:	pointer to Counter associated with the device
1538 *
1539 * Unregister Counter registered with devm_counter_register.
1540 */
1541void devm_counter_unregister(struct device *dev,
1542			     struct counter_device *const counter)
1543{
1544	int rc;
1545
1546	rc = devres_release(dev, devm_counter_unreg, devm_counter_match,
1547			    counter);
1548	WARN_ON(rc);
1549}
1550EXPORT_SYMBOL_GPL(devm_counter_unregister);
1551
1552static int __init counter_init(void)
1553{
1554	return bus_register(&counter_bus_type);
1555}
1556
1557static void __exit counter_exit(void)
1558{
1559	bus_unregister(&counter_bus_type);
1560}
1561
1562subsys_initcall(counter_init);
1563module_exit(counter_exit);
1564
1565MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1566MODULE_DESCRIPTION("Generic Counter interface");
1567MODULE_LICENSE("GPL v2");