1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333 |
- /*
- * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "ipa_table.h"
- #include "ipa_nat_utils.h"
- #include <errno.h>
- #define IPA_BASE_TABLE_PERCENTAGE .8
- #define IPA_EXPANSION_TABLE_PERCENTAGE .2
- #define IPA_BASE_TABLE_PCNT_4SRAM 1.00
- #define IPA_EXPANSION_TABLE_PCNT_4SRAM 0.43
- /*
- * The table number of entries is limited by Entry ID structure
- * above. The base table max entries is limited by index into table
- * bits number.
- *
- * The table max ents number is: (base table max ents / base table percentage)
- *
- * IPA_TABLE_MAX_ENTRIES = 2^(index into table) / IPA_BASE_TABLE_PERCENTAGE
- */
- static int InsertHead(
- ipa_table* table,
- void* rec_ptr, /* empty record in table */
- uint16_t rec_index, /* index of record above */
- void* user_data,
- struct ipa_ioc_nat_dma_cmd* cmd );
- static int InsertTail(
- ipa_table* table,
- void* rec_ptr, /* occupied record at index below */
- uint16_t* rec_index_ptr, /* pointer to index of record above */
- void* user_data,
- struct ipa_ioc_nat_dma_cmd* cmd );
- static uint16_t MakeEntryHdl(
- ipa_table* tbl,
- uint16_t tbl_entry );
- static int FindExpnTblFreeEntry(
- ipa_table* table,
- void** free_entry,
- uint16_t* entry_index );
- static int Get2PowerTightUpperBound(
- uint16_t num);
- static int GetEvenTightUpperBound(
- uint16_t num);
- void ipa_table_init(
- ipa_table* table,
- const char* table_name,
- enum ipa3_nat_mem_in nmi,
- int entry_size,
- void* meta,
- int meta_entry_size,
- ipa_table_entry_interface* entry_interface )
- {
- IPADBG("In\n");
- memset(table, 0, sizeof(ipa_table));
- strlcpy(table->name, table_name, IPA_RESOURCE_NAME_MAX);
- table->nmi = nmi;
- table->entry_size = entry_size;
- table->meta = meta;
- table->meta_entry_size = meta_entry_size;
- table->entry_interface = entry_interface;
- IPADBG("Table %s with entry size %d has been initialized\n",
- table->name, table->entry_size);
- IPADBG("Out\n");
- }
- int ipa_table_calculate_entries_num(
- ipa_table* table,
- uint16_t number_of_entries,
- enum ipa3_nat_mem_in nmi)
- {
- uint16_t table_entries, expn_table_entries;
- float btp, etp;
- int result = 0;
- IPADBG("In\n");
- if (number_of_entries > IPA_TABLE_MAX_ENTRIES)
- {
- IPAERR("Required number of %s entries %d exceeds the maximum %d\n",
- table->name, number_of_entries, IPA_TABLE_MAX_ENTRIES);
- result = -EINVAL;
- goto bail;
- }
- if ( nmi == IPA_NAT_MEM_IN_SRAM )
- {
- btp = IPA_BASE_TABLE_PCNT_4SRAM;
- etp = IPA_EXPANSION_TABLE_PCNT_4SRAM;
- }
- else
- {
- btp = IPA_BASE_TABLE_PERCENTAGE;
- etp = IPA_EXPANSION_TABLE_PERCENTAGE;
- }
- table_entries = Get2PowerTightUpperBound(number_of_entries * btp);
- expn_table_entries = GetEvenTightUpperBound(number_of_entries * etp);
- table->tot_tbl_ents = table_entries + expn_table_entries;
- if ( table->tot_tbl_ents > IPA_TABLE_MAX_ENTRIES )
- {
- IPAERR("Required number of %s entries %u "
- "(user provided %u) exceeds the maximum %u\n",
- table->name,
- table->tot_tbl_ents,
- number_of_entries,
- IPA_TABLE_MAX_ENTRIES);
- result = -EINVAL;
- goto bail;
- }
- table->table_entries = table_entries;
- table->expn_table_entries = expn_table_entries;
- IPADBG("Num of %s entries:%u expn entries:%u total entries:%u\n",
- table->name,
- table->table_entries,
- table->expn_table_entries,
- table->tot_tbl_ents);
- bail:
- IPADBG("Out\n");
- return result;
- }
- int ipa_table_calculate_size(ipa_table* table)
- {
- int size = table->entry_size * (table->table_entries + table->expn_table_entries);
- IPADBG("In\n");
- IPADBG("%s size: %d\n", table->name, size);
- IPADBG("Out\n");
- return size;
- }
- uint8_t* ipa_table_calculate_addresses(
- ipa_table* table,
- uint8_t* base_addr)
- {
- uint8_t* result = NULL;
- IPADBG("In\n");
- table->table_addr = base_addr;
- table->expn_table_addr =
- table->table_addr + table->entry_size * table->table_entries;
- IPADBG("Table %s addresses: table_addr %pK expn_table_addr %pK\n",
- table->name, table->table_addr, table->expn_table_addr);
- result = table->expn_table_addr + table->entry_size * table->expn_table_entries;
- IPADBG("Out\n");
- return result;
- }
- void ipa_table_reset(
- ipa_table* table)
- {
- uint32_t i,tot;
- IPADBG("In\n");
- IPADBG("memset %s table to 0, %pK\n", table->name, table->table_addr);
- tot = table->entry_size * table->table_entries;
- for (i = 0; i < tot; i++)
- table->table_addr[i] = '\0';
- IPADBG("memset %s expn table to 0, %pK\n", table->name, table->expn_table_addr);
- tot = table->entry_size * table->expn_table_entries;
- for (i = 0; i < tot; i++)
- table->expn_table_addr[i] = '\0';
- IPADBG("Out\n");
- }
- int ipa_table_add_entry(
- ipa_table* table,
- void* user_data,
- uint16_t* rec_index_ptr,
- uint32_t* rule_hdl,
- struct ipa_ioc_nat_dma_cmd* cmd )
- {
- void* rec_ptr;
- int ret = 0, occupied;
- IPADBG("In\n");
- rec_ptr = GOTO_REC(table, *rec_index_ptr);
- /*
- * Check whether there is any collision
- */
- occupied = table->entry_interface->entry_is_valid(rec_ptr);
- if ( ! occupied )
- {
- IPADBG("Collision free (in %s) ... found open slot\n", table->name);
- ret = InsertHead(table, rec_ptr, *rec_index_ptr, user_data, cmd);
- }
- else
- {
- IPADBG("Collision (in %s) ... will probe for open slot\n", table->name);
- ret = InsertTail(table, rec_ptr, rec_index_ptr, user_data, cmd);
- }
- if (ret)
- goto bail;
- IPADBG("New Entry Index %u in %s\n", *rec_index_ptr, table->name);
- if ( rule_hdl ) {
- *rule_hdl = MakeEntryHdl(table, *rec_index_ptr);
- IPADBG("rule_hdl value(%u)\n", *rule_hdl);
- }
- bail:
- IPADBG("Out\n");
- return ret;
- }
- void ipa_table_create_delete_command(
- ipa_table* table,
- struct ipa_ioc_nat_dma_cmd* cmd,
- ipa_table_iterator* iterator)
- {
- IPADBG("In\n");
- IPADBG("Delete rule at index(0x%04X) in %s\n",
- iterator->curr_index,
- table->name);
- if ( ! VALID_INDEX(iterator->prev_index) )
- {
- /*
- * The following two assigns (ie. the defaults), will cause
- * the enabled bit in the record to be set to 0.
- */
- uint16_t data = 0;
- dma_help_type ht = HELP_UPDATE_HEAD;
- if ( VALID_INDEX(iterator->next_index) )
- {
- /*
- * NOTE WELL HERE:
- *
- * This record is the first in a chain/list of
- * records. Delete means something different in this
- * context.
- *
- * The code below will cause the change of the protocol
- * field in the rule record to 0xFF. It does not set the
- * enable bit in the record to 0. This is done in special
- * cases when the record being deleted is the first in a
- * list of records.
- *
- * What does this mean? It means that the record is
- * functionally deleted, but not really deleted. Why?
- * Because the IPA will no longer use it because of the
- * bad protocol (ie. functionally deleted), but these
- * higher level APIs still see it as "enabled."
- *
- * This all means that deleted really means two things: 1)
- * Not enabled, and 2) Not a valid record. APIs that walk
- * the table...looking for enabled records (ie. the
- * enabled bit)....now have to be a bit smarter to see the
- * bad protocol as well.
- */
- data = table->entry_interface->
- entry_get_delete_head_dma_command_data(
- iterator->curr_entry, iterator->next_entry);
- ht = HELP_DELETE_HEAD;
- }
- ipa_table_add_dma_cmd(table,
- ht,
- iterator->curr_entry,
- iterator->curr_index,
- data,
- cmd);
- }
- else
- {
- ipa_table_add_dma_cmd(table,
- HELP_UPDATE_ENTRY,
- iterator->prev_entry,
- iterator->prev_index,
- iterator->next_index,
- cmd);
- }
- IPADBG("Out\n");
- }
- void ipa_table_delete_entry(
- ipa_table* table,
- ipa_table_iterator* iterator,
- uint8_t is_prev_empty)
- {
- IPADBG("In\n");
- if ( VALID_INDEX(iterator->next_index) )
- {
- /*
- * Update the next entry's prev_index field with current
- * entry's prev_index
- */
- table->entry_interface->entry_set_prev_index(
- iterator->next_entry,
- iterator->next_index,
- iterator->prev_index,
- table->meta,
- table->table_entries);
- }
- else if (is_prev_empty)
- {
- if (iterator->prev_entry == NULL)
- {
- IPAERR("failed to delete of an empty head %d while delete the next entry %d in %s",
- iterator->prev_index, iterator->curr_index, table->name);
- }
- else
- {
- /*
- * Delete an empty head rule after the whole tail was deleted
- */
- IPADBG("deleting the dead node %d for %s\n",
- iterator->prev_index, table->name);
- memset(iterator->prev_entry, 0, table->entry_size);
- --table->cur_tbl_cnt;
- }
- }
- ipa_table_erase_entry(table, iterator->curr_index);
- IPADBG("Out\n");
- }
- void ipa_table_erase_entry(
- ipa_table* table,
- uint16_t index)
- {
- void* entry = GOTO_REC(table, index);
- IPADBG("In\n");
- IPADBG("table(%p) index(%u)\n", table, index);
- memset(entry, 0, table->entry_size);
- if ( index < table->table_entries )
- {
- --table->cur_tbl_cnt;
- }
- else
- {
- --table->cur_expn_tbl_cnt;
- }
- IPADBG("Out\n");
- }
- /**
- * ipa_table_get_entry() - returns a table entry according to the received entry handle
- * @table: [in] the table
- * @entry_handle: [in] entry handle
- * @entry: [out] the retrieved entry
- * @entry_index: [out] absolute index of the retrieved entry
- *
- * Parse the entry handle to retrieve the entry and its index
- *
- * Returns: 0 on success, negative on failure
- */
- int ipa_table_get_entry(
- ipa_table* table,
- uint32_t entry_handle,
- void** entry,
- uint16_t* entry_index )
- {
- enum ipa3_nat_mem_in nmi;
- uint8_t is_expn_tbl;
- uint16_t rec_index;
- int ret = 0;
- IPADBG("In\n");
- IPADBG("table(%p) entry_handle(%u) entry(%p) entry_index(%p)\n",
- table, entry_handle, entry, entry_index);
- /*
- * Retrieve the memory and table type as well as the index
- */
- BREAK_RULE_HDL(table, entry_handle, nmi, is_expn_tbl, rec_index);
- if ( is_expn_tbl )
- {
- IPADBG("Retrieving entry from expansion table\n");
- }
- else
- {
- IPADBG("Retrieving entry from base (non-expansion) table\n");
- }
- if ( rec_index >= table->tot_tbl_ents )
- {
- IPAERR("The entry handle's record index (%u) exceeds table size (%u)\n",
- rec_index, table->tot_tbl_ents);
- ret = -EINVAL;
- goto bail;
- }
- *entry = GOTO_REC(table, rec_index);
- if ( entry_index )
- {
- *entry_index = rec_index;
- }
- bail:
- IPADBG("Out\n");
- return ret;
- }
- void* ipa_table_get_entry_by_index(
- ipa_table* table,
- uint16_t rec_index )
- {
- void* result = NULL;
- IPADBG("In\n");
- IPADBG("table(%p) rec_index(%u)\n",
- table,
- rec_index);
- if ( ! rec_index || rec_index >= table->tot_tbl_ents )
- {
- IPAERR("Invalid record index (%u): It's "
- "either zero or exceeds table size (%u)\n",
- rec_index, table->tot_tbl_ents);
- goto bail;
- }
- result = GOTO_REC(table, rec_index);
- bail:
- IPADBG("Out\n");
- return result;
- }
- void ipa_table_dma_cmd_helper_init(
- ipa_table_dma_cmd_helper* dma_cmd_helper,
- uint8_t table_indx,
- ipa_table_dma_type table_type,
- ipa_table_dma_type expn_table_type,
- uint32_t offset)
- {
- IPADBG("In\n");
- dma_cmd_helper->offset = offset;
- dma_cmd_helper->table_indx = table_indx;
- dma_cmd_helper->table_type = table_type;
- dma_cmd_helper->expn_table_type = expn_table_type;
- IPADBG("Out\n");
- }
- void ipa_table_dma_cmd_generate(
- ipa_table_dma_cmd_helper* dma_cmd_helper,
- uint8_t is_expn,
- uint32_t entry_offset,
- uint16_t data,
- struct ipa_ioc_nat_dma_cmd* cmd)
- {
- struct ipa_ioc_nat_dma_one* dma = &cmd->dma[cmd->entries];
- IPADBG("In\n");
- IPADBG("is_expn(0x%02X) entry_offset(0x%08X) data(0x%04X)\n",
- is_expn, entry_offset, data);
- dma->table_index = dma_cmd_helper->table_indx;
- /*
- * DMA parameter base_addr is the table type (see the IPA
- * architecture document)
- */
- dma->base_addr =
- (is_expn) ?
- dma_cmd_helper->expn_table_type :
- dma_cmd_helper->table_type;
- dma->offset = dma_cmd_helper->offset + entry_offset;
- dma->data = data;
- IPADBG("dma_entry[%u](table_index(0x%02X) "
- "base_addr(0x%02X) data(0x%04X) offset(0x%08X))\n",
- cmd->entries,
- dma->table_index,
- dma->base_addr,
- dma->data,
- dma->offset);
- cmd->entries++;
- IPADBG("Out\n");
- }
- int ipa_table_iterator_init(
- ipa_table_iterator* iterator,
- ipa_table* table,
- void* curr_entry,
- uint16_t curr_index)
- {
- int occupied;
- int ret = 0;
- IPADBG("In\n");
- memset(iterator, 0, sizeof(ipa_table_iterator));
- occupied = table->entry_interface->entry_is_valid(curr_entry);
- if ( ! occupied )
- {
- IPAERR("Invalid (not enabled) rule %u in %s\n", curr_index, table->name);
- ret = -EINVAL;
- goto bail;
- }
- iterator->curr_entry = curr_entry;
- iterator->curr_index = curr_index;
- iterator->prev_index = table->entry_interface->entry_get_prev_index(
- curr_entry,
- curr_index,
- table->meta,
- table->table_entries);
- iterator->next_index = table->entry_interface->entry_get_next_index(
- curr_entry);
- if ( VALID_INDEX(iterator->prev_index) )
- {
- iterator->prev_entry = ipa_table_get_entry_by_index(
- table,
- iterator->prev_index);
- if ( iterator->prev_entry == NULL )
- {
- IPAERR("Failed to retrieve the entry at index 0x%04X for %s\n",
- iterator->prev_index, table->name);
- ret = -EPERM;
- goto bail;
- }
- }
- if ( VALID_INDEX(iterator->next_index) )
- {
- iterator->next_entry = ipa_table_get_entry_by_index(
- table,
- iterator->next_index);
- if ( iterator->next_entry == NULL )
- {
- IPAERR("Failed to retrieve the entry at index 0x%04X for %s\n",
- iterator->next_index, table->name);
- ret = -EPERM;
- goto bail;
- }
- }
- IPADBG("[index/entry] for "
- "prev:[0x%04X/%p] "
- "curr:[0x%04X/%p] "
- "next:[0x%04X/%p] "
- "\"%s\"\n",
- iterator->prev_index,
- iterator->prev_entry,
- iterator->curr_index,
- iterator->curr_entry,
- iterator->next_index,
- iterator->next_entry,
- table->name);
- bail:
- IPADBG("Out\n");
- return ret;
- }
- int ipa_table_iterator_next(
- ipa_table_iterator* iterator,
- ipa_table* table)
- {
- int ret = 0;
- IPADBG("In\n");
- iterator->prev_entry = iterator->curr_entry;
- iterator->prev_index = iterator->curr_index;
- iterator->curr_entry = iterator->next_entry;
- iterator->curr_index = iterator->next_index;
- iterator->next_index = table->entry_interface->entry_get_next_index(
- iterator->curr_entry);
- if ( ! VALID_INDEX(iterator->next_index) )
- {
- iterator->next_entry = NULL;
- }
- else
- {
- iterator->next_entry = ipa_table_get_entry_by_index(
- table, iterator->next_index);
- if (iterator->next_entry == NULL)
- {
- IPAERR("Failed to retrieve the entry at index %d for %s\n",
- iterator->next_index, table->name);
- ret = -EPERM;
- goto bail;
- }
- }
- IPADBG("Iterator moved to: prev_index=%d curr_index=%d next_index=%d\n",
- iterator->prev_index, iterator->curr_index, iterator->next_index);
- IPADBG(" prev_entry=%pK curr_entry=%pK next_entry=%pK\n",
- iterator->prev_entry, iterator->curr_entry, iterator->next_entry);
- bail:
- IPADBG("Out\n");
- return ret;
- }
- int ipa_table_iterator_end(
- ipa_table_iterator* iterator,
- ipa_table* table_ptr,
- uint16_t rec_index, /* a table slot relative to hash */
- void* rec_ptr ) /* occupant record at index above */
- {
- bool found_end = false;
- int ret;
- IPADBG("In\n");
- if ( ! iterator || ! table_ptr || ! rec_ptr )
- {
- IPAERR("Bad arg: iterator(%p) and/or table_ptr (%p) and/or rec_ptr(%p)\n",
- iterator, table_ptr, rec_ptr);
- ret = -1;
- goto bail;
- }
- memset(iterator, 0, sizeof(ipa_table_iterator));
- iterator->prev_index = rec_index;
- iterator->prev_entry = rec_ptr;
- while ( 1 )
- {
- uint16_t next_index =
- table_ptr->entry_interface->entry_get_next_index(iterator->prev_entry);
- if ( ! VALID_INDEX(next_index) )
- {
- found_end = true;
- break;
- }
- if ( next_index == iterator->prev_index )
- {
- IPAERR("next_index(%u) and prev_index(%u) shouldn't be equal in %s\n",
- next_index,
- iterator->prev_index,
- table_ptr->name);
- break;
- }
- iterator->prev_index = next_index;
- iterator->prev_entry = GOTO_REC(table_ptr, next_index);
- }
- if ( found_end )
- {
- IPADBG("Iterator found end of list record\n");
- ret = 0;
- }
- else
- {
- IPAERR("Iterator can't find end of list record\n");
- ret = -1;
- }
- bail:
- IPADBG("Out\n");
- return ret;
- }
- int ipa_table_iterator_is_head_with_tail(
- ipa_table_iterator* iterator)
- {
- int ret = 0;
- IPADBG("In\n");
- ret = VALID_INDEX(iterator->next_index) && ! VALID_INDEX(iterator->prev_index);
- IPADBG("Out\n");
- return ret;
- }
- static int InsertHead(
- ipa_table* table,
- void* rec_ptr, /* empty record in table */
- uint16_t rec_index, /* index of record above */
- void* user_data,
- struct ipa_ioc_nat_dma_cmd* cmd )
- {
- uint16_t enable_data = 0;
- int ret = 0;
- IPADBG("In\n");
- ret = table->entry_interface->entry_head_insert(
- rec_ptr,
- user_data,
- &enable_data);
- if (ret)
- {
- IPAERR("unable to insert a new entry to the head in %s\n", table->name);
- goto bail;
- }
- ipa_table_add_dma_cmd(
- table,
- HELP_UPDATE_HEAD,
- rec_ptr,
- rec_index,
- enable_data,
- cmd);
- ++table->cur_tbl_cnt;
- bail:
- IPADBG("Out\n");
- return ret;
- }
- static int InsertTail(
- ipa_table* table,
- void* rec_ptr, /* occupied record at index below */
- uint16_t* rec_index_ptr, /* pointer to index of record above */
- void* user_data,
- struct ipa_ioc_nat_dma_cmd* cmd )
- {
- bool is_index_tbl = (table->meta) ? true : false;
- ipa_table_iterator iterator;
- uint16_t enable_data = 0;
- int ret = 0;
- IPADBG("In\n");
- /*
- * The most important side effect of the following is to set the
- * iterator's prev_index and prev_entry...which will be the last
- * valid entry on the end of the list.
- */
- ret = ipa_table_iterator_end(&iterator, table, *rec_index_ptr, rec_ptr);
- if ( ret )
- {
- IPAERR("Failed to reach the end of list following rec_index(%u) in %s\n",
- *rec_index_ptr, table->name);
- goto bail;
- }
- /*
- * The most important side effect of the following is to set the
- * iterator's curr_index and curr_entry with the next available
- * expansion table open slot.
- */
- ret = FindExpnTblFreeEntry(table, &iterator.curr_entry, &iterator.curr_index);
- if ( ret )
- {
- IPAERR("FindExpnTblFreeEntry of %s failed\n", table->name);
- goto bail;
- }
- /*
- * Copy data into curr_entry (ie. open slot).
- */
- if ( is_index_tbl )
- {
- ret = table->entry_interface->entry_tail_insert(
- iterator.curr_entry,
- user_data);
- }
- else
- {
- /*
- * We need enable bit when not index table, hence...
- */
- ret = table->entry_interface->entry_head_insert(
- iterator.curr_entry,
- user_data,
- &enable_data);
- }
- if (ret)
- {
- IPAERR("Unable to insert a new entry to the tail in %s\n", table->name);
- goto bail;
- }
- /*
- * Update curr_entry's prev_index field with iterator.prev_index
- */
- table->entry_interface->entry_set_prev_index(
- iterator.curr_entry, /* set by FindExpnTblFreeEntry above */
- iterator.curr_index, /* set by FindExpnTblFreeEntry above */
- iterator.prev_index, /* set by ipa_table_iterator_end above */
- table->meta,
- table->table_entries);
- if ( ! is_index_tbl )
- {
- /*
- * Generate dma command to have the IPA update the
- * curr_entry's enable field when not the index table...
- */
- ipa_table_add_dma_cmd(
- table,
- HELP_UPDATE_HEAD,
- iterator.curr_entry,
- iterator.curr_index,
- enable_data,
- cmd);
- }
- /*
- * Generate a dma command to have the IPA update the prev_entry's
- * next_index with iterator.curr_index.
- */
- ipa_table_add_dma_cmd(
- table,
- HELP_UPDATE_ENTRY,
- iterator.prev_entry,
- iterator.prev_index,
- iterator.curr_index,
- cmd);
- ++table->cur_expn_tbl_cnt;
- *rec_index_ptr = iterator.curr_index;
- bail:
- IPADBG("Out\n");
- return ret;
- }
- /**
- * MakeEntryHdl() - makes an entry handle
- * @tbl_hdl: [in] tbl - the table
- * @tbl_entry: [in] tbl_entry - table entry
- *
- * Calculate the entry handle which will be returned to client
- *
- * Returns: >0 table entry handle
- */
- static uint16_t MakeEntryHdl(
- ipa_table* tbl,
- uint16_t tbl_entry )
- {
- uint16_t entry_hdl = 0;
- IPADBG("In\n");
- if (tbl_entry >= tbl->table_entries)
- {
- /*
- * Update the index into table
- */
- entry_hdl = tbl_entry - tbl->table_entries;
- entry_hdl = (entry_hdl << IPA_TABLE_TYPE_BITS);
- /*
- * Update the expansion table type bit
- */
- entry_hdl = (entry_hdl | IPA_TABLE_TYPE_MASK);
- }
- else
- {
- entry_hdl = tbl_entry;
- entry_hdl = (entry_hdl << IPA_TABLE_TYPE_BITS);
- }
- /*
- * Set memory type bit.
- */
- entry_hdl = entry_hdl | (tbl->nmi << IPA_TABLE_TYPE_MEM_SHIFT);
- IPADBG("In: tbl_entry(%u) Out: entry_hdl(%u)\n", tbl_entry, entry_hdl);
- IPADBG("Out\n");
- return entry_hdl;
- }
- static int mt_slot(
- ipa_table* table_ptr,
- uint32_t rule_hdl,
- void* record_ptr,
- uint16_t record_index,
- void* meta_record_ptr,
- uint16_t meta_record_index,
- void* arb_data_ptr )
- {
- IPADBG("%s: Empty expansion slot: (%u) in table of size: (%u)\n",
- table_ptr->name,
- record_index,
- table_ptr->tot_tbl_ents);
- return record_index;
- }
- /*
- * returns expn table entry absolute index
- */
- static int FindExpnTblFreeEntry(
- ipa_table* table,
- void** free_entry,
- uint16_t* entry_index )
- {
- int ret;
- IPADBG("In\n");
- if ( ! table || ! free_entry || ! entry_index )
- {
- IPAERR("Bad arg: table(%p) and/or "
- "free_entry(%p) and/or entry_index(%p)\n",
- table, free_entry, entry_index);
- ret = -1;
- goto bail;
- }
- *entry_index = 0;
- *free_entry = NULL;
- /*
- * The following will start walk at expansion slots
- * (ie. just after table->table_entries)...
- */
- ret = ipa_table_walk(table, table->table_entries, WHEN_SLOT_EMPTY, mt_slot, 0);
- if ( ret > 0 )
- {
- *entry_index = (uint16_t) ret;
- *free_entry = GOTO_REC(table, *entry_index);
- IPADBG("%s: entry_index val (%u) free_entry val (%p)\n",
- table->name,
- *entry_index,
- *free_entry);
- ret = 0;
- }
- else
- {
- if ( ret < 0 )
- {
- IPAERR("%s: While searching table for emtpy slot\n",
- table->name);
- }
- else
- {
- IPADBG("%s: No empty slots (ie. expansion table full): "
- "BASE (avail/used): (%u/%u) EXPN (avail/used): (%u/%u)\n",
- table->name,
- table->table_entries,
- table->cur_tbl_cnt,
- table->expn_table_entries,
- table->cur_expn_tbl_cnt);
- }
- ret = -1;
- }
- bail:
- IPADBG("Out\n");
- return ret;
- }
- /**
- * Get2PowerTightUpperBound() - Returns the tight upper bound which is a power of 2
- * @num: [in] given number
- *
- * Returns the tight upper bound for a given number which is power of 2
- *
- * Returns: the tight upper bound which is power of 2
- */
- static int Get2PowerTightUpperBound(uint16_t num)
- {
- uint16_t tmp = num, prev = 0, curr = 2;
- if (num == 0)
- return 2;
- while (tmp != 1)
- {
- prev = curr;
- curr <<= 1;
- tmp >>= 1;
- }
- return (num == prev) ? prev : curr;
- }
- /**
- * GetEvenTightUpperBound() - Returns the tight upper bound which is an even number
- * @num: [in] given number
- *
- * Returns the tight upper bound for a given number which is an even number
- *
- * Returns: the tight upper bound which is an even number
- */
- static int GetEvenTightUpperBound(uint16_t num)
- {
- if (num == 0)
- return 2;
- return (num % 2) ? num + 1 : num;
- }
- int ipa_calc_num_sram_table_entries(
- uint32_t sram_size,
- uint32_t table1_ent_size,
- uint32_t table2_ent_size,
- uint16_t* num_entries_ptr)
- {
- ipa_table nat_table;
- ipa_table index_table;
- int size = 0;
- uint16_t tot;
- IPADBG("In\n");
- IPADBG("sram_size(%x or %u)\n", sram_size, sram_size);
- *num_entries_ptr = 0;
- tot = 1;
- while ( 1 )
- {
- IPADBG("Trying %u entries\n", tot);
- ipa_table_init(&nat_table,
- "tmp_sram_table1",
- IPA_NAT_MEM_IN_DDR,
- table1_ent_size,
- NULL,
- 0,
- NULL);
- ipa_table_init(&index_table,
- "tmp_sram_table1",
- IPA_NAT_MEM_IN_DDR,
- table2_ent_size,
- NULL,
- 0,
- NULL);
- nat_table.table_entries = index_table.table_entries =
- Get2PowerTightUpperBound(tot * IPA_BASE_TABLE_PCNT_4SRAM);
- nat_table.expn_table_entries = index_table.expn_table_entries =
- GetEvenTightUpperBound(tot * IPA_EXPANSION_TABLE_PCNT_4SRAM);
- size = ipa_table_calculate_size(&nat_table);
- size += ipa_table_calculate_size(&index_table);
- IPADBG("%u entries consumes size(0x%x or %u)\n", tot, size, size);
- if ( size > sram_size )
- break;
- *num_entries_ptr = tot;
- ++tot;
- }
- IPADBG("Optimal number of entries: %u\n", *num_entries_ptr);
- IPADBG("Out\n");
- return (*num_entries_ptr) ? 0 : -1;
- }
- int ipa_table_walk(
- ipa_table* ipa_tbl_ptr,
- uint16_t start_index,
- When2Callback when2cb,
- ipa_table_walk_cb walk_cb,
- void* arb_data_ptr )
- {
- uint16_t i;
- uint32_t tot;
- uint8_t* rec_ptr;
- void* meta_record_ptr;
- uint16_t meta_record_index;
- int ret = 0;
- IPADBG("In\n");
- if ( ! ipa_tbl_ptr ||
- ! VALID_WHEN2CALLBACK(when2cb) ||
- ! walk_cb )
- {
- IPAERR("Bad arg: ipa_tbl_ptr(%p) and/or "
- "when2cb(%u) and/or walk_cb(%p)\n",
- ipa_tbl_ptr,
- when2cb,
- walk_cb);
- ret = -EINVAL;
- goto bail;
- }
- tot =
- ipa_tbl_ptr->table_entries +
- ipa_tbl_ptr->expn_table_entries;
- if ( start_index >= tot )
- {
- IPAERR("Bad arg: start_index(%u)\n", start_index);
- ret = -EINVAL;
- goto bail;
- }
- /*
- * Go through table...
- */
- for ( i = start_index, rec_ptr = GOTO_REC(ipa_tbl_ptr, start_index);
- i < tot;
- i++, rec_ptr += ipa_tbl_ptr->entry_size )
- {
- bool call_back;
- if ( ipa_tbl_ptr->entry_interface->entry_is_valid(rec_ptr) )
- {
- call_back = (when2cb == WHEN_SLOT_FILLED) ? true : false;
- }
- else
- {
- call_back = (when2cb == WHEN_SLOT_EMPTY) ? true : false;
- }
- if ( call_back )
- {
- uint32_t rule_hdl = MakeEntryHdl(ipa_tbl_ptr, i);
- meta_record_ptr = NULL;
- meta_record_index = 0;
- if ( i >= ipa_tbl_ptr->table_entries && ipa_tbl_ptr->meta )
- {
- meta_record_index = i - ipa_tbl_ptr->table_entries;
- meta_record_ptr = (uint8_t*) ipa_tbl_ptr->meta +
- (meta_record_index * ipa_tbl_ptr->meta_entry_size);
- }
- ret = walk_cb(
- ipa_tbl_ptr,
- rule_hdl,
- rec_ptr,
- i,
- meta_record_ptr,
- meta_record_index,
- arb_data_ptr);
- if ( ret != 0 )
- {
- if ( ret < 0 )
- {
- IPAERR("walk_cb returned non-zero (%d)\n", ret);
- }
- else
- {
- IPADBG("walk_cb returned non-zero (%d)\n", ret);
- }
- goto bail;
- }
- }
- }
- bail:
- IPADBG("Out\n");
- return ret;
- }
- int ipa_table_add_dma_cmd(
- ipa_table* tbl_ptr,
- dma_help_type help_type,
- void* rec_ptr,
- uint16_t rec_index,
- uint16_t data_for_entry,
- struct ipa_ioc_nat_dma_cmd* cmd_ptr )
- {
- ipa_table_dma_cmd_helper* help_ptr;
- uint32_t tab_sz, entry_offset;
- uint8_t is_expn;
- int ret = 0;
- IPADBG("In\n");
- if ( ! tbl_ptr ||
- ! VALID_DMA_HELP_TYPE(help_type) ||
- ! rec_ptr ||
- ! cmd_ptr )
- {
- IPAERR("Bad arg: tbl_ptr(%p) and/or help_type(%u) "
- "and/or rec_ptr(%p) and/or cmd_ptr(%p)\n",
- tbl_ptr,
- help_type,
- rec_ptr,
- cmd_ptr);
- ret = -EINVAL;
- goto bail;
- }
- tab_sz =
- tbl_ptr->table_entries +
- tbl_ptr->expn_table_entries;
- if ( rec_index >= tab_sz )
- {
- IPAERR("Bad arg: rec_index(%u)\n", rec_index);
- ret = -EINVAL;
- goto bail;
- }
- is_expn = (rec_index >= tbl_ptr->table_entries);
- entry_offset = (uint8_t*) rec_ptr -
- ((is_expn) ? tbl_ptr->expn_table_addr : tbl_ptr->table_addr);
- ipa_table_dma_cmd_generate(
- tbl_ptr->dma_help[help_type],
- is_expn,
- entry_offset,
- data_for_entry,
- cmd_ptr);
- bail:
- IPADBG("Out\n");
- return ret;
- }
|