counter-sysfs.c 32 KB

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