counter.c 40 KB

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