/arch/arm/mach-fsm/npa.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase · C · 1572 lines · 1166 code · 246 blank · 160 comment · 157 complexity · 08f28696f4476f1e8ac612cff21e3393 MD5 · raw file

  1. /* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. * 02110-1301, USA.
  16. *
  17. */
  18. /*
  19. * Node Power Architecture (NPA) implementation.
  20. */
  21. #include <linux/kernel.h>
  22. #include <linux/init.h>
  23. #include <linux/module.h>
  24. #include <linux/err.h>
  25. #include <linux/string.h>
  26. #include <linux/workqueue.h>
  27. #include <linux/spinlock_types.h>
  28. #include "npa.h"
  29. #include "npa_resource.h"
  30. #define NPA_STR_NPA_INTERNAL "NPA-Internal"
  31. #define NPA_STR_USER_CALLBACK "User-Callback"
  32. /* Resource lock could be called with NULL mutex, when only the container
  33. * is created and the node is not defined yet.
  34. */
  35. #ifdef CONFIG_MSM_NPA_LOG
  36. #define RESOURCE_LOCK(r) do { \
  37. BUG_ON(!r); \
  38. if ((r)->definition)\
  39. npa_log(NPA_LOG_MASK_LOCKS, r,\
  40. "NPA: Resource [%s] level [%u] locked [%p] at "\
  41. "line [%d] by process [%p]\n",\
  42. (r)->definition->name, (r)->level, (r)->resource_lock,\
  43. __LINE__, current);\
  44. if ((r)->resource_lock)\
  45. mutex_lock_nested((r)->resource_lock, (r)->level);\
  46. } \
  47. while (0)
  48. #define RESOURCE_UNLOCK(r) do { \
  49. BUG_ON(!r); \
  50. if ((r)->definition)\
  51. npa_log(NPA_LOG_MASK_LOCKS, r,\
  52. "NPA: Resource [%s] level [%u] unlocked [%p] at "\
  53. "line [%d] by process [%p]\n",\
  54. (r)->definition->name, (r)->level, (r)->resource_lock,\
  55. __LINE__, current);\
  56. if ((r)->resource_lock)\
  57. mutex_unlock((r)->resource_lock);\
  58. } \
  59. while (0)
  60. #else
  61. #define RESOURCE_LOCK(r) do { \
  62. BUG_ON(!r); \
  63. if ((r)->resource_lock) \
  64. mutex_lock_nested((r)->resource_lock, (r)->level) ;\
  65. } \
  66. while (0)
  67. #define RESOURCE_UNLOCK(r) do { \
  68. BUG_ON(!r); \
  69. if ((r)->resource_lock) \
  70. mutex_unlock((r)->resource_lock); \
  71. } \
  72. while (0)
  73. #endif
  74. #ifdef CONFIG_MSM_NPA_LOG
  75. int npa_log_mask;
  76. EXPORT_SYMBOL(npa_log_mask);
  77. char npa_log_resource_name[NPA_NAME_MAX] = {0};
  78. EXPORT_SYMBOL(npa_log_resource_name);
  79. int npa_log_reset;
  80. EXPORT_SYMBOL(npa_log_reset);
  81. module_param_named(log_mask, npa_log_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
  82. MODULE_PARM_DESC(npa_log_mask,
  83. "Specify NPA logging for any or all of "
  84. "resource, client states, events, lists, plugin or locks.");
  85. module_param_string(log_resource_name, npa_log_resource_name,
  86. sizeof(npa_log_resource_name), S_IRUGO | S_IWUSR | S_IWGRP);
  87. MODULE_PARM_DESC(npa_log_resource_name,
  88. "Specify logging for a specific NPA resource.");
  89. module_param_named(log_reset, npa_log_reset, int, S_IRUGO | S_IWUSR | S_IWGRP);
  90. MODULE_PARM_DESC(npa_log_reset, "Reset NPA module parameters.");
  91. struct npa_resource *npa_log_resource;
  92. #endif
  93. /* Maps resource name to alias name.*/
  94. struct npa_alias_list {
  95. struct list_head list;
  96. const char *alias;
  97. struct npa_resource *resource;
  98. };
  99. static LIST_HEAD(alias_list); /* List of aliases */
  100. static LIST_HEAD(active_list); /* Resources defined and active */
  101. static LIST_HEAD(waiting_list); /* Resources pending definition or waiting
  102. on dependencies. */
  103. static DEFINE_RWLOCK(list_lock);/* RW lock for locking active and waiting
  104. lists */
  105. static struct workqueue_struct *npa_wq;
  106. static struct npa_resource *__get_resource(const char *resource_name);
  107. static void resource_creation_handler(void *data, unsigned int state,
  108. void *called_data, unsigned int value);
  109. static void send_single_event(struct work_struct *work);
  110. static void send_update_events(struct work_struct *work);
  111. #ifdef CONFIG_MSM_NPA_LOG
  112. void _npa_log(int log_mask, struct npa_resource *res, const char *fmt, ...)
  113. {
  114. if (npa_log_reset) {
  115. npa_log_mask = 0;
  116. npa_log_resource = NULL;
  117. npa_log_resource_name[0] = 0;
  118. npa_log_reset = 0;
  119. }
  120. if (npa_log_resource_name[0] && !npa_log_resource) {
  121. npa_log_resource = __get_resource(npa_log_resource_name);
  122. if (npa_log_resource)
  123. pr_info("NPA: Logging for resource [%s]\n",
  124. npa_log_resource_name);
  125. }
  126. if (!npa_log_resource ||
  127. (npa_log_resource && (res == npa_log_resource)))
  128. if (log_mask & npa_log_mask) {
  129. va_list ap;
  130. va_start(ap, fmt);
  131. vprintk(fmt, ap);
  132. va_end(ap);
  133. }
  134. }
  135. void __print_resource(struct npa_resource *r)
  136. {
  137. struct npa_client *client = NULL;
  138. struct npa_event *e = NULL;
  139. struct npa_alias_list *a = NULL;
  140. const char *rname = r->definition->name;
  141. if (!(npa_log_mask & NPA_LOG_MASK_RESOURCE))
  142. return;
  143. list_for_each_entry(a, &alias_list, list) {
  144. if (!strncmp(a->resource->definition->name,
  145. r->definition->name, NPA_NAME_MAX)) {
  146. pr_info("NPA: Resource [%s] Alias: [%s]\n",
  147. rname, a->alias);
  148. }
  149. }
  150. pr_info("NPA: Resource [%s] Units: [%s]\n",
  151. rname, r->definition->units);
  152. pr_info("NPA: Resource [%s] Node name: [%s]\n",
  153. rname, r->node->name);
  154. pr_info("NPA: Resource [%s] Level: [%u]\n",
  155. rname, r->level);
  156. list_for_each_entry(client, &r->clients, list) {
  157. pr_info("NPA: Resource [%s] client [%s: %u]\n",
  158. rname, client->name, ACTIVE_STATE(client));
  159. }
  160. list_for_each_entry(e, &r->events, list) {
  161. pr_info("NPA: Reource [%s] event [%s, %d]\n",
  162. rname, e->handler_name, e->type);
  163. }
  164. pr_info("NPA: Resource [%s] Active state: [%u]\n",
  165. rname, r->active_state);
  166. pr_info("NPA: Resource [%s] Active max: [%u]\n",
  167. rname, r->active_max);
  168. pr_info("NPA: Resource [%s] Active headroom: [%u]\n",
  169. rname, r->active_headroom);
  170. }
  171. EXPORT_SYMBOL(__print_resource);
  172. void __print_resources(void)
  173. {
  174. struct npa_resource *resource = NULL;
  175. if (!(npa_log_mask & NPA_LOG_MASK_RESOURCE))
  176. return;
  177. list_for_each_entry(resource, &active_list, list)
  178. __print_resource(resource);
  179. list_for_each_entry(resource, &waiting_list, list)
  180. __print_resource(resource);
  181. }
  182. EXPORT_SYMBOL(__print_resources);
  183. void __print_client_states(struct npa_resource *resource)
  184. {
  185. struct npa_client *client = NULL;
  186. if (!(npa_log_mask & NPA_LOG_MASK_LIST))
  187. return;
  188. list_for_each_entry(client, &resource->clients, list) {
  189. pr_info("NPA: Resource [%s] client [%s: %u]\n",
  190. resource->definition->name,
  191. client->name, ACTIVE_STATE(client));
  192. }
  193. }
  194. EXPORT_SYMBOL(__print_client_states);
  195. void __print_aliases(void)
  196. {
  197. struct npa_alias_list *a = NULL;
  198. if (npa_log_mask & NPA_LOG_MASK_LIST)
  199. return;
  200. list_for_each_entry(a, &alias_list, list) {
  201. pr_info("NPA: Alias[%s --> %s]\n",
  202. a->alias, a->resource->definition->name);
  203. }
  204. }
  205. EXPORT_SYMBOL(__print_aliases);
  206. #endif
  207. /* Returns the resource, if the name matches any element in the list.
  208. * NULL if not found.
  209. * @resource_name can be original resource name or an alias.
  210. */
  211. static struct npa_resource *__get_resource(const char *resource_name)
  212. {
  213. struct npa_alias_list *alias = NULL;
  214. struct npa_alias_list *temp = NULL;
  215. list_for_each_entry_safe(alias, temp, &alias_list, list) {
  216. if (!strncmp(resource_name, alias->alias, NPA_NAME_MAX))
  217. return alias->resource;
  218. }
  219. return NULL;
  220. }
  221. static int __is_active_resource(struct npa_resource *resource)
  222. {
  223. struct npa_resource *res_itr = NULL;
  224. if (resource && !list_empty(&active_list)) {
  225. list_for_each_entry(res_itr, &active_list, list) {
  226. if (resource == res_itr)
  227. return 1;
  228. }
  229. }
  230. return 0;
  231. }
  232. static struct npa_resource *active_resource(const char *resource_name)
  233. {
  234. struct npa_resource *resource = NULL;
  235. read_lock(&list_lock);
  236. resource = __get_resource(resource_name);
  237. if (resource)
  238. resource = __is_active_resource(resource) ? resource : NULL;
  239. read_unlock(&list_lock);
  240. return resource;
  241. }
  242. /* Creates a resource object with the definition provided. The created
  243. * resource is automatically added to the waiting list. create_resource can be
  244. * called with an node pointer or NULL, indicating the node has to be created.
  245. * If the node already exists, then the resource definition and the resource
  246. * objects will be replaced with the ones provided.
  247. * Node = NULL, resource_defn = valid, name = valid:
  248. * Create a new resource for the first time and create a node for it.
  249. * Node = valid, resource_defn = valid, name = valid:
  250. * Link a new node to an existing resource.
  251. */
  252. static struct npa_resource *create_resource(struct npa_node_definition *node,
  253. struct npa_resource_definition *resource_defn,
  254. const char *name)
  255. {
  256. struct npa_alias_list *new_alias = NULL;
  257. struct npa_resource *new_resource = NULL;
  258. struct npa_resource *resource = NULL;
  259. struct npa_node_definition *old_node = NULL;
  260. struct npa_node_definition *new_node = NULL;
  261. struct npa_resource_definition *old_defn = NULL;
  262. struct npa_resource_definition *new_defn = NULL;
  263. if (!node) {
  264. new_node = kzalloc(sizeof(struct npa_node_definition),
  265. GFP_KERNEL);
  266. new_defn = kzalloc(sizeof(struct npa_resource_definition),
  267. GFP_KERNEL);
  268. new_defn->name = name;
  269. new_node->resources = new_defn;
  270. new_node->resource_count = 1;
  271. new_node->dependencies = NULL;
  272. new_node->dependency_count = 0;
  273. } else {
  274. new_node = node;
  275. new_defn = resource_defn;
  276. }
  277. write_lock(&list_lock);
  278. resource = __get_resource(name);
  279. if (resource && !node)
  280. goto done;
  281. if (!resource) {
  282. new_resource = kzalloc(sizeof(struct npa_resource), GFP_ATOMIC);
  283. new_alias = kzalloc(sizeof(struct npa_alias_list), GFP_ATOMIC);
  284. new_alias->alias = name;
  285. new_alias->resource = new_resource;
  286. INIT_LIST_HEAD(&new_alias->list);
  287. new_resource->node = new_node;
  288. new_resource->definition = new_defn;
  289. INIT_LIST_HEAD(&new_resource->list);
  290. INIT_LIST_HEAD(&new_resource->clients);
  291. INIT_LIST_HEAD(&new_resource->events);
  292. INIT_LIST_HEAD(&new_resource->watermarks);
  293. INIT_WORK(&new_resource->work, send_update_events);
  294. list_add(&new_alias->list, &alias_list);
  295. list_add(&new_resource->list, &waiting_list);
  296. resource = new_resource;
  297. } else {
  298. /* Resource exists */
  299. old_node = resource->node;
  300. old_defn = resource->definition;
  301. /* Replace the alias name pointer to use new defn. */
  302. if (old_defn) {
  303. struct npa_alias_list *a = NULL;
  304. list_for_each_entry(a, &alias_list, list) {
  305. if (a->alias == old_defn->name)
  306. a->alias = new_defn->name;
  307. }
  308. }
  309. /* Replace the node and resource defn. */
  310. resource->node = new_node;
  311. resource->definition = new_defn;
  312. }
  313. done:
  314. write_unlock(&list_lock);
  315. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  316. "NPA: Resource [%s] definition created\n",
  317. resource->definition->name);
  318. if (resource != new_resource) {
  319. kfree(old_defn);
  320. kfree(old_node);
  321. if (!node) {
  322. kfree(new_node);
  323. kfree(new_defn);
  324. }
  325. kfree(new_resource);
  326. kfree(new_alias);
  327. }
  328. return resource;
  329. }
  330. /* Register callback function for a resource creation event
  331. * (NPA_EVENT_RESERVED1). The event object malloc'd in this function is
  332. * released is to be released in the handler. NPA_EVENT_RESERVED1 events
  333. * are use and throw events and should be removed from the list once notified.
  334. */
  335. static int register_resource_event(struct npa_resource *resource,
  336. npa_cb_fn callback, void *data)
  337. {
  338. struct npa_event *event = NULL;
  339. if (!callback)
  340. return 0; /* Nothing to wait for */
  341. event = kzalloc(sizeof(struct npa_event), GFP_KERNEL);
  342. INIT_LIST_HEAD(&event->list);
  343. INIT_WORK(&event->work, send_single_event);
  344. event->type = NPA_EVENT_RESERVED1;
  345. event->resource = resource;
  346. /* Helpful identification string to distinguish user callbacks
  347. * from NPA internal resource completion events.
  348. */
  349. if (callback == resource_creation_handler)
  350. event->handler_name = NPA_STR_NPA_INTERNAL;
  351. else
  352. event->handler_name = NPA_STR_USER_CALLBACK;
  353. event->callback = callback;
  354. event->user_data = data;
  355. RESOURCE_LOCK(resource);
  356. list_add(&event->list, &resource->events);
  357. RESOURCE_UNLOCK(resource);
  358. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  359. "NPA: Registered for NPA_EVENT_RESERVED1 from resource [%s]\n",
  360. resource->definition->name);
  361. return 0;
  362. }
  363. /* Sends notification to this particular event object. This is mostly used
  364. * when the event is added to the resource.
  365. */
  366. static void send_single_event(struct work_struct *work)
  367. {
  368. struct npa_event *event = container_of(work, struct npa_event, work);
  369. struct npa_resource *resource = event->resource;
  370. struct npa_event_data event_data;
  371. /* Read the state when it is not being modified. */
  372. RESOURCE_LOCK(resource);
  373. event_data.resource_name = resource->definition->name;
  374. event_data.state = resource->active_state;
  375. event_data.headroom = resource->active_headroom;
  376. RESOURCE_UNLOCK(resource);
  377. npa_log(NPA_LOG_MASK_EVENT, resource,
  378. "NPA: Sending single event [%s] for resource [%s]\n",
  379. event->handler_name, resource->definition->name);
  380. event->callback(event->user_data, event->type, &event_data, 0);
  381. }
  382. /* Executes callbacks on all event objects. Callbacks are called in the
  383. * sequence of the event objects. This function does not entertain any
  384. * priority. If a callback blocks, it will affect all others that are
  385. * pending in the event list, as well as blocking the NPA work queue.
  386. */
  387. static void send_update_events(struct work_struct *work)
  388. {
  389. int expired = 0;
  390. struct npa_event *event = NULL;
  391. struct npa_event *temp = NULL;
  392. struct npa_resource *resource =
  393. container_of(work, struct npa_resource, work);
  394. struct npa_event_data event_data;
  395. npa_log(NPA_LOG_MASK_EVENT, resource,
  396. "NPA: Resource [%s] sending change events\n",
  397. resource->definition->name);
  398. /* Read the state when it is not being modified. */
  399. RESOURCE_LOCK(resource);
  400. event_data.resource_name = resource->definition->name;
  401. event_data.state = resource->active_state;
  402. event_data.headroom = resource->active_headroom;
  403. RESOURCE_UNLOCK(resource);
  404. list_for_each_entry_safe(event, temp, &resource->events, list) {
  405. expired = 0;
  406. switch (event->type) {
  407. case NPA_EVENT_RESERVED1:
  408. /* Destroy after execution. */
  409. list_del(&event->list);
  410. expired = 1;
  411. break;
  412. case NPA_EVENT_CHANGE:
  413. break;
  414. default:
  415. BUG();
  416. break;
  417. }
  418. npa_log(NPA_LOG_MASK_EVENT, resource,
  419. "NPA: Resource [%s] sending event [%d] to [%s] "
  420. "with state [%u] headroom [%d] \n",
  421. resource->definition->name, event->type,
  422. event->handler_name, event_data.state,
  423. event_data.headroom);
  424. event->callback(event->user_data, event->type, &event_data, 0);
  425. if (expired)
  426. kfree(event);
  427. }
  428. npa_log(NPA_LOG_MASK_EVENT, resource,
  429. "NPA: Resource [%s] sending watermark events\n",
  430. resource->definition->name);
  431. /* Send the watermark events */
  432. list_for_each_entry_safe(event, temp, &resource->watermarks, list) {
  433. if (event_data.state <= event->lo_watermark) {
  434. npa_log(NPA_LOG_MASK_EVENT, resource,
  435. "NPA: Resource [%s] sending "
  436. "low watermark event to [%s] "
  437. "with state [%u] headroom [%d]\n",
  438. resource->definition->name,
  439. event->handler_name,
  440. event_data.state,
  441. event_data.headroom);
  442. event->callback(event->user_data,
  443. NPA_EVENT_LO_WATERMARK,
  444. &event_data, 0);
  445. }
  446. if (event_data.state >= event->hi_watermark) {
  447. npa_log(NPA_LOG_MASK_EVENT, resource,
  448. "NPA: Resource [%s] sending "
  449. "high watermark event to [%s] "
  450. "with state [%u] headroom [%d]\n",
  451. resource->definition->name,
  452. event->handler_name,
  453. event_data.state,
  454. event_data.headroom);
  455. event->callback(event->user_data,
  456. NPA_EVENT_HI_WATERMARK,
  457. &event_data, 0);
  458. }
  459. }
  460. }
  461. /* Schedules a work to notify all those registered for events of the change
  462. * in resource state.
  463. */
  464. static void publish_resource_state(struct npa_resource *resource)
  465. {
  466. npa_log(NPA_LOG_MASK_EVENT, resource,
  467. "NPA: Queueing work for resource [%s]\n",
  468. resource->definition->name);
  469. queue_work(npa_wq, &resource->work);
  470. }
  471. /* Activate this resource and all other resources that are part of this node.
  472. * Resources when created by default are put in waiting lists.
  473. * This function is to be called, when all the dependencies of this
  474. * resources are available and the resource is ready to be used.
  475. */
  476. static int activate_node(struct npa_resource *resource)
  477. {
  478. struct npa_resource_definition *def = NULL;
  479. struct npa_node_dependency *node_dep = NULL;
  480. struct npa_client dummy = {
  481. .type = NPA_CLIENT_REQUIRED,
  482. .name = NPA_STR_NPA_INTERNAL,
  483. .resource_name = resource->definition->name,
  484. };
  485. unsigned int count = 0;
  486. unsigned int node_level = 0;
  487. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  488. "NPA: Resource [%s] being activated\n",
  489. resource->definition->name);
  490. /* Create clients for all the dependencies, so that the driver
  491. * function can send the requests to these resources as well.
  492. */
  493. RESOURCE_LOCK(resource);
  494. node_dep = resource->node->dependencies;
  495. count = resource->node->dependency_count;
  496. while (count) {
  497. struct npa_client *client =
  498. npa_create_sync_client(node_dep->name,
  499. resource->node->name,
  500. node_dep->client_type);
  501. BUG_ON((client == NULL) || IS_ERR(client));
  502. node_dep->handle = client;
  503. if (client->resource->level > node_level)
  504. node_level = client->resource->level;
  505. count--;
  506. node_dep++;
  507. }
  508. def = resource->node->resources;
  509. count = resource->node->resource_count;
  510. while (count) {
  511. write_lock(&list_lock);
  512. list_del(&def->resource->list); /* Remove from waiting list */
  513. list_add(&def->resource->list, &active_list);
  514. write_unlock(&list_lock);
  515. def->resource->active_state =
  516. def->resource->node->driver_fn(def->resource, &dummy,
  517. def->resource->requested_state);
  518. def->resource->active_headroom = def->resource->active_max -
  519. def->resource->active_state;
  520. def->resource->level = node_level + 1;
  521. count--;
  522. def++;
  523. }
  524. RESOURCE_UNLOCK(resource);
  525. /* Schedule a work to signal all dependencies that may depend
  526. * on this resource.
  527. */
  528. def = resource->node->resources;
  529. count = resource->node->resource_count;
  530. while (count) {
  531. publish_resource_state(def->resource);
  532. def++;
  533. count--;
  534. }
  535. return 0;
  536. }
  537. static void request_state(struct npa_resource *resource,
  538. struct npa_client *client, unsigned int state)
  539. {
  540. unsigned int new_state;
  541. npa_log(NPA_LOG_MASK_CLIENT, resource,
  542. "NPA: Resource [%s] client [%s] requested state [%u]\n",
  543. resource->definition->name, client->name, state);
  544. RESOURCE_LOCK(resource);
  545. PENDING_STATE(client) = state;
  546. new_state = resource->active_plugin->update_fn(resource, client);
  547. ACTIVE_STATE(client) = PENDING_STATE(client);
  548. resource->requested_state = new_state;
  549. if (new_state > resource->active_max)
  550. new_state = resource->active_max;
  551. if ((resource->definition->attributes &
  552. NPA_RESOURCE_REPORT_ALL_REQS) ||
  553. new_state != resource->active_state) {
  554. resource->active_state =
  555. resource->node->driver_fn(resource, client,
  556. new_state);
  557. resource->active_headroom = resource->active_max -
  558. resource->active_state;
  559. }
  560. RESOURCE_UNLOCK(resource);
  561. npa_log(NPA_LOG_MASK_CLIENT, resource,
  562. "NPA: Resource [%s] state set to [%u]\n",
  563. resource->definition->name, resource->active_state);
  564. publish_resource_state(resource);
  565. }
  566. /* Return if any dependency of this resource is still not active.
  567. * Returns NULL if there are no pending dependencies.
  568. */
  569. static struct npa_node_dependency *get_first_pending_dependency(
  570. struct npa_resource *resource)
  571. {
  572. struct npa_node_dependency *dep = NULL;
  573. unsigned int count = 0;
  574. dep = resource->node->dependencies;
  575. count = resource->node->dependency_count;
  576. while (count) {
  577. if (!active_resource(dep->name))
  578. return dep;
  579. count--;
  580. dep++;
  581. }
  582. return NULL;
  583. }
  584. /* Callback function for NPA_EVENT_RESERVED1. This function registers
  585. * itself with the event queue for the first pending dependency of the
  586. * resource. If there are no dependency, then this activates the resource
  587. * as well.
  588. */
  589. static void resource_creation_handler(void *data, unsigned int type,
  590. void *event_data, unsigned int value)
  591. {
  592. struct npa_resource *resource = (struct npa_resource *)data;
  593. struct npa_node_dependency *dep = NULL;
  594. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  595. "NPA: Resource [%s] creation handler called\n",
  596. resource->definition->name);
  597. dep = get_first_pending_dependency(resource);
  598. if (dep) {
  599. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  600. "NPA: Resource [%s] has dependency on resource [%s]\n",
  601. resource->definition->name, dep->name);
  602. npa_resource_available(dep->name,
  603. resource_creation_handler, resource);
  604. return;
  605. }
  606. /* All dependencies are complete. Finish the resource completion. */
  607. activate_node(resource);
  608. }
  609. static void resource_destruction_handler(void *data, unsigned int value,
  610. void *event_data, unsigned int type)
  611. {
  612. struct npa_resource *resource = data;
  613. BUG_ON(!list_empty(&resource->clients));
  614. if (!list_empty(&resource->events)) {
  615. struct npa_event *event = NULL;
  616. struct npa_event *temp = NULL;
  617. list_for_each_entry_safe(event, temp, &resource->events, list) {
  618. list_del(&event->list);
  619. npa_log(NPA_LOG_MASK_EVENT, resource,
  620. "NPA: Resource [%s] sending "
  621. "event [%d] to [%s]\n",
  622. resource->definition->name,
  623. event->type, event->handler_name);
  624. event->callback(event->user_data, value, NULL, 0);
  625. kfree(event);
  626. }
  627. }
  628. BUG_ON(!list_empty(&resource->watermarks));
  629. kfree(resource->definition);
  630. kfree(resource->node);
  631. kfree(resource);
  632. }
  633. /* Defines the node and individual resources.
  634. * All resources need to be defined by an external entity before the resource
  635. * can be used. This function checks for any pending dependency. This function
  636. * adds the callback to its event queue and when the resource is completely
  637. * defined, the callback is invoked.
  638. */
  639. int npa_define_node(struct npa_node_definition *node,
  640. unsigned int initial_state[],
  641. npa_cb_fn callback, void *user_data)
  642. {
  643. struct npa_resource *resource = NULL;
  644. struct npa_resource_definition *res_def = NULL;
  645. struct npa_node_dependency *node_dep = NULL;
  646. struct mutex *common_lock = NULL;
  647. unsigned int count = 0;
  648. int ret = 0;
  649. int idx = 0;
  650. if (!node || !node->name[0] || !node->resources || !node->driver_fn)
  651. return -EINVAL;
  652. npa_log(NPA_LOG_MASK_RESOURCE, NULL,
  653. "NPA: Defining node: [%s]\n", node->name);
  654. common_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
  655. mutex_init(common_lock);
  656. /* For each resource definition in this node definition, see if a
  657. * npa_resource object already exists, if not create and add to the
  658. * waiting list. We then check for dependencies and wait on those
  659. * using the first resource object that we have. Once the dependencies
  660. * are satisfied for this resource, we go ahead and activate all
  661. * the resources of this node.
  662. */
  663. res_def = node->resources;
  664. count = node->resource_count;
  665. while (count) {
  666. BUG_ON(!res_def->plugin);
  667. resource = create_resource(node, res_def, res_def->name);
  668. BUG_ON(__is_active_resource(resource));
  669. resource->definition = res_def;
  670. resource->node = node;
  671. resource->requested_state = initial_state[idx++];
  672. resource->active_max = res_def->max;
  673. resource->active_plugin = res_def->plugin;
  674. resource->resource_lock = common_lock;
  675. res_def->resource = resource;
  676. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  677. "NPA: Defining resource: [%s]\n", res_def->name);
  678. count--;
  679. res_def++;
  680. }
  681. /* Get the first resource in the node definition */
  682. resource = node->resources[0].resource;
  683. /* Save the callback function to be called if the resource is ready.*/
  684. ret = register_resource_event(resource, callback, user_data);
  685. if (ret)
  686. return ret;
  687. node_dep = get_first_pending_dependency(resource);
  688. if (node_dep) {
  689. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  690. "NPA: Resource [%s] has dependency on resource [%s]\n",
  691. resource->definition->name, node_dep->name);
  692. return npa_resource_available(node_dep->name,
  693. resource_creation_handler,
  694. (void *)resource);
  695. }
  696. /* Only executed when there are no pending dependencies of this node.*/
  697. activate_node(resource);
  698. return ret;
  699. }
  700. EXPORT_SYMBOL(npa_define_node);
  701. /* Checks if the resource is available in the NPA active or waiting lists.
  702. * If not, then creates a dummy resource and adds it to the waiting list.
  703. * When the resource is available, the callback function is executed when
  704. * the events are fired.
  705. */
  706. int npa_resource_available(const char *resource_name,
  707. npa_cb_fn callback, void *user_data)
  708. {
  709. struct npa_resource *resource = NULL;
  710. if (!resource_name || !resource_name[0] || !callback)
  711. return -EINVAL;
  712. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  713. "NPA: Checking if resource [%s] is available\n", resource_name);
  714. resource = create_resource(NULL, NULL, resource_name);
  715. read_lock(&list_lock);
  716. if (!__is_active_resource(resource)) {
  717. read_unlock(&list_lock);
  718. /* Register for NPA_EVENT_RESERVED1 event callback and exit */
  719. return register_resource_event(resource, callback, user_data);
  720. }
  721. read_unlock(&list_lock);
  722. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  723. "NPA: Resource [%s] is available\n", resource_name);
  724. /* Resource is active. Call in the current context. */
  725. callback(user_data, resource->active_state, NULL, 0);
  726. return 0;
  727. }
  728. EXPORT_SYMBOL(npa_resource_available);
  729. /* Define an alias name for a resource. */
  730. int npa_alias_resource(const char *resource_name, const char *alias_name,
  731. npa_cb_fn callback, void *user_data)
  732. {
  733. struct npa_resource *parent = NULL;
  734. struct npa_resource *resource = NULL;
  735. struct npa_alias_list *ralias = NULL;
  736. if (!resource_name || !resource_name[0] ||
  737. !alias_name || !alias_name[0] || !callback)
  738. return -EINVAL;
  739. npa_log(NPA_LOG_MASK_RESOURCE, NULL,
  740. "NPA: Creating alias [%s] for resource [%s]\n",
  741. alias_name, resource_name);
  742. ralias = kzalloc(sizeof(struct npa_alias_list), GFP_KERNEL);
  743. parent = create_resource(NULL, NULL, resource_name);
  744. write_lock(&list_lock);
  745. resource = __get_resource(alias_name);
  746. if (resource) {
  747. struct npa_alias_list *alias = NULL;
  748. list_for_each_entry(alias, &alias_list, list) {
  749. if (alias->resource == resource)
  750. alias->resource = parent;
  751. }
  752. list_del(&resource->list);
  753. } else {
  754. INIT_LIST_HEAD(&ralias->list);
  755. ralias->alias = alias_name;
  756. ralias->resource = parent;
  757. list_add(&ralias->list, &alias_list);
  758. }
  759. write_unlock(&list_lock);
  760. read_lock(&list_lock);
  761. if (__is_active_resource(parent)) {
  762. read_unlock(&list_lock);
  763. if (resource)
  764. resource_destruction_handler(resource,
  765. parent->active_state, NULL, 0);
  766. callback(user_data, 0, NULL, 0);
  767. } else {
  768. read_unlock(&list_lock);
  769. register_resource_event(parent, callback, user_data);
  770. if (resource)
  771. register_resource_event(parent,
  772. resource_destruction_handler, resource);
  773. }
  774. #ifdef CONFIG_MSM_NPA_LOG
  775. /* If we were looking to log an alias, then re-acquire the resource* */
  776. npa_log_resource = __get_resource(npa_log_resource_name);
  777. #endif
  778. npa_log(NPA_LOG_MASK_RESOURCE, parent,
  779. "NPA: Alias [%s] created for resource [%s]\n",
  780. alias_name, parent->definition->name);
  781. return 0;
  782. }
  783. EXPORT_SYMBOL(npa_alias_resource);
  784. /* Update the resource state with this state. The driver function is expected
  785. * to update the underlying h/w state or whatever this resource represents.
  786. * This function sends update events to the listeners.
  787. */
  788. int npa_assign_resource_state(struct npa_resource *resource,
  789. unsigned int state)
  790. {
  791. npa_log(NPA_LOG_MASK_RESOURCE, resource,
  792. "NPA: Resource [%s] is assigned state [%u]\n",
  793. resource->definition->name, state);
  794. resource->active_state = state;
  795. resource->active_headroom = resource->active_max - state;
  796. publish_resource_state(resource);
  797. return 0;
  798. }
  799. EXPORT_SYMBOL(npa_assign_resource_state);
  800. /* Create a sync client for this resource.
  801. * Returns an handle to the NPA client object if the resource is active,
  802. * error condition otherwise.
  803. */
  804. struct npa_client *npa_create_sync_client(const char *resource_name,
  805. const char *client_name, enum npa_client_type type)
  806. {
  807. struct npa_client *client = NULL;
  808. struct npa_resource *resource = NULL;
  809. int flag = 0;
  810. if (!resource_name || !resource_name[0] ||
  811. !client_name || !client_name[0])
  812. return ERR_PTR(-EINVAL);
  813. resource = active_resource(resource_name);
  814. if (!resource) {
  815. /* Clients for pending resources are not allowed. */
  816. npa_log(NPA_LOG_MASK_CLIENT, resource,
  817. "NPA: Resource [%s] requested by "
  818. "client [%s] not active\n",
  819. resource_name, client_name);
  820. return ERR_PTR(-ENODEV);
  821. }
  822. RESOURCE_LOCK(resource);
  823. if (!(type & resource->active_plugin->supported_clients))
  824. flag = -1;
  825. if ((resource->definition->attributes &
  826. NPA_RESOURCE_SINGLE_CLIENT) &&
  827. !list_empty(&resource->clients))
  828. flag = -2;
  829. RESOURCE_UNLOCK(resource);
  830. if (flag == -1) {
  831. npa_log(NPA_LOG_MASK_CLIENT, resource,
  832. "NPA: Client [%s, %d] is not "
  833. "supported by resource [%s]\n",
  834. client_name, type, resource_name);
  835. return ERR_PTR(-EINVAL);
  836. }
  837. if (flag == -2) {
  838. npa_log(NPA_LOG_MASK_CLIENT, resource,
  839. "NPA: Resource [%s] supports only a single"
  840. "client. Client [%s] create failed\n",
  841. resource_name, client_name);
  842. return ERR_PTR(-EBUSY);
  843. }
  844. npa_log(NPA_LOG_MASK_CLIENT, resource,
  845. "NPA: Creating sync client [%s] for "
  846. "resource [%s]\n", client_name, resource_name);
  847. client = kzalloc(sizeof(struct npa_client), GFP_KERNEL);
  848. INIT_LIST_HEAD(&client->list);
  849. client->name = client_name;
  850. client->resource_name = resource_name;
  851. client->resource = resource;
  852. client->type = type;
  853. RESOURCE_LOCK(resource);
  854. list_add(&client->list, &resource->clients);
  855. if (resource->active_plugin->create_client_fn)
  856. resource->active_plugin->create_client_fn(client);
  857. RESOURCE_UNLOCK(resource);
  858. npa_log(NPA_LOG_MASK_CLIENT, resource,
  859. "NPA: Client [%s, %d] for resource [%s] created\n",
  860. client_name, type, resource_name);
  861. return client;
  862. }
  863. EXPORT_SYMBOL(npa_create_sync_client);
  864. /* Removes a client from a resource. */
  865. void npa_destroy_client(struct npa_client *client)
  866. {
  867. struct npa_resource *resource = NULL;
  868. if (client) {
  869. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  870. "NPA: Resource [%s] client [%s, %d] destroyed\n",
  871. client->resource->definition->name,
  872. client->name, client->type);
  873. resource = client->resource;
  874. RESOURCE_LOCK(resource);
  875. if (resource->active_plugin->destroy_client_fn)
  876. resource->active_plugin->destroy_client_fn(client);
  877. list_del(&client->list);
  878. RESOURCE_UNLOCK(resource);
  879. kfree(client);
  880. }
  881. }
  882. EXPORT_SYMBOL(npa_destroy_client);
  883. /* Issues a required workflow request call to the client. If the update function
  884. * returns a state different from the current resource state, then the resource
  885. * driver function is called in the same context to update the resource and the
  886. * update events will be scheduled to fire.
  887. */
  888. int npa_issue_required_request(struct npa_client *client, unsigned int state)
  889. {
  890. if (client->type != NPA_CLIENT_REQUIRED)
  891. return -EINVAL;
  892. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  893. "NPA: Resource [%s] received request from client [%s, %u]\n",
  894. client->resource->definition->name,
  895. client->name, state);
  896. request_state(client->resource, client, state);
  897. return 0;
  898. }
  899. EXPORT_SYMBOL(npa_issue_required_request);
  900. int npa_modify_required_request(struct npa_client *client, int delta)
  901. {
  902. if (client->type != NPA_CLIENT_REQUIRED)
  903. return -EINVAL;
  904. /* Check if the active state of the client is non-zero. */
  905. if (!ACTIVE_STATE(client))
  906. return -EINVAL;
  907. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  908. "NPA: Resource [%s] modify request by client [%s, %d]\n",
  909. client->resource->definition->name, client->name, delta);
  910. request_state(client->resource, client, ACTIVE_STATE(client) + delta);
  911. return 0;
  912. }
  913. EXPORT_SYMBOL(npa_modify_required_request);
  914. int npa_issue_impulse_request(struct npa_client *client)
  915. {
  916. if (client->type != NPA_CLIENT_IMPULSE)
  917. return -EINVAL;
  918. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  919. "NPA: Resource [%s] impulse request by client [%s]\n",
  920. client->resource->definition->name, client->name);
  921. request_state(client->resource, client,
  922. client->resource->definition->max);
  923. return 0;
  924. }
  925. EXPORT_SYMBOL(npa_issue_impulse_request);
  926. int npa_issue_isoc_request(struct npa_client *client, unsigned int duration,
  927. unsigned int level)
  928. {
  929. if (client->type != NPA_CLIENT_ISOCHRONOUS)
  930. return -EINVAL;
  931. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  932. "NPA: Resource [%s] isoc request by "
  933. "client [%s] with duration [%u], level [%u]\n",
  934. client->resource->definition->name,
  935. client->name, duration, level);
  936. /* TODO: Update work struct with time values */
  937. client->work[PENDING_REQUEST].state = level;
  938. request_state(client->resource, client, PENDING_STATE(client));
  939. return 0;
  940. }
  941. EXPORT_SYMBOL(npa_issue_isoc_request);
  942. int npa_issue_limit_max_request(struct npa_client *client, unsigned int max)
  943. {
  944. int val = max;
  945. struct npa_resource *resource = client->resource;
  946. struct npa_client *cl_itr = NULL;
  947. if (client->type != NPA_CLIENT_LIMIT_MAX)
  948. return -EINVAL;
  949. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  950. "NPA: Resource [%s] limit max [%u] request by client [%s] \n",
  951. client->resource->definition->name, max, client->name);
  952. RESOURCE_LOCK(resource);
  953. list_for_each_entry(cl_itr, &resource->clients, list) {
  954. if ((cl_itr->type & NPA_CLIENT_LIMIT_MAX))
  955. if (ACTIVE_STATE(cl_itr) &&
  956. (ACTIVE_STATE(cl_itr) < val))
  957. val = ACTIVE_STATE(cl_itr);
  958. }
  959. resource->active_max = val;
  960. RESOURCE_UNLOCK(resource);
  961. /* Issue the request to the update_fn and limit the current state if
  962. * needed and call the driver fn. Send events if resource state is
  963. * changed.
  964. */
  965. request_state(client->resource, client, max);
  966. return 0;
  967. }
  968. EXPORT_SYMBOL(npa_issue_limit_max_request);
  969. void npa_complete_request(struct npa_client *client)
  970. {
  971. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  972. "NPA: Client [%s] completed request\n", client->name);
  973. /* Complete this request. */
  974. request_state(client->resource, client, 0);
  975. }
  976. EXPORT_SYMBOL(npa_complete_request);
  977. void npa_cancel_request(struct npa_client *client)
  978. {
  979. npa_log(NPA_LOG_MASK_CLIENT, client->resource,
  980. "NPA: Client [%s] cancelled request\n", client->name);
  981. /* TODO: In future flush any history for this client that may have
  982. * been captured. And complete this request.
  983. */
  984. request_state(client->resource, client, 0);
  985. }
  986. EXPORT_SYMBOL(npa_cancel_request);
  987. unsigned int npa_get_state(struct npa_client *client)
  988. {
  989. return client->resource->active_state;
  990. }
  991. EXPORT_SYMBOL(npa_get_state);
  992. /* Create an event object and attach to the resource event list.
  993. * This function expects that the resource be active for the event to
  994. * be registered with the resource.
  995. */
  996. struct npa_event *npa_create_change_event(const char *resource_name,
  997. const char *handler_name, npa_cb_fn event_cb, void *user_data)
  998. {
  999. struct npa_event *event = NULL;
  1000. struct npa_resource *resource = NULL;
  1001. if (!resource_name || !resource_name[0] ||
  1002. !handler_name || !event_cb)
  1003. return ERR_PTR(-EINVAL);
  1004. resource = active_resource(resource_name);
  1005. if (!resource)
  1006. return ERR_PTR(-ENODEV);
  1007. event = kzalloc(sizeof(struct npa_event), GFP_KERNEL);
  1008. INIT_LIST_HEAD(&event->list);
  1009. INIT_WORK(&event->work, send_single_event);
  1010. event->type = NPA_EVENT_CHANGE;
  1011. event->handler_name = handler_name;
  1012. event->resource = resource;
  1013. event->callback = event_cb;
  1014. event->user_data = user_data;
  1015. RESOURCE_LOCK(resource);
  1016. list_add(&event->list, &resource->events);
  1017. RESOURCE_UNLOCK(resource);
  1018. npa_log(NPA_LOG_MASK_EVENT, resource,
  1019. "NPA: Resource [%s] adding change event for [%s]\n",
  1020. resource->definition->name, handler_name);
  1021. /* Callback with the current resource state only for this event */
  1022. queue_work(npa_wq, &event->work);
  1023. return event;
  1024. }
  1025. EXPORT_SYMBOL(npa_create_change_event);
  1026. struct npa_event *npa_create_watermark_event(const char *resource_name,
  1027. const char *handler_name, npa_cb_fn event_cb, void *user_data)
  1028. {
  1029. struct npa_event *event = NULL;
  1030. struct npa_resource *resource = NULL;
  1031. if (!resource_name || !resource_name[0] ||
  1032. !handler_name || !event_cb)
  1033. return ERR_PTR(-EINVAL);
  1034. resource = active_resource(resource_name);
  1035. if (!resource)
  1036. return ERR_PTR(-ENODEV);
  1037. event = kzalloc(sizeof(struct npa_event), GFP_KERNEL);
  1038. INIT_LIST_HEAD(&event->list);
  1039. INIT_WORK(&event->work, send_single_event);
  1040. event->type = NPA_EVENT_LO_WATERMARK;
  1041. event->handler_name = handler_name;
  1042. event->resource = resource;
  1043. event->callback = event_cb;
  1044. event->user_data = user_data;
  1045. RESOURCE_LOCK(resource);
  1046. list_add(&event->list, &resource->watermarks);
  1047. RESOURCE_UNLOCK(resource);
  1048. npa_log(NPA_LOG_MASK_EVENT, resource,
  1049. "NPA: Resource [%s] adding watermark events for [%s]\n",
  1050. resource->definition->name, handler_name);
  1051. return event;
  1052. }
  1053. EXPORT_SYMBOL(npa_create_watermark_event);
  1054. /* Removes an event from the event queue of this resource. */
  1055. void npa_destroy_event(struct npa_event *event)
  1056. {
  1057. /* TODO BUG: Possible race condition with send-events(), event
  1058. * list being modified outside.
  1059. */
  1060. RESOURCE_LOCK(event->resource);
  1061. list_del(&event->list);
  1062. RESOURCE_UNLOCK(event->resource);
  1063. npa_log(NPA_LOG_MASK_EVENT, event->resource,
  1064. "NPA: Resource [%s] event [%s] destroyed\n",
  1065. event->resource->definition->name, event->handler_name);
  1066. kfree(event);
  1067. }
  1068. EXPORT_SYMBOL(npa_destroy_event);
  1069. /* Set watermarks for this event. The events are fired only if the resource
  1070. * state lie outside the watermarks.
  1071. */
  1072. int npa_set_event_watermarks(struct npa_event *event,
  1073. int lo_watermark, int hi_watermark)
  1074. {
  1075. unsigned int state;
  1076. int publish_event = 0;
  1077. if (!event)
  1078. return -EINVAL;
  1079. RESOURCE_LOCK(event->resource);
  1080. state = event->resource->active_state;
  1081. event->lo_watermark = lo_watermark;
  1082. event->hi_watermark = hi_watermark;
  1083. if (state <= event->lo_watermark) {
  1084. event->type = NPA_EVENT_LO_WATERMARK;
  1085. publish_event = 1;
  1086. }
  1087. if (state >= event->hi_watermark) {
  1088. event->type = NPA_EVENT_HI_WATERMARK;
  1089. publish_event = 1;
  1090. }
  1091. RESOURCE_UNLOCK(event->resource);
  1092. npa_log(NPA_LOG_MASK_EVENT, event->resource,
  1093. "NPA: Resource [%s] event [%s] watermarks [%d, %d] set\n",
  1094. event->resource->definition->name, event->handler_name,
  1095. lo_watermark, hi_watermark);
  1096. if (publish_event)
  1097. queue_work(npa_wq, &event->work);
  1098. return 0;
  1099. }
  1100. EXPORT_SYMBOL(npa_set_event_watermarks);
  1101. /* Pre-defined NPA update functions.
  1102. * Currently we only consider "required" client requests.
  1103. */
  1104. static unsigned int binary_update(struct npa_resource *resource,
  1105. struct npa_client *client)
  1106. {
  1107. struct npa_client *cl_itr = NULL;
  1108. unsigned int val = PENDING_STATE(client);
  1109. __print_client_states(resource);
  1110. if (!(client->type & NPA_CLIENT_REQUIRED))
  1111. return resource->active_state;
  1112. if ((resource->active_state == ACTIVE_STATE(client)) &&
  1113. (ACTIVE_STATE(client) != val))
  1114. return val;
  1115. list_for_each_entry(cl_itr, &resource->clients, list) {
  1116. if ((cl_itr->type & NPA_CLIENT_REQUIRED) && (cl_itr != client))
  1117. val |= ACTIVE_STATE(cl_itr);
  1118. }
  1119. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1120. "NPA: Binary plugin: Calculated [%u] for resource [%s] "
  1121. "client [%s]\n",
  1122. val, resource->definition->name, client->name);
  1123. return val;
  1124. }
  1125. static unsigned int min_update(struct npa_resource *resource,
  1126. struct npa_client *client)
  1127. {
  1128. struct npa_client *cl_itr = NULL;
  1129. unsigned int val = PENDING_STATE(client);
  1130. __print_client_states(resource);
  1131. if (!(client->type & NPA_CLIENT_REQUIRED))
  1132. return resource->active_state;
  1133. if (val && (resource->active_state == ACTIVE_STATE(client)) &&
  1134. (val <= ACTIVE_STATE(client))) {
  1135. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1136. "NPA: Min plugin: Current request [%u] is min for "
  1137. "resource [%s]\n",
  1138. val, resource->definition->name);
  1139. return val;
  1140. }
  1141. list_for_each_entry(cl_itr, &resource->clients, list) {
  1142. if (!(cl_itr->type & NPA_CLIENT_REQUIRED))
  1143. continue;
  1144. if ((cl_itr != client) && ACTIVE_STATE(cl_itr)) {
  1145. if (!val)
  1146. val = ACTIVE_STATE(cl_itr);
  1147. if (ACTIVE_STATE(cl_itr) < val)
  1148. val = ACTIVE_STATE(cl_itr);
  1149. }
  1150. }
  1151. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1152. "NPA: Min plugin: Calculated [%u] for resource [%s] "
  1153. "client [%s]\n",
  1154. val, resource->definition->name, client->name);
  1155. return val;
  1156. }
  1157. static unsigned int max_update(struct npa_resource *resource,
  1158. struct npa_client *client)
  1159. {
  1160. struct npa_client *cl_itr = NULL;
  1161. unsigned int val = PENDING_STATE(client);
  1162. __print_client_states(resource);
  1163. if (!(client->type & NPA_CLIENT_REQUIRED))
  1164. return resource->active_state;
  1165. if ((val != 0) &&
  1166. (resource->active_state == ACTIVE_STATE(client)) &&
  1167. (val >= ACTIVE_STATE(client))) {
  1168. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1169. "NPA: Max plugin: Current request [%u] is max for "
  1170. "resource [%s]\n",
  1171. val, resource->definition->name);
  1172. return val;
  1173. }
  1174. list_for_each_entry(cl_itr, &resource->clients, list) {
  1175. if (!(cl_itr->type & NPA_CLIENT_REQUIRED))
  1176. continue;
  1177. if ((cl_itr != client) && ACTIVE_STATE(cl_itr)) {
  1178. if (!val)
  1179. val = ACTIVE_STATE(cl_itr);
  1180. if (ACTIVE_STATE(cl_itr) > val)
  1181. val = ACTIVE_STATE(cl_itr);
  1182. }
  1183. }
  1184. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1185. "NPA: Max plugin: Calculated [%u] for resource [%s] "
  1186. "client [%s]\n",
  1187. val, resource->definition->name, client->name);
  1188. return val;
  1189. }
  1190. static unsigned int sum_update(struct npa_resource *resource,
  1191. struct npa_client *client)
  1192. {
  1193. unsigned int val = resource->active_state;
  1194. __print_client_states(resource);
  1195. if (!(client->type & NPA_CLIENT_REQUIRED))
  1196. return resource->active_state;
  1197. val -= ACTIVE_STATE(client);
  1198. val += PENDING_STATE(client);
  1199. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1200. "NPA: Sum plugin: Calculated [%u] for resource [%s] "
  1201. "client [%s]\n",
  1202. val, resource->definition->name, client->name);
  1203. return val;
  1204. }
  1205. static unsigned int always_update(struct npa_resource *resource,
  1206. struct npa_client *client)
  1207. {
  1208. unsigned int val = 1;
  1209. __print_client_states(resource);
  1210. if (!(client->type & NPA_CLIENT_REQUIRED))
  1211. return resource->active_state;
  1212. npa_log(NPA_LOG_MASK_PLUGIN, resource,
  1213. "NPA: Always on plugin: Calculated [%u] for resource [%s] "
  1214. "client [%s]\n",
  1215. val, resource->definition->name, client->name);
  1216. return val;
  1217. }
  1218. const struct npa_resource_plugin_ops npa_binary_plugin = {
  1219. .update_fn = binary_update,
  1220. .supported_clients = NPA_CLIENT_REQUIRED,
  1221. .create_client_fn = NULL,
  1222. .destroy_client_fn = NULL,
  1223. };
  1224. EXPORT_SYMBOL(npa_binary_plugin);
  1225. const struct npa_resource_plugin_ops npa_min_plugin = {
  1226. .update_fn = min_update,
  1227. .supported_clients = NPA_CLIENT_REQUIRED,
  1228. .create_client_fn = NULL,
  1229. .destroy_client_fn = NULL,
  1230. };
  1231. EXPORT_SYMBOL(npa_min_plugin);
  1232. const struct npa_resource_plugin_ops npa_max_plugin = {
  1233. .update_fn = max_update,
  1234. .supported_clients = NPA_CLIENT_REQUIRED,
  1235. .create_client_fn = NULL,
  1236. .destroy_client_fn = NULL,
  1237. };
  1238. EXPORT_SYMBOL(npa_max_plugin);
  1239. const struct npa_resource_plugin_ops npa_sum_plugin = {
  1240. .update_fn = sum_update,
  1241. .supported_clients = NPA_CLIENT_REQUIRED,
  1242. .create_client_fn = NULL,
  1243. .destroy_client_fn = NULL,
  1244. };
  1245. EXPORT_SYMBOL(npa_sum_plugin);
  1246. const struct npa_resource_plugin_ops npa_always_on_plugin = {
  1247. .update_fn = always_update,
  1248. .supported_clients = NPA_CLIENT_REQUIRED,
  1249. .create_client_fn = NULL,
  1250. .destroy_client_fn = NULL,
  1251. };
  1252. EXPORT_SYMBOL(npa_always_on_plugin);
  1253. /* NPA Init function. */
  1254. static int npa_init(void)
  1255. {
  1256. npa_wq = create_workqueue("npa");
  1257. BUG_ON(!npa_wq);
  1258. pr_info("NPA: Init done.\n");
  1259. return 0;
  1260. }
  1261. #ifdef CONFIG_MSM_NPA_DEBUG
  1262. /* ** DEBUG use only **
  1263. * NPA reset function. Releases all resources and resource states.
  1264. * This function should be called only when there all the clients and events
  1265. * are destroyed. No request should be made during this call.
  1266. */
  1267. void npa_reset(void)
  1268. {
  1269. struct npa_alias_list *a = NULL;
  1270. struct npa_alias_list *b = NULL;
  1271. struct npa_alias_list *temp_a = NULL;
  1272. struct npa_event *e = NULL;
  1273. struct npa_event *temp_e = NULL;
  1274. struct npa_client *c = NULL;
  1275. struct npa_client *temp_c = NULL;
  1276. struct npa_resource *resource = NULL;
  1277. struct npa_resource_definition *def = NULL;
  1278. unsigned int count = 0;
  1279. write_lock(&list_lock);
  1280. list_for_each_entry_safe(a, temp_a, &alias_list, list) {
  1281. list_del(&a->list);
  1282. kfree(a);
  1283. if (!resource)
  1284. continue;
  1285. resource = a->resource;
  1286. list_for_each_entry_safe(e, temp_e, &resource->events, list) {
  1287. list_del(&e->list);
  1288. kfree(e);
  1289. }
  1290. list_for_each_entry_safe(e, temp_e, &resource->watermarks,
  1291. list){
  1292. list_del(&e->list);
  1293. kfree(e);
  1294. }
  1295. list_for_each_entry_safe(c, temp_c, &resource->clients, list) {
  1296. list_del(&c->list);
  1297. kfree(c);
  1298. }
  1299. if (!__is_active_resource(resource)) {
  1300. kfree(resource->definition);
  1301. kfree(resource->node);
  1302. }
  1303. list_for_each_entry(b, &alias_list, list) {
  1304. if (b->resource == resource)
  1305. b->resource = NULL;
  1306. }
  1307. resource->definition->resource = NULL;
  1308. kfree(resource->resource_lock);
  1309. def = resource->node->resources;
  1310. count = resource->node->resource_count;
  1311. while (count) {
  1312. if (def->resource)
  1313. def->resource->resource_lock = NULL;
  1314. count--;
  1315. def++;
  1316. }
  1317. kfree(resource);
  1318. }
  1319. write_unlock(&list_lock);
  1320. }
  1321. EXPORT_SYMBOL(npa_reset);
  1322. #endif
  1323. /* NPA needs to be made available before the resources. Should be way up in the
  1324. * initialization list of the kernel.
  1325. */
  1326. postcore_initcall(npa_init);