ipa_table.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. /*
  2. * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above
  10. * copyright notice, this list of conditions and the following
  11. * disclaimer in the documentation and/or other materials provided
  12. * with the distribution.
  13. * * Neither the name of The Linux Foundation nor the names of its
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  21. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  24. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  25. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  26. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  27. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include "ipa_table.h"
  30. #include "ipa_nat_utils.h"
  31. #include <errno.h>
  32. #define IPA_BASE_TABLE_PERCENTAGE .8
  33. #define IPA_EXPANSION_TABLE_PERCENTAGE .2
  34. #define IPA_BASE_TABLE_PCNT_4SRAM 1.00
  35. #define IPA_EXPANSION_TABLE_PCNT_4SRAM 0.43
  36. /*
  37. * The table number of entries is limited by Entry ID structure
  38. * above. The base table max entries is limited by index into table
  39. * bits number.
  40. *
  41. * The table max ents number is: (base table max ents / base table percentage)
  42. *
  43. * IPA_TABLE_MAX_ENTRIES = 2^(index into table) / IPA_BASE_TABLE_PERCENTAGE
  44. */
  45. static int InsertHead(
  46. ipa_table* table,
  47. void* rec_ptr, /* empty record in table */
  48. uint16_t rec_index, /* index of record above */
  49. void* user_data,
  50. struct ipa_ioc_nat_dma_cmd* cmd );
  51. static int InsertTail(
  52. ipa_table* table,
  53. void* rec_ptr, /* occupied record at index below */
  54. uint16_t* rec_index_ptr, /* pointer to index of record above */
  55. void* user_data,
  56. struct ipa_ioc_nat_dma_cmd* cmd );
  57. static uint16_t MakeEntryHdl(
  58. ipa_table* tbl,
  59. uint16_t tbl_entry );
  60. static int FindExpnTblFreeEntry(
  61. ipa_table* table,
  62. void** free_entry,
  63. uint16_t* entry_index );
  64. static int Get2PowerTightUpperBound(
  65. uint16_t num);
  66. static int GetEvenTightUpperBound(
  67. uint16_t num);
  68. void ipa_table_init(
  69. ipa_table* table,
  70. const char* table_name,
  71. enum ipa3_nat_mem_in nmi,
  72. int entry_size,
  73. void* meta,
  74. int meta_entry_size,
  75. ipa_table_entry_interface* entry_interface )
  76. {
  77. IPADBG("In\n");
  78. memset(table, 0, sizeof(ipa_table));
  79. strlcpy(table->name, table_name, IPA_RESOURCE_NAME_MAX);
  80. table->nmi = nmi;
  81. table->entry_size = entry_size;
  82. table->meta = meta;
  83. table->meta_entry_size = meta_entry_size;
  84. table->entry_interface = entry_interface;
  85. IPADBG("Table %s with entry size %d has been initialized\n",
  86. table->name, table->entry_size);
  87. IPADBG("Out\n");
  88. }
  89. int ipa_table_calculate_entries_num(
  90. ipa_table* table,
  91. uint16_t number_of_entries,
  92. enum ipa3_nat_mem_in nmi)
  93. {
  94. uint16_t table_entries, expn_table_entries;
  95. float btp, etp;
  96. int result = 0;
  97. IPADBG("In\n");
  98. if (number_of_entries > IPA_TABLE_MAX_ENTRIES)
  99. {
  100. IPAERR("Required number of %s entries %d exceeds the maximum %d\n",
  101. table->name, number_of_entries, IPA_TABLE_MAX_ENTRIES);
  102. result = -EINVAL;
  103. goto bail;
  104. }
  105. if ( nmi == IPA_NAT_MEM_IN_SRAM )
  106. {
  107. btp = IPA_BASE_TABLE_PCNT_4SRAM;
  108. etp = IPA_EXPANSION_TABLE_PCNT_4SRAM;
  109. }
  110. else
  111. {
  112. btp = IPA_BASE_TABLE_PERCENTAGE;
  113. etp = IPA_EXPANSION_TABLE_PERCENTAGE;
  114. }
  115. table_entries = Get2PowerTightUpperBound(number_of_entries * btp);
  116. expn_table_entries = GetEvenTightUpperBound(number_of_entries * etp);
  117. table->tot_tbl_ents = table_entries + expn_table_entries;
  118. if ( table->tot_tbl_ents > IPA_TABLE_MAX_ENTRIES )
  119. {
  120. IPAERR("Required number of %s entries %u "
  121. "(user provided %u) exceeds the maximum %u\n",
  122. table->name,
  123. table->tot_tbl_ents,
  124. number_of_entries,
  125. IPA_TABLE_MAX_ENTRIES);
  126. result = -EINVAL;
  127. goto bail;
  128. }
  129. table->table_entries = table_entries;
  130. table->expn_table_entries = expn_table_entries;
  131. IPADBG("Num of %s entries:%u expn entries:%u total entries:%u\n",
  132. table->name,
  133. table->table_entries,
  134. table->expn_table_entries,
  135. table->tot_tbl_ents);
  136. bail:
  137. IPADBG("Out\n");
  138. return result;
  139. }
  140. int ipa_table_calculate_size(ipa_table* table)
  141. {
  142. int size = table->entry_size * (table->table_entries + table->expn_table_entries);
  143. IPADBG("In\n");
  144. IPADBG("%s size: %d\n", table->name, size);
  145. IPADBG("Out\n");
  146. return size;
  147. }
  148. uint8_t* ipa_table_calculate_addresses(
  149. ipa_table* table,
  150. uint8_t* base_addr)
  151. {
  152. uint8_t* result = NULL;
  153. IPADBG("In\n");
  154. table->table_addr = base_addr;
  155. table->expn_table_addr =
  156. table->table_addr + table->entry_size * table->table_entries;
  157. IPADBG("Table %s addresses: table_addr %pK expn_table_addr %pK\n",
  158. table->name, table->table_addr, table->expn_table_addr);
  159. result = table->expn_table_addr + table->entry_size * table->expn_table_entries;
  160. IPADBG("Out\n");
  161. return result;
  162. }
  163. void ipa_table_reset(
  164. ipa_table* table)
  165. {
  166. uint32_t i,tot;
  167. IPADBG("In\n");
  168. IPADBG("memset %s table to 0, %pK\n", table->name, table->table_addr);
  169. tot = table->entry_size * table->table_entries;
  170. for (i = 0; i < tot; i++)
  171. table->table_addr[i] = '\0';
  172. IPADBG("memset %s expn table to 0, %pK\n", table->name, table->expn_table_addr);
  173. tot = table->entry_size * table->expn_table_entries;
  174. for (i = 0; i < tot; i++)
  175. table->expn_table_addr[i] = '\0';
  176. IPADBG("Out\n");
  177. }
  178. int ipa_table_add_entry(
  179. ipa_table* table,
  180. void* user_data,
  181. uint16_t* rec_index_ptr,
  182. uint32_t* rule_hdl,
  183. struct ipa_ioc_nat_dma_cmd* cmd )
  184. {
  185. void* rec_ptr;
  186. int ret = 0, occupied;
  187. IPADBG("In\n");
  188. rec_ptr = GOTO_REC(table, *rec_index_ptr);
  189. /*
  190. * Check whether there is any collision
  191. */
  192. occupied = table->entry_interface->entry_is_valid(rec_ptr);
  193. if ( ! occupied )
  194. {
  195. IPADBG("Collision free (in %s) ... found open slot\n", table->name);
  196. ret = InsertHead(table, rec_ptr, *rec_index_ptr, user_data, cmd);
  197. }
  198. else
  199. {
  200. IPADBG("Collision (in %s) ... will probe for open slot\n", table->name);
  201. ret = InsertTail(table, rec_ptr, rec_index_ptr, user_data, cmd);
  202. }
  203. if (ret)
  204. goto bail;
  205. IPADBG("New Entry Index %u in %s\n", *rec_index_ptr, table->name);
  206. if ( rule_hdl ) {
  207. *rule_hdl = MakeEntryHdl(table, *rec_index_ptr);
  208. IPADBG("rule_hdl value(%u)\n", *rule_hdl);
  209. }
  210. bail:
  211. IPADBG("Out\n");
  212. return ret;
  213. }
  214. void ipa_table_create_delete_command(
  215. ipa_table* table,
  216. struct ipa_ioc_nat_dma_cmd* cmd,
  217. ipa_table_iterator* iterator)
  218. {
  219. IPADBG("In\n");
  220. IPADBG("Delete rule at index(0x%04X) in %s\n",
  221. iterator->curr_index,
  222. table->name);
  223. if ( ! VALID_INDEX(iterator->prev_index) )
  224. {
  225. /*
  226. * The following two assigns (ie. the defaults), will cause
  227. * the enabled bit in the record to be set to 0.
  228. */
  229. uint16_t data = 0;
  230. dma_help_type ht = HELP_UPDATE_HEAD;
  231. if ( VALID_INDEX(iterator->next_index) )
  232. {
  233. /*
  234. * NOTE WELL HERE:
  235. *
  236. * This record is the first in a chain/list of
  237. * records. Delete means something different in this
  238. * context.
  239. *
  240. * The code below will cause the change of the protocol
  241. * field in the rule record to 0xFF. It does not set the
  242. * enable bit in the record to 0. This is done in special
  243. * cases when the record being deleted is the first in a
  244. * list of records.
  245. *
  246. * What does this mean? It means that the record is
  247. * functionally deleted, but not really deleted. Why?
  248. * Because the IPA will no longer use it because of the
  249. * bad protocol (ie. functionally deleted), but these
  250. * higher level APIs still see it as "enabled."
  251. *
  252. * This all means that deleted really means two things: 1)
  253. * Not enabled, and 2) Not a valid record. APIs that walk
  254. * the table...looking for enabled records (ie. the
  255. * enabled bit)....now have to be a bit smarter to see the
  256. * bad protocol as well.
  257. */
  258. data = table->entry_interface->
  259. entry_get_delete_head_dma_command_data(
  260. iterator->curr_entry, iterator->next_entry);
  261. ht = HELP_DELETE_HEAD;
  262. }
  263. ipa_table_add_dma_cmd(table,
  264. ht,
  265. iterator->curr_entry,
  266. iterator->curr_index,
  267. data,
  268. cmd);
  269. }
  270. else
  271. {
  272. ipa_table_add_dma_cmd(table,
  273. HELP_UPDATE_ENTRY,
  274. iterator->prev_entry,
  275. iterator->prev_index,
  276. iterator->next_index,
  277. cmd);
  278. }
  279. IPADBG("Out\n");
  280. }
  281. void ipa_table_delete_entry(
  282. ipa_table* table,
  283. ipa_table_iterator* iterator,
  284. uint8_t is_prev_empty)
  285. {
  286. IPADBG("In\n");
  287. if ( VALID_INDEX(iterator->next_index) )
  288. {
  289. /*
  290. * Update the next entry's prev_index field with current
  291. * entry's prev_index
  292. */
  293. table->entry_interface->entry_set_prev_index(
  294. iterator->next_entry,
  295. iterator->next_index,
  296. iterator->prev_index,
  297. table->meta,
  298. table->table_entries);
  299. }
  300. else if (is_prev_empty)
  301. {
  302. if (iterator->prev_entry == NULL)
  303. {
  304. IPAERR("failed to delete of an empty head %d while delete the next entry %d in %s",
  305. iterator->prev_index, iterator->curr_index, table->name);
  306. }
  307. else
  308. {
  309. /*
  310. * Delete an empty head rule after the whole tail was deleted
  311. */
  312. IPADBG("deleting the dead node %d for %s\n",
  313. iterator->prev_index, table->name);
  314. memset(iterator->prev_entry, 0, table->entry_size);
  315. --table->cur_tbl_cnt;
  316. }
  317. }
  318. ipa_table_erase_entry(table, iterator->curr_index);
  319. IPADBG("Out\n");
  320. }
  321. void ipa_table_erase_entry(
  322. ipa_table* table,
  323. uint16_t index)
  324. {
  325. void* entry = GOTO_REC(table, index);
  326. IPADBG("In\n");
  327. IPADBG("table(%p) index(%u)\n", table, index);
  328. memset(entry, 0, table->entry_size);
  329. if ( index < table->table_entries )
  330. {
  331. --table->cur_tbl_cnt;
  332. }
  333. else
  334. {
  335. --table->cur_expn_tbl_cnt;
  336. }
  337. IPADBG("Out\n");
  338. }
  339. /**
  340. * ipa_table_get_entry() - returns a table entry according to the received entry handle
  341. * @table: [in] the table
  342. * @entry_handle: [in] entry handle
  343. * @entry: [out] the retrieved entry
  344. * @entry_index: [out] absolute index of the retrieved entry
  345. *
  346. * Parse the entry handle to retrieve the entry and its index
  347. *
  348. * Returns: 0 on success, negative on failure
  349. */
  350. int ipa_table_get_entry(
  351. ipa_table* table,
  352. uint32_t entry_handle,
  353. void** entry,
  354. uint16_t* entry_index )
  355. {
  356. enum ipa3_nat_mem_in nmi;
  357. uint8_t is_expn_tbl;
  358. uint16_t rec_index;
  359. int ret = 0;
  360. IPADBG("In\n");
  361. IPADBG("table(%p) entry_handle(%u) entry(%p) entry_index(%p)\n",
  362. table, entry_handle, entry, entry_index);
  363. /*
  364. * Retrieve the memory and table type as well as the index
  365. */
  366. BREAK_RULE_HDL(table, entry_handle, nmi, is_expn_tbl, rec_index);
  367. if ( is_expn_tbl )
  368. {
  369. IPADBG("Retrieving entry from expansion table\n");
  370. }
  371. else
  372. {
  373. IPADBG("Retrieving entry from base (non-expansion) table\n");
  374. }
  375. if ( rec_index >= table->tot_tbl_ents )
  376. {
  377. IPAERR("The entry handle's record index (%u) exceeds table size (%u)\n",
  378. rec_index, table->tot_tbl_ents);
  379. ret = -EINVAL;
  380. goto bail;
  381. }
  382. *entry = GOTO_REC(table, rec_index);
  383. if ( entry_index )
  384. {
  385. *entry_index = rec_index;
  386. }
  387. bail:
  388. IPADBG("Out\n");
  389. return ret;
  390. }
  391. void* ipa_table_get_entry_by_index(
  392. ipa_table* table,
  393. uint16_t rec_index )
  394. {
  395. void* result = NULL;
  396. IPADBG("In\n");
  397. IPADBG("table(%p) rec_index(%u)\n",
  398. table,
  399. rec_index);
  400. if ( ! rec_index || rec_index >= table->tot_tbl_ents )
  401. {
  402. IPAERR("Invalid record index (%u): It's "
  403. "either zero or exceeds table size (%u)\n",
  404. rec_index, table->tot_tbl_ents);
  405. goto bail;
  406. }
  407. result = GOTO_REC(table, rec_index);
  408. bail:
  409. IPADBG("Out\n");
  410. return result;
  411. }
  412. void ipa_table_dma_cmd_helper_init(
  413. ipa_table_dma_cmd_helper* dma_cmd_helper,
  414. uint8_t table_indx,
  415. ipa_table_dma_type table_type,
  416. ipa_table_dma_type expn_table_type,
  417. uint32_t offset)
  418. {
  419. IPADBG("In\n");
  420. dma_cmd_helper->offset = offset;
  421. dma_cmd_helper->table_indx = table_indx;
  422. dma_cmd_helper->table_type = table_type;
  423. dma_cmd_helper->expn_table_type = expn_table_type;
  424. IPADBG("Out\n");
  425. }
  426. void ipa_table_dma_cmd_generate(
  427. ipa_table_dma_cmd_helper* dma_cmd_helper,
  428. uint8_t is_expn,
  429. uint32_t entry_offset,
  430. uint16_t data,
  431. struct ipa_ioc_nat_dma_cmd* cmd)
  432. {
  433. struct ipa_ioc_nat_dma_one* dma = &cmd->dma[cmd->entries];
  434. IPADBG("In\n");
  435. IPADBG("is_expn(0x%02X) entry_offset(0x%08X) data(0x%04X)\n",
  436. is_expn, entry_offset, data);
  437. dma->table_index = dma_cmd_helper->table_indx;
  438. /*
  439. * DMA parameter base_addr is the table type (see the IPA
  440. * architecture document)
  441. */
  442. dma->base_addr =
  443. (is_expn) ?
  444. dma_cmd_helper->expn_table_type :
  445. dma_cmd_helper->table_type;
  446. dma->offset = dma_cmd_helper->offset + entry_offset;
  447. dma->data = data;
  448. IPADBG("dma_entry[%u](table_index(0x%02X) "
  449. "base_addr(0x%02X) data(0x%04X) offset(0x%08X))\n",
  450. cmd->entries,
  451. dma->table_index,
  452. dma->base_addr,
  453. dma->data,
  454. dma->offset);
  455. cmd->entries++;
  456. IPADBG("Out\n");
  457. }
  458. int ipa_table_iterator_init(
  459. ipa_table_iterator* iterator,
  460. ipa_table* table,
  461. void* curr_entry,
  462. uint16_t curr_index)
  463. {
  464. int occupied;
  465. int ret = 0;
  466. IPADBG("In\n");
  467. memset(iterator, 0, sizeof(ipa_table_iterator));
  468. occupied = table->entry_interface->entry_is_valid(curr_entry);
  469. if ( ! occupied )
  470. {
  471. IPAERR("Invalid (not enabled) rule %u in %s\n", curr_index, table->name);
  472. ret = -EINVAL;
  473. goto bail;
  474. }
  475. iterator->curr_entry = curr_entry;
  476. iterator->curr_index = curr_index;
  477. iterator->prev_index = table->entry_interface->entry_get_prev_index(
  478. curr_entry,
  479. curr_index,
  480. table->meta,
  481. table->table_entries);
  482. iterator->next_index = table->entry_interface->entry_get_next_index(
  483. curr_entry);
  484. if ( VALID_INDEX(iterator->prev_index) )
  485. {
  486. iterator->prev_entry = ipa_table_get_entry_by_index(
  487. table,
  488. iterator->prev_index);
  489. if ( iterator->prev_entry == NULL )
  490. {
  491. IPAERR("Failed to retrieve the entry at index 0x%04X for %s\n",
  492. iterator->prev_index, table->name);
  493. ret = -EPERM;
  494. goto bail;
  495. }
  496. }
  497. if ( VALID_INDEX(iterator->next_index) )
  498. {
  499. iterator->next_entry = ipa_table_get_entry_by_index(
  500. table,
  501. iterator->next_index);
  502. if ( iterator->next_entry == NULL )
  503. {
  504. IPAERR("Failed to retrieve the entry at index 0x%04X for %s\n",
  505. iterator->next_index, table->name);
  506. ret = -EPERM;
  507. goto bail;
  508. }
  509. }
  510. IPADBG("[index/entry] for "
  511. "prev:[0x%04X/%p] "
  512. "curr:[0x%04X/%p] "
  513. "next:[0x%04X/%p] "
  514. "\"%s\"\n",
  515. iterator->prev_index,
  516. iterator->prev_entry,
  517. iterator->curr_index,
  518. iterator->curr_entry,
  519. iterator->next_index,
  520. iterator->next_entry,
  521. table->name);
  522. bail:
  523. IPADBG("Out\n");
  524. return ret;
  525. }
  526. int ipa_table_iterator_next(
  527. ipa_table_iterator* iterator,
  528. ipa_table* table)
  529. {
  530. int ret = 0;
  531. IPADBG("In\n");
  532. iterator->prev_entry = iterator->curr_entry;
  533. iterator->prev_index = iterator->curr_index;
  534. iterator->curr_entry = iterator->next_entry;
  535. iterator->curr_index = iterator->next_index;
  536. iterator->next_index = table->entry_interface->entry_get_next_index(
  537. iterator->curr_entry);
  538. if ( ! VALID_INDEX(iterator->next_index) )
  539. {
  540. iterator->next_entry = NULL;
  541. }
  542. else
  543. {
  544. iterator->next_entry = ipa_table_get_entry_by_index(
  545. table, iterator->next_index);
  546. if (iterator->next_entry == NULL)
  547. {
  548. IPAERR("Failed to retrieve the entry at index %d for %s\n",
  549. iterator->next_index, table->name);
  550. ret = -EPERM;
  551. goto bail;
  552. }
  553. }
  554. IPADBG("Iterator moved to: prev_index=%d curr_index=%d next_index=%d\n",
  555. iterator->prev_index, iterator->curr_index, iterator->next_index);
  556. IPADBG(" prev_entry=%pK curr_entry=%pK next_entry=%pK\n",
  557. iterator->prev_entry, iterator->curr_entry, iterator->next_entry);
  558. bail:
  559. IPADBG("Out\n");
  560. return ret;
  561. }
  562. int ipa_table_iterator_end(
  563. ipa_table_iterator* iterator,
  564. ipa_table* table_ptr,
  565. uint16_t rec_index, /* a table slot relative to hash */
  566. void* rec_ptr ) /* occupant record at index above */
  567. {
  568. bool found_end = false;
  569. int ret;
  570. IPADBG("In\n");
  571. if ( ! iterator || ! table_ptr || ! rec_ptr )
  572. {
  573. IPAERR("Bad arg: iterator(%p) and/or table_ptr (%p) and/or rec_ptr(%p)\n",
  574. iterator, table_ptr, rec_ptr);
  575. ret = -1;
  576. goto bail;
  577. }
  578. memset(iterator, 0, sizeof(ipa_table_iterator));
  579. iterator->prev_index = rec_index;
  580. iterator->prev_entry = rec_ptr;
  581. while ( 1 )
  582. {
  583. uint16_t next_index =
  584. table_ptr->entry_interface->entry_get_next_index(iterator->prev_entry);
  585. if ( ! VALID_INDEX(next_index) )
  586. {
  587. found_end = true;
  588. break;
  589. }
  590. if ( next_index == iterator->prev_index )
  591. {
  592. IPAERR("next_index(%u) and prev_index(%u) shouldn't be equal in %s\n",
  593. next_index,
  594. iterator->prev_index,
  595. table_ptr->name);
  596. break;
  597. }
  598. iterator->prev_index = next_index;
  599. iterator->prev_entry = GOTO_REC(table_ptr, next_index);
  600. }
  601. if ( found_end )
  602. {
  603. IPADBG("Iterator found end of list record\n");
  604. ret = 0;
  605. }
  606. else
  607. {
  608. IPAERR("Iterator can't find end of list record\n");
  609. ret = -1;
  610. }
  611. bail:
  612. IPADBG("Out\n");
  613. return ret;
  614. }
  615. int ipa_table_iterator_is_head_with_tail(
  616. ipa_table_iterator* iterator)
  617. {
  618. int ret = 0;
  619. IPADBG("In\n");
  620. ret = VALID_INDEX(iterator->next_index) && ! VALID_INDEX(iterator->prev_index);
  621. IPADBG("Out\n");
  622. return ret;
  623. }
  624. static int InsertHead(
  625. ipa_table* table,
  626. void* rec_ptr, /* empty record in table */
  627. uint16_t rec_index, /* index of record above */
  628. void* user_data,
  629. struct ipa_ioc_nat_dma_cmd* cmd )
  630. {
  631. uint16_t enable_data = 0;
  632. int ret = 0;
  633. IPADBG("In\n");
  634. ret = table->entry_interface->entry_head_insert(
  635. rec_ptr,
  636. user_data,
  637. &enable_data);
  638. if (ret)
  639. {
  640. IPAERR("unable to insert a new entry to the head in %s\n", table->name);
  641. goto bail;
  642. }
  643. ipa_table_add_dma_cmd(
  644. table,
  645. HELP_UPDATE_HEAD,
  646. rec_ptr,
  647. rec_index,
  648. enable_data,
  649. cmd);
  650. ++table->cur_tbl_cnt;
  651. bail:
  652. IPADBG("Out\n");
  653. return ret;
  654. }
  655. static int InsertTail(
  656. ipa_table* table,
  657. void* rec_ptr, /* occupied record at index below */
  658. uint16_t* rec_index_ptr, /* pointer to index of record above */
  659. void* user_data,
  660. struct ipa_ioc_nat_dma_cmd* cmd )
  661. {
  662. bool is_index_tbl = (table->meta) ? true : false;
  663. ipa_table_iterator iterator;
  664. uint16_t enable_data = 0;
  665. int ret = 0;
  666. IPADBG("In\n");
  667. /*
  668. * The most important side effect of the following is to set the
  669. * iterator's prev_index and prev_entry...which will be the last
  670. * valid entry on the end of the list.
  671. */
  672. ret = ipa_table_iterator_end(&iterator, table, *rec_index_ptr, rec_ptr);
  673. if ( ret )
  674. {
  675. IPAERR("Failed to reach the end of list following rec_index(%u) in %s\n",
  676. *rec_index_ptr, table->name);
  677. goto bail;
  678. }
  679. /*
  680. * The most important side effect of the following is to set the
  681. * iterator's curr_index and curr_entry with the next available
  682. * expansion table open slot.
  683. */
  684. ret = FindExpnTblFreeEntry(table, &iterator.curr_entry, &iterator.curr_index);
  685. if ( ret )
  686. {
  687. IPAERR("FindExpnTblFreeEntry of %s failed\n", table->name);
  688. goto bail;
  689. }
  690. /*
  691. * Copy data into curr_entry (ie. open slot).
  692. */
  693. if ( is_index_tbl )
  694. {
  695. ret = table->entry_interface->entry_tail_insert(
  696. iterator.curr_entry,
  697. user_data);
  698. }
  699. else
  700. {
  701. /*
  702. * We need enable bit when not index table, hence...
  703. */
  704. ret = table->entry_interface->entry_head_insert(
  705. iterator.curr_entry,
  706. user_data,
  707. &enable_data);
  708. }
  709. if (ret)
  710. {
  711. IPAERR("Unable to insert a new entry to the tail in %s\n", table->name);
  712. goto bail;
  713. }
  714. /*
  715. * Update curr_entry's prev_index field with iterator.prev_index
  716. */
  717. table->entry_interface->entry_set_prev_index(
  718. iterator.curr_entry, /* set by FindExpnTblFreeEntry above */
  719. iterator.curr_index, /* set by FindExpnTblFreeEntry above */
  720. iterator.prev_index, /* set by ipa_table_iterator_end above */
  721. table->meta,
  722. table->table_entries);
  723. if ( ! is_index_tbl )
  724. {
  725. /*
  726. * Generate dma command to have the IPA update the
  727. * curr_entry's enable field when not the index table...
  728. */
  729. ipa_table_add_dma_cmd(
  730. table,
  731. HELP_UPDATE_HEAD,
  732. iterator.curr_entry,
  733. iterator.curr_index,
  734. enable_data,
  735. cmd);
  736. }
  737. /*
  738. * Generate a dma command to have the IPA update the prev_entry's
  739. * next_index with iterator.curr_index.
  740. */
  741. ipa_table_add_dma_cmd(
  742. table,
  743. HELP_UPDATE_ENTRY,
  744. iterator.prev_entry,
  745. iterator.prev_index,
  746. iterator.curr_index,
  747. cmd);
  748. ++table->cur_expn_tbl_cnt;
  749. *rec_index_ptr = iterator.curr_index;
  750. bail:
  751. IPADBG("Out\n");
  752. return ret;
  753. }
  754. /**
  755. * MakeEntryHdl() - makes an entry handle
  756. * @tbl_hdl: [in] tbl - the table
  757. * @tbl_entry: [in] tbl_entry - table entry
  758. *
  759. * Calculate the entry handle which will be returned to client
  760. *
  761. * Returns: >0 table entry handle
  762. */
  763. static uint16_t MakeEntryHdl(
  764. ipa_table* tbl,
  765. uint16_t tbl_entry )
  766. {
  767. uint16_t entry_hdl = 0;
  768. IPADBG("In\n");
  769. if (tbl_entry >= tbl->table_entries)
  770. {
  771. /*
  772. * Update the index into table
  773. */
  774. entry_hdl = tbl_entry - tbl->table_entries;
  775. entry_hdl = (entry_hdl << IPA_TABLE_TYPE_BITS);
  776. /*
  777. * Update the expansion table type bit
  778. */
  779. entry_hdl = (entry_hdl | IPA_TABLE_TYPE_MASK);
  780. }
  781. else
  782. {
  783. entry_hdl = tbl_entry;
  784. entry_hdl = (entry_hdl << IPA_TABLE_TYPE_BITS);
  785. }
  786. /*
  787. * Set memory type bit.
  788. */
  789. entry_hdl = entry_hdl | (tbl->nmi << IPA_TABLE_TYPE_MEM_SHIFT);
  790. IPADBG("In: tbl_entry(%u) Out: entry_hdl(%u)\n", tbl_entry, entry_hdl);
  791. IPADBG("Out\n");
  792. return entry_hdl;
  793. }
  794. static int mt_slot(
  795. ipa_table* table_ptr,
  796. uint32_t rule_hdl,
  797. void* record_ptr,
  798. uint16_t record_index,
  799. void* meta_record_ptr,
  800. uint16_t meta_record_index,
  801. void* arb_data_ptr )
  802. {
  803. IPADBG("%s: Empty expansion slot: (%u) in table of size: (%u)\n",
  804. table_ptr->name,
  805. record_index,
  806. table_ptr->tot_tbl_ents);
  807. return record_index;
  808. }
  809. /*
  810. * returns expn table entry absolute index
  811. */
  812. static int FindExpnTblFreeEntry(
  813. ipa_table* table,
  814. void** free_entry,
  815. uint16_t* entry_index )
  816. {
  817. int ret;
  818. IPADBG("In\n");
  819. if ( ! table || ! free_entry || ! entry_index )
  820. {
  821. IPAERR("Bad arg: table(%p) and/or "
  822. "free_entry(%p) and/or entry_index(%p)\n",
  823. table, free_entry, entry_index);
  824. ret = -1;
  825. goto bail;
  826. }
  827. *entry_index = 0;
  828. *free_entry = NULL;
  829. /*
  830. * The following will start walk at expansion slots
  831. * (ie. just after table->table_entries)...
  832. */
  833. ret = ipa_table_walk(table, table->table_entries, WHEN_SLOT_EMPTY, mt_slot, 0);
  834. if ( ret > 0 )
  835. {
  836. *entry_index = (uint16_t) ret;
  837. *free_entry = GOTO_REC(table, *entry_index);
  838. IPADBG("%s: entry_index val (%u) free_entry val (%p)\n",
  839. table->name,
  840. *entry_index,
  841. *free_entry);
  842. ret = 0;
  843. }
  844. else
  845. {
  846. if ( ret < 0 )
  847. {
  848. IPAERR("%s: While searching table for emtpy slot\n",
  849. table->name);
  850. }
  851. else
  852. {
  853. IPADBG("%s: No empty slots (ie. expansion table full): "
  854. "BASE (avail/used): (%u/%u) EXPN (avail/used): (%u/%u)\n",
  855. table->name,
  856. table->table_entries,
  857. table->cur_tbl_cnt,
  858. table->expn_table_entries,
  859. table->cur_expn_tbl_cnt);
  860. }
  861. ret = -1;
  862. }
  863. bail:
  864. IPADBG("Out\n");
  865. return ret;
  866. }
  867. /**
  868. * Get2PowerTightUpperBound() - Returns the tight upper bound which is a power of 2
  869. * @num: [in] given number
  870. *
  871. * Returns the tight upper bound for a given number which is power of 2
  872. *
  873. * Returns: the tight upper bound which is power of 2
  874. */
  875. static int Get2PowerTightUpperBound(uint16_t num)
  876. {
  877. uint16_t tmp = num, prev = 0, curr = 2;
  878. if (num == 0)
  879. return 2;
  880. while (tmp != 1)
  881. {
  882. prev = curr;
  883. curr <<= 1;
  884. tmp >>= 1;
  885. }
  886. return (num == prev) ? prev : curr;
  887. }
  888. /**
  889. * GetEvenTightUpperBound() - Returns the tight upper bound which is an even number
  890. * @num: [in] given number
  891. *
  892. * Returns the tight upper bound for a given number which is an even number
  893. *
  894. * Returns: the tight upper bound which is an even number
  895. */
  896. static int GetEvenTightUpperBound(uint16_t num)
  897. {
  898. if (num == 0)
  899. return 2;
  900. return (num % 2) ? num + 1 : num;
  901. }
  902. int ipa_calc_num_sram_table_entries(
  903. uint32_t sram_size,
  904. uint32_t table1_ent_size,
  905. uint32_t table2_ent_size,
  906. uint16_t* num_entries_ptr)
  907. {
  908. ipa_table nat_table;
  909. ipa_table index_table;
  910. int size = 0;
  911. uint16_t tot;
  912. IPADBG("In\n");
  913. IPADBG("sram_size(%x or %u)\n", sram_size, sram_size);
  914. *num_entries_ptr = 0;
  915. tot = 1;
  916. while ( 1 )
  917. {
  918. IPADBG("Trying %u entries\n", tot);
  919. ipa_table_init(&nat_table,
  920. "tmp_sram_table1",
  921. IPA_NAT_MEM_IN_DDR,
  922. table1_ent_size,
  923. NULL,
  924. 0,
  925. NULL);
  926. ipa_table_init(&index_table,
  927. "tmp_sram_table1",
  928. IPA_NAT_MEM_IN_DDR,
  929. table2_ent_size,
  930. NULL,
  931. 0,
  932. NULL);
  933. nat_table.table_entries = index_table.table_entries =
  934. Get2PowerTightUpperBound(tot * IPA_BASE_TABLE_PCNT_4SRAM);
  935. nat_table.expn_table_entries = index_table.expn_table_entries =
  936. GetEvenTightUpperBound(tot * IPA_EXPANSION_TABLE_PCNT_4SRAM);
  937. size = ipa_table_calculate_size(&nat_table);
  938. size += ipa_table_calculate_size(&index_table);
  939. IPADBG("%u entries consumes size(0x%x or %u)\n", tot, size, size);
  940. if ( size > sram_size )
  941. break;
  942. *num_entries_ptr = tot;
  943. ++tot;
  944. }
  945. IPADBG("Optimal number of entries: %u\n", *num_entries_ptr);
  946. IPADBG("Out\n");
  947. return (*num_entries_ptr) ? 0 : -1;
  948. }
  949. int ipa_table_walk(
  950. ipa_table* ipa_tbl_ptr,
  951. uint16_t start_index,
  952. When2Callback when2cb,
  953. ipa_table_walk_cb walk_cb,
  954. void* arb_data_ptr )
  955. {
  956. uint16_t i;
  957. uint32_t tot;
  958. uint8_t* rec_ptr;
  959. void* meta_record_ptr;
  960. uint16_t meta_record_index;
  961. int ret = 0;
  962. IPADBG("In\n");
  963. if ( ! ipa_tbl_ptr ||
  964. ! VALID_WHEN2CALLBACK(when2cb) ||
  965. ! walk_cb )
  966. {
  967. IPAERR("Bad arg: ipa_tbl_ptr(%p) and/or "
  968. "when2cb(%u) and/or walk_cb(%p)\n",
  969. ipa_tbl_ptr,
  970. when2cb,
  971. walk_cb);
  972. ret = -EINVAL;
  973. goto bail;
  974. }
  975. tot =
  976. ipa_tbl_ptr->table_entries +
  977. ipa_tbl_ptr->expn_table_entries;
  978. if ( start_index >= tot )
  979. {
  980. IPAERR("Bad arg: start_index(%u)\n", start_index);
  981. ret = -EINVAL;
  982. goto bail;
  983. }
  984. /*
  985. * Go through table...
  986. */
  987. for ( i = start_index, rec_ptr = GOTO_REC(ipa_tbl_ptr, start_index);
  988. i < tot;
  989. i++, rec_ptr += ipa_tbl_ptr->entry_size )
  990. {
  991. bool call_back;
  992. if ( ipa_tbl_ptr->entry_interface->entry_is_valid(rec_ptr) )
  993. {
  994. call_back = (when2cb == WHEN_SLOT_FILLED) ? true : false;
  995. }
  996. else
  997. {
  998. call_back = (when2cb == WHEN_SLOT_EMPTY) ? true : false;
  999. }
  1000. if ( call_back )
  1001. {
  1002. uint32_t rule_hdl = MakeEntryHdl(ipa_tbl_ptr, i);
  1003. meta_record_ptr = NULL;
  1004. meta_record_index = 0;
  1005. if ( i >= ipa_tbl_ptr->table_entries && ipa_tbl_ptr->meta )
  1006. {
  1007. meta_record_index = i - ipa_tbl_ptr->table_entries;
  1008. meta_record_ptr = (uint8_t*) ipa_tbl_ptr->meta +
  1009. (meta_record_index * ipa_tbl_ptr->meta_entry_size);
  1010. }
  1011. ret = walk_cb(
  1012. ipa_tbl_ptr,
  1013. rule_hdl,
  1014. rec_ptr,
  1015. i,
  1016. meta_record_ptr,
  1017. meta_record_index,
  1018. arb_data_ptr);
  1019. if ( ret != 0 )
  1020. {
  1021. if ( ret < 0 )
  1022. {
  1023. IPAERR("walk_cb returned non-zero (%d)\n", ret);
  1024. }
  1025. else
  1026. {
  1027. IPADBG("walk_cb returned non-zero (%d)\n", ret);
  1028. }
  1029. goto bail;
  1030. }
  1031. }
  1032. }
  1033. bail:
  1034. IPADBG("Out\n");
  1035. return ret;
  1036. }
  1037. int ipa_table_add_dma_cmd(
  1038. ipa_table* tbl_ptr,
  1039. dma_help_type help_type,
  1040. void* rec_ptr,
  1041. uint16_t rec_index,
  1042. uint16_t data_for_entry,
  1043. struct ipa_ioc_nat_dma_cmd* cmd_ptr )
  1044. {
  1045. ipa_table_dma_cmd_helper* help_ptr;
  1046. uint32_t tab_sz, entry_offset;
  1047. uint8_t is_expn;
  1048. int ret = 0;
  1049. IPADBG("In\n");
  1050. if ( ! tbl_ptr ||
  1051. ! VALID_DMA_HELP_TYPE(help_type) ||
  1052. ! rec_ptr ||
  1053. ! cmd_ptr )
  1054. {
  1055. IPAERR("Bad arg: tbl_ptr(%p) and/or help_type(%u) "
  1056. "and/or rec_ptr(%p) and/or cmd_ptr(%p)\n",
  1057. tbl_ptr,
  1058. help_type,
  1059. rec_ptr,
  1060. cmd_ptr);
  1061. ret = -EINVAL;
  1062. goto bail;
  1063. }
  1064. tab_sz =
  1065. tbl_ptr->table_entries +
  1066. tbl_ptr->expn_table_entries;
  1067. if ( rec_index >= tab_sz )
  1068. {
  1069. IPAERR("Bad arg: rec_index(%u)\n", rec_index);
  1070. ret = -EINVAL;
  1071. goto bail;
  1072. }
  1073. is_expn = (rec_index >= tbl_ptr->table_entries);
  1074. entry_offset = (uint8_t*) rec_ptr -
  1075. ((is_expn) ? tbl_ptr->expn_table_addr : tbl_ptr->table_addr);
  1076. ipa_table_dma_cmd_generate(
  1077. tbl_ptr->dma_help[help_type],
  1078. is_expn,
  1079. entry_offset,
  1080. data_for_entry,
  1081. cmd_ptr);
  1082. bail:
  1083. IPADBG("Out\n");
  1084. return ret;
  1085. }