123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
- */
- #include "ipa_i.h"
- #include <linux/if_ether.h>
- #include <linux/log2.h>
- #include <linux/debugfs.h>
- #include <linux/ipa_wigig.h>
- #define IPA_WIGIG_DESC_RING_EL_SIZE 32
- #define IPA_WIGIG_STATUS_RING_EL_SIZE 16
- #define GSI_STOP_MAX_RETRY_CNT 10
- #define IPA_WIGIG_CONNECTED BIT(0)
- #define IPA_WIGIG_ENABLED BIT(1)
- #define IPA_WIGIG_MSB_MASK 0xFFFFFFFF00000000
- #define IPA_WIGIG_LSB_MASK 0x00000000FFFFFFFF
- #define IPA_WIGIG_MSB(num) ((u32)((num & IPA_WIGIG_MSB_MASK) >> 32))
- #define IPA_WIGIG_LSB(num) ((u32)(num & IPA_WIGIG_LSB_MASK))
- /* extract PCIE addresses [0:39] relevant msb */
- #define IPA_WIGIG_8_MSB_MASK 0xFF00000000
- #define IPA_WIGIG_8_MSB(num) ((u32)((num & IPA_WIGIG_8_MSB_MASK) >> 32))
- #define W11AD_RX 0
- #define W11AD_TX 1
- #define W11AD_TO_GSI_DB_m 1
- #define W11AD_TO_GSI_DB_n 1
- static LIST_HEAD(smmu_reg_addr_list);
- static LIST_HEAD(smmu_ring_addr_list);
- static DEFINE_MUTEX(smmu_lock);
- struct dentry *wigig_dent;
- struct ipa_wigig_smmu_reg_addr {
- struct list_head link;
- phys_addr_t phys_addr;
- enum ipa_smmu_cb_type cb_type;
- u8 count;
- };
- struct ipa_wigig_smmu_ring_addr {
- struct list_head link;
- u64 iova;
- enum ipa_smmu_cb_type cb_type;
- u8 count;
- };
- static int ipa3_wigig_uc_loaded_handler(struct notifier_block *self,
- unsigned long val, void *data)
- {
- IPADBG("val %ld\n", val);
- if (!ipa3_ctx) {
- IPAERR("IPA ctx is null\n");
- return -EINVAL;
- }
- WARN_ON(data != ipa3_ctx);
- if (ipa3_ctx->uc_wigig_ctx.uc_ready_cb) {
- ipa3_ctx->uc_wigig_ctx.uc_ready_cb(
- ipa3_ctx->uc_wigig_ctx.priv);
- ipa3_ctx->uc_wigig_ctx.uc_ready_cb =
- NULL;
- ipa3_ctx->uc_wigig_ctx.priv = NULL;
- }
- IPADBG("exit\n");
- return 0;
- }
- static struct notifier_block uc_loaded_notifier = {
- .notifier_call = ipa3_wigig_uc_loaded_handler,
- };
- int ipa3_wigig_init_i(void)
- {
- IPADBG("\n");
- ipa3_uc_register_ready_cb(&uc_loaded_notifier);
- IPADBG("exit\n");
- return 0;
- }
- int ipa3_wigig_internal_init(
- struct ipa_wdi_uc_ready_params *inout,
- ipa_wigig_misc_int_cb int_notify,
- phys_addr_t *uc_db_pa)
- {
- int result = 0;
- IPADBG("\n");
- if (inout == NULL) {
- IPAERR("inout is NULL");
- return -EINVAL;
- }
- if (int_notify == NULL) {
- IPAERR("int_notify is NULL");
- return -EINVAL;
- }
- result = ipa3_uc_state_check();
- if (result) {
- inout->is_uC_ready = false;
- ipa3_ctx->uc_wigig_ctx.uc_ready_cb = inout->notify;
- } else {
- inout->is_uC_ready = true;
- }
- ipa3_ctx->uc_wigig_ctx.priv = inout->priv;
- ipa3_ctx->uc_wigig_ctx.misc_notify_cb = int_notify;
- *uc_db_pa = ipa3_ctx->ipa_wrapper_base +
- ipahal_get_reg_base() +
- ipahal_get_reg_mn_ofst(
- IPA_UC_MAILBOX_m_n,
- W11AD_TO_GSI_DB_m,
- W11AD_TO_GSI_DB_n);
- IPADBG("exit\n");
- return 0;
- }
- static int ipa3_wigig_tx_bit_to_ep(
- const u8 tx_bit_num,
- enum ipa_client_type *type)
- {
- IPADBG("tx_bit_num %d\n", tx_bit_num);
- switch (tx_bit_num) {
- case 2:
- *type = IPA_CLIENT_WIGIG1_CONS;
- break;
- case 3:
- *type = IPA_CLIENT_WIGIG2_CONS;
- break;
- case 4:
- *type = IPA_CLIENT_WIGIG3_CONS;
- break;
- case 5:
- *type = IPA_CLIENT_WIGIG4_CONS;
- break;
- default:
- IPAERR("invalid tx_bit_num %d\n", tx_bit_num);
- return -EINVAL;
- }
- IPADBG("exit\n");
- return 0;
- }
- static int ipa3_wigig_smmu_map_buffers(bool Rx,
- struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu,
- void *buff,
- bool map)
- {
- int result;
- /* data buffers */
- if (Rx) {
- struct ipa_wigig_rx_pipe_data_buffer_info_smmu *dbuff_smmu =
- (struct ipa_wigig_rx_pipe_data_buffer_info_smmu *)buff;
- int num_elem =
- pipe_smmu->desc_ring_size /
- IPA_WIGIG_DESC_RING_EL_SIZE;
- result = ipa3_smmu_map_peer_buff(
- dbuff_smmu->data_buffer_base_iova,
- dbuff_smmu->data_buffer_size * num_elem,
- map,
- &dbuff_smmu->data_buffer_base,
- IPA_SMMU_CB_11AD);
- if (result) {
- IPAERR(
- "failed to %s rx data_buffer %d, num elem %d\n"
- , map ? "map" : "unmap",
- result, num_elem);
- goto fail_map_buff;
- }
- } else {
- int i;
- struct ipa_wigig_tx_pipe_data_buffer_info_smmu *dbuff_smmu =
- (struct ipa_wigig_tx_pipe_data_buffer_info_smmu *)buff;
- for (i = 0; i < dbuff_smmu->num_buffers; i++) {
- result = ipa3_smmu_map_peer_buff(
- *(dbuff_smmu->data_buffer_base_iova + i),
- dbuff_smmu->data_buffer_size,
- map,
- (dbuff_smmu->data_buffer_base + i),
- IPA_SMMU_CB_11AD);
- if (result) {
- IPAERR(
- "%d: failed to %s tx data buffer %d\n"
- , i, map ? "map" : "unmap",
- result);
- for (i--; i >= 0; i--) {
- result = ipa3_smmu_map_peer_buff(
- *(dbuff_smmu->data_buffer_base_iova +
- i),
- dbuff_smmu->data_buffer_size,
- !map,
- (dbuff_smmu->data_buffer_base +
- i),
- IPA_SMMU_CB_11AD);
- }
- goto fail_map_buff;
- }
- }
- }
- IPADBG("exit\n");
- return 0;
- fail_map_buff:
- return result;
- }
- static int ipa3_wigig_smmu_map_reg(phys_addr_t phys_addr, bool map,
- enum ipa_smmu_cb_type cb_type)
- {
- struct ipa_wigig_smmu_reg_addr *entry;
- struct ipa_wigig_smmu_reg_addr *next;
- int result = 0;
- IPADBG("addr %pa, %s\n", &phys_addr, map ? "map" : "unmap");
- mutex_lock(&smmu_lock);
- list_for_each_entry_safe(entry, next, &smmu_reg_addr_list, link) {
- if ((entry->phys_addr == phys_addr) &&
- (entry->cb_type == cb_type)) {
- IPADBG("cb %d, page %pa already mapped, ", cb_type,
- &phys_addr);
- if (map) {
- entry->count++;
- IPADBG("inc to %d\n", (entry->count));
- } else {
- --entry->count;
- IPADBG("dec to %d\n", entry->count);
- if (!(entry->count)) {
- IPADBG("unmap and delete\n");
- result = ipa3_smmu_map_peer_reg(
- phys_addr, map, cb_type);
- if (result) {
- IPAERR("failed to unmap %pa\n",
- &phys_addr);
- goto finish;
- }
- list_del(&entry->link);
- kfree(entry);
- }
- }
- goto finish;
- }
- }
- IPADBG("new page found %pa, map and add to list CB %d\n", &phys_addr,
- cb_type);
- result = ipa3_smmu_map_peer_reg(phys_addr, map, cb_type);
- if (result) {
- IPAERR("failed to map %pa\n", &phys_addr);
- goto finish;
- }
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (entry == NULL) {
- IPAERR("couldn't allocate for %pa\n", &phys_addr);
- ipa3_smmu_map_peer_reg(phys_addr, !map, cb_type);
- result = -ENOMEM;
- goto finish;
- }
- INIT_LIST_HEAD(&entry->link);
- entry->phys_addr = phys_addr;
- entry->cb_type = cb_type;
- entry->count = 1;
- list_add(&entry->link, &smmu_reg_addr_list);
- finish:
- mutex_unlock(&smmu_lock);
- IPADBG("exit\n");
- return result;
- }
- static int ipa3_wigig_smmu_map_ring(u64 iova, u32 size, bool map,
- struct sg_table *sgt, enum ipa_smmu_cb_type cb_type)
- {
- struct ipa_wigig_smmu_ring_addr *entry;
- struct ipa_wigig_smmu_ring_addr *next;
- int result = 0;
- IPADBG("iova %llX, %s\n", iova, map ? "map" : "unmap");
- mutex_lock(&smmu_lock);
- list_for_each_entry_safe(entry, next, &smmu_ring_addr_list, link) {
- if ((entry->iova == iova) &&
- (entry->cb_type == cb_type)) {
- IPADBG("cb %d, page 0x%llX already mapped, ", cb_type,
- iova);
- if (map) {
- entry->count++;
- IPADBG("inc to %d\n", (entry->count));
- } else {
- --entry->count;
- IPADBG("dec to %d\n", entry->count);
- if (!(entry->count)) {
- IPADBG("unmap and delete\n");
- result = ipa3_smmu_map_peer_buff(
- iova, size, map, sgt, cb_type);
- if (result) {
- IPAERR(
- "failed to unmap 0x%llX\n",
- iova);
- goto finish;
- }
- list_del(&entry->link);
- kfree(entry);
- }
- }
- goto finish;
- }
- }
- IPADBG("new page found 0x%llX, map and add to list\n", iova);
- result = ipa3_smmu_map_peer_buff(iova, size, map, sgt, cb_type);
- if (result) {
- IPAERR("failed to map 0x%llX\n", iova);
- goto finish;
- }
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (entry == NULL) {
- IPAERR("couldn't allocate for 0x%llX\n", iova);
- ipa3_smmu_map_peer_buff(iova, size, !map, sgt, cb_type);
- result = -ENOMEM;
- goto finish;
- }
- INIT_LIST_HEAD(&entry->link);
- entry->iova = iova;
- entry->cb_type = cb_type;
- entry->count = 1;
- list_add(&entry->link, &smmu_ring_addr_list);
- finish:
- mutex_unlock(&smmu_lock);
- IPADBG("exit\n");
- return result;
- }
- static int ipa3_wigig_smmu_map_channel(bool Rx,
- struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu,
- void *buff,
- bool map)
- {
- int result = 0;
- struct ipa_smmu_cb_ctx *smmu_ctx = ipa3_get_smmu_ctx(IPA_SMMU_CB_11AD);
- IPADBG("\n");
- /*
- * --------------------------------------------------------------------
- * entity |HWHEAD|HWTAIL|HWHEAD|HWTAIL| misc | buffers| rings|
- * |Sring |Sring |Dring |Dring | regs | | |
- * --------------------------------------------------------------------
- * GSI (apps CB) | TX |RX, TX| |RX, TX| | |Rx, TX|
- * --------------------------------------------------------------------
- * IPA (11AD CB) | | | | | | RX, TX | |
- * --------------------------------------------------------------------
- * uc (uC CB) | RX | | TX | |always| | |
- * --------------------------------------------------------------------
- *
- * buffers are mapped to 11AD CB. in case this context bank is shared,
- * mapping is done by 11ad driver only and applies to both 11ad and
- * IPA HWs (page tables are shared). Otherwise, mapping is done here.
- */
- if (!smmu_ctx) {
- IPAERR("11AD SMMU ctx is null\n");
- return -EINVAL;
- }
- if (Rx) {
- IPADBG("RX %s status_ring_HWHEAD_pa %pa uC CB\n",
- map ? "map" : "unmap",
- &pipe_smmu->status_ring_HWHEAD_pa);
- result = ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->status_ring_HWHEAD_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR(
- "failed to %s status_ring_HWAHEAD %d\n",
- map ? "map" : "unmap",
- result);
- goto fail;
- }
- } else {
- IPADBG("TX %s status_ring_HWHEAD_pa %pa AP CB\n",
- map ? "map" : "unmap",
- &pipe_smmu->status_ring_HWHEAD_pa);
- result = ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->status_ring_HWHEAD_pa,
- PAGE_SIZE),
- map,
- IPA_SMMU_CB_AP);
- if (result) {
- IPAERR(
- "failed to %s status_ring_HWAHEAD %d\n",
- map ? "map" : "unmap",
- result);
- goto fail;
- }
- IPADBG("TX %s desc_ring_HWHEAD_pa %pa uC CB\n",
- map ? "map" : "unmap",
- &pipe_smmu->desc_ring_HWHEAD_pa);
- result = ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->desc_ring_HWHEAD_pa,
- PAGE_SIZE),
- map,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR("failed to %s desc_ring_HWHEAD %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_desc_HWHEAD;
- }
- }
- IPADBG("%s status_ring_HWTAIL_pa %pa AP CB\n",
- map ? "map" : "unmap",
- &pipe_smmu->status_ring_HWTAIL_pa);
- result = ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->status_ring_HWTAIL_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_AP);
- if (result) {
- IPAERR(
- "failed to %s status_ring_HWTAIL %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_status_HWTAIL;
- }
- IPADBG("%s desc_ring_HWTAIL_pa %pa AP CB\n",
- map ? "map" : "unmap",
- &pipe_smmu->desc_ring_HWTAIL_pa);
- result = ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->desc_ring_HWTAIL_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_AP);
- if (result) {
- IPAERR("failed to %s desc_ring_HWTAIL %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_desc_HWTAIL;
- }
- /* rings */
- IPADBG("%s desc_ring_base_iova %llX AP CB\n",
- map ? "map" : "unmap",
- pipe_smmu->desc_ring_base_iova);
- result = ipa3_wigig_smmu_map_ring(
- pipe_smmu->desc_ring_base_iova,
- pipe_smmu->desc_ring_size,
- map,
- &pipe_smmu->desc_ring_base,
- IPA_SMMU_CB_AP);
- if (result) {
- IPAERR("failed to %s desc_ring_base %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_desc_ring;
- }
- IPADBG("%s status_ring_base_iova %llX AP CB\n",
- map ? "map" : "unmap",
- pipe_smmu->status_ring_base_iova);
- result = ipa3_wigig_smmu_map_ring(
- pipe_smmu->status_ring_base_iova,
- pipe_smmu->status_ring_size,
- map,
- &pipe_smmu->status_ring_base,
- IPA_SMMU_CB_AP);
- if (result) {
- IPAERR("failed to %s status_ring_base %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_status_ring;
- }
- if (!smmu_ctx->shared) {
- IPADBG("CB not shared - map buffers\n");
- result = ipa3_wigig_smmu_map_buffers(Rx, pipe_smmu, buff, map);
- if (result) {
- IPAERR("failed to %s buffers %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_buffers;
- }
- }
- IPADBG("exit\n");
- return 0;
- fail_buffers:
- ipa3_wigig_smmu_map_ring(
- pipe_smmu->status_ring_base_iova, pipe_smmu->status_ring_size,
- !map, &pipe_smmu->status_ring_base, IPA_SMMU_CB_AP);
- fail_status_ring:
- ipa3_wigig_smmu_map_ring(
- pipe_smmu->desc_ring_base_iova, pipe_smmu->desc_ring_size,
- !map, &pipe_smmu->desc_ring_base, IPA_SMMU_CB_AP);
- fail_desc_ring:
- ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->desc_ring_HWTAIL_pa, PAGE_SIZE),
- !map, IPA_SMMU_CB_AP);
- fail_desc_HWTAIL:
- ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->status_ring_HWTAIL_pa, PAGE_SIZE),
- !map, IPA_SMMU_CB_AP);
- fail_status_HWTAIL:
- if (Rx)
- ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->status_ring_HWHEAD_pa, PAGE_SIZE),
- !map, IPA_SMMU_CB_UC);
- else
- ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->desc_ring_HWHEAD_pa, PAGE_SIZE),
- !map, IPA_SMMU_CB_UC);
- fail_desc_HWHEAD:
- if (!Rx)
- ipa3_wigig_smmu_map_reg(
- rounddown(pipe_smmu->status_ring_HWHEAD_pa, PAGE_SIZE),
- !map, IPA_SMMU_CB_AP);
- fail:
- return result;
- }
- static void ipa_gsi_chan_err_cb(struct gsi_chan_err_notify *notify)
- {
- switch (notify->evt_id) {
- case GSI_CHAN_INVALID_TRE_ERR:
- IPAERR("Got GSI_CHAN_INVALID_TRE_ERR\n");
- break;
- case GSI_CHAN_NON_ALLOCATED_EVT_ACCESS_ERR:
- IPAERR("Got GSI_CHAN_NON_ALLOCATED_EVT_ACCESS_ERR\n");
- break;
- case GSI_CHAN_OUT_OF_BUFFERS_ERR:
- IPAERR("Got GSI_CHAN_OUT_OF_BUFFERS_ERR\n");
- break;
- case GSI_CHAN_OUT_OF_RESOURCES_ERR:
- IPAERR("Got GSI_CHAN_OUT_OF_RESOURCES_ERR\n");
- break;
- case GSI_CHAN_UNSUPPORTED_INTER_EE_OP_ERR:
- IPAERR("Got GSI_CHAN_UNSUPPORTED_INTER_EE_OP_ERR\n");
- break;
- case GSI_CHAN_HWO_1_ERR:
- IPAERR("Got GSI_CHAN_HWO_1_ERR\n");
- break;
- default:
- IPAERR("Unexpected err evt: %d\n", notify->evt_id);
- }
- ipa_assert();
- }
- static void ipa_gsi_evt_ring_err_cb(struct gsi_evt_err_notify *notify)
- {
- switch (notify->evt_id) {
- case GSI_EVT_OUT_OF_BUFFERS_ERR:
- IPAERR("Got GSI_EVT_OUT_OF_BUFFERS_ERR\n");
- break;
- case GSI_EVT_OUT_OF_RESOURCES_ERR:
- IPAERR("Got GSI_EVT_OUT_OF_RESOURCES_ERR\n");
- break;
- case GSI_EVT_UNSUPPORTED_INTER_EE_OP_ERR:
- IPAERR("Got GSI_EVT_UNSUPPORTED_INTER_EE_OP_ERR\n");
- break;
- case GSI_EVT_EVT_RING_EMPTY_ERR:
- IPAERR("Got GSI_EVT_EVT_RING_EMPTY_ERR\n");
- break;
- default:
- IPAERR("Unexpected err evt: %d\n", notify->evt_id);
- }
- ipa_assert();
- }
- static uint16_t int_modt = 15;
- static uint8_t int_modc = 200;
- static uint8_t tx_hwtail_mod_threshold = 200;
- static uint8_t rx_hwtail_mod_threshold = 200;
- static int ipa3_wigig_config_gsi(bool Rx,
- bool smmu_en,
- void *pipe_info,
- void *buff,
- const struct ipa_gsi_ep_config *ep_gsi,
- struct ipa3_ep_context *ep)
- {
- struct gsi_evt_ring_props evt_props;
- struct gsi_chan_props channel_props;
- union __packed gsi_channel_scratch gsi_scratch;
- int gsi_res;
- struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu;
- struct ipa_wigig_pipe_setup_info *pipe;
- struct ipa_wigig_rx_pipe_data_buffer_info *rx_dbuff;
- struct ipa_wigig_rx_pipe_data_buffer_info_smmu *rx_dbuff_smmu;
- struct ipa_wigig_tx_pipe_data_buffer_info *tx_dbuff;
- struct ipa_wigig_tx_pipe_data_buffer_info_smmu *tx_dbuff_smmu;
- IPADBG("%s, %s\n", Rx ? "Rx" : "Tx", smmu_en ? "smmu en" : "smmu dis");
- /* alloc event ring */
- memset(&evt_props, 0, sizeof(evt_props));
- evt_props.intf = GSI_EVT_CHTYPE_11AD_EV;
- evt_props.re_size = GSI_EVT_RING_RE_SIZE_16B;
- evt_props.intr = GSI_INTR_MSI;
- evt_props.intvec = 0;
- evt_props.exclusive = true;
- evt_props.err_cb = ipa_gsi_evt_ring_err_cb;
- evt_props.user_data = NULL;
- evt_props.int_modc = int_modc;
- evt_props.int_modt = int_modt;
- evt_props.ring_base_vaddr = NULL;
- if (smmu_en) {
- pipe_smmu = (struct ipa_wigig_pipe_setup_info_smmu *)pipe_info;
- evt_props.ring_base_addr =
- pipe_smmu->desc_ring_base_iova;
- evt_props.ring_len = pipe_smmu->desc_ring_size;
- evt_props.msi_addr = pipe_smmu->desc_ring_HWTAIL_pa;
- } else {
- pipe = (struct ipa_wigig_pipe_setup_info *)pipe_info;
- evt_props.ring_base_addr = pipe->desc_ring_base_pa;
- evt_props.ring_len = pipe->desc_ring_size;
- evt_props.msi_addr = pipe->desc_ring_HWTAIL_pa;
- }
- gsi_res = gsi_alloc_evt_ring(&evt_props,
- ipa3_ctx->gsi_dev_hdl,
- &ep->gsi_evt_ring_hdl);
- if (gsi_res != GSI_STATUS_SUCCESS) {
- IPAERR("Error allocating event ring: %d\n", gsi_res);
- return -EFAULT;
- }
- /* event scratch not configured by SW for TX channels */
- if (Rx) {
- union __packed gsi_evt_scratch evt_scratch;
- memset(&evt_scratch, 0, sizeof(evt_scratch));
- evt_scratch.w11ad.update_status_hwtail_mod_threshold =
- rx_hwtail_mod_threshold;
- gsi_res = gsi_write_evt_ring_scratch(ep->gsi_evt_ring_hdl,
- evt_scratch);
- if (gsi_res != GSI_STATUS_SUCCESS) {
- IPAERR("Error writing WIGIG event ring scratch: %d\n",
- gsi_res);
- goto fail_write_evt_scratch;
- }
- }
- ep->gsi_mem_info.evt_ring_len = evt_props.ring_len;
- ep->gsi_mem_info.evt_ring_base_addr = evt_props.ring_base_addr;
- ep->gsi_mem_info.evt_ring_base_vaddr = evt_props.ring_base_vaddr;
- /* alloc channel ring */
- memset(&channel_props, 0, sizeof(channel_props));
- memset(&gsi_scratch, 0, sizeof(gsi_scratch));
- if (Rx)
- channel_props.dir = GSI_CHAN_DIR_TO_GSI;
- else
- channel_props.dir = GSI_CHAN_DIR_FROM_GSI;
- channel_props.re_size = GSI_CHAN_RE_SIZE_16B;
- channel_props.prot = GSI_CHAN_PROT_11AD;
- channel_props.ch_id = ep_gsi->ipa_gsi_chan_num;
- channel_props.evt_ring_hdl = ep->gsi_evt_ring_hdl;
- channel_props.xfer_cb = NULL;
- channel_props.use_db_eng = GSI_CHAN_DB_MODE;
- channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
- channel_props.prefetch_mode = ep_gsi->prefetch_mode;
- channel_props.empty_lvl_threshold = ep_gsi->prefetch_threshold;
- channel_props.low_weight = 1;
- channel_props.err_cb = ipa_gsi_chan_err_cb;
- channel_props.ring_base_vaddr = NULL;
- if (Rx) {
- if (smmu_en) {
- rx_dbuff_smmu =
- (struct ipa_wigig_rx_pipe_data_buffer_info_smmu *)buff;
- channel_props.ring_base_addr =
- pipe_smmu->status_ring_base_iova;
- channel_props.ring_len =
- pipe_smmu->status_ring_size;
- gsi_scratch.rx_11ad.status_ring_hwtail_address_lsb =
- IPA_WIGIG_LSB(
- pipe_smmu->status_ring_HWTAIL_pa);
- gsi_scratch.rx_11ad.status_ring_hwtail_address_msb =
- IPA_WIGIG_MSB(
- pipe_smmu->status_ring_HWTAIL_pa);
- gsi_scratch.rx_11ad.data_buffers_base_address_lsb =
- IPA_WIGIG_LSB(
- rx_dbuff_smmu->data_buffer_base_iova);
- gsi_scratch.rx_11ad.data_buffers_base_address_msb =
- IPA_WIGIG_MSB(
- rx_dbuff_smmu->data_buffer_base_iova);
- gsi_scratch.rx_11ad.fixed_data_buffer_size_pow_2 =
- ilog2(rx_dbuff_smmu->data_buffer_size);
- } else {
- rx_dbuff =
- (struct ipa_wigig_rx_pipe_data_buffer_info *)buff;
- channel_props.ring_base_addr =
- pipe->status_ring_base_pa;
- channel_props.ring_len = pipe->status_ring_size;
- gsi_scratch.rx_11ad.status_ring_hwtail_address_lsb =
- IPA_WIGIG_LSB(pipe->status_ring_HWTAIL_pa);
- gsi_scratch.rx_11ad.status_ring_hwtail_address_msb =
- IPA_WIGIG_MSB(pipe->status_ring_HWTAIL_pa);
- gsi_scratch.rx_11ad.data_buffers_base_address_lsb =
- IPA_WIGIG_LSB(rx_dbuff->data_buffer_base_pa);
- gsi_scratch.rx_11ad.data_buffers_base_address_msb =
- IPA_WIGIG_MSB(rx_dbuff->data_buffer_base_pa);
- gsi_scratch.rx_11ad.fixed_data_buffer_size_pow_2 =
- ilog2(rx_dbuff->data_buffer_size);
- }
- IPADBG("rx scratch: status_ring_hwtail_address_lsb 0x%X\n",
- gsi_scratch.rx_11ad.status_ring_hwtail_address_lsb);
- IPADBG("rx scratch: status_ring_hwtail_address_msb 0x%X\n",
- gsi_scratch.rx_11ad.status_ring_hwtail_address_msb);
- IPADBG("rx scratch: data_buffers_base_address_lsb 0x%X\n",
- gsi_scratch.rx_11ad.data_buffers_base_address_lsb);
- IPADBG("rx scratch: data_buffers_base_address_msb 0x%X\n",
- gsi_scratch.rx_11ad.data_buffers_base_address_msb);
- IPADBG("rx scratch: fixed_data_buffer_size_pow_2 %d\n",
- gsi_scratch.rx_11ad.fixed_data_buffer_size_pow_2);
- IPADBG("rx scratch 0x[%X][%X][%X][%X]\n",
- gsi_scratch.data.word1,
- gsi_scratch.data.word2,
- gsi_scratch.data.word3,
- gsi_scratch.data.word4);
- } else {
- if (smmu_en) {
- tx_dbuff_smmu =
- (struct ipa_wigig_tx_pipe_data_buffer_info_smmu *)buff;
- channel_props.ring_base_addr =
- pipe_smmu->desc_ring_base_iova;
- channel_props.ring_len =
- pipe_smmu->desc_ring_size;
- gsi_scratch.tx_11ad.status_ring_hwtail_address_lsb =
- IPA_WIGIG_LSB(
- pipe_smmu->status_ring_HWTAIL_pa);
- gsi_scratch.tx_11ad.status_ring_hwhead_address_lsb =
- IPA_WIGIG_LSB(
- pipe_smmu->status_ring_HWHEAD_pa);
- gsi_scratch.tx_11ad.status_ring_hwhead_hwtail_8_msb =
- IPA_WIGIG_8_MSB(
- pipe_smmu->status_ring_HWHEAD_pa);
- gsi_scratch.tx_11ad.fixed_data_buffer_size_pow_2 =
- ilog2(tx_dbuff_smmu->data_buffer_size);
- gsi_scratch.tx_11ad.status_ring_num_elem =
- pipe_smmu->status_ring_size /
- IPA_WIGIG_STATUS_RING_EL_SIZE;
- } else {
- tx_dbuff =
- (struct ipa_wigig_tx_pipe_data_buffer_info *)buff;
- channel_props.ring_base_addr = pipe->desc_ring_base_pa;
- channel_props.ring_len = pipe->desc_ring_size;
- gsi_scratch.tx_11ad.status_ring_hwtail_address_lsb =
- IPA_WIGIG_LSB(
- pipe->status_ring_HWTAIL_pa);
- gsi_scratch.tx_11ad.status_ring_hwhead_address_lsb =
- IPA_WIGIG_LSB(
- pipe->status_ring_HWHEAD_pa);
- gsi_scratch.tx_11ad.status_ring_hwhead_hwtail_8_msb =
- IPA_WIGIG_8_MSB(pipe->status_ring_HWHEAD_pa);
- gsi_scratch.tx_11ad.status_ring_num_elem =
- pipe->status_ring_size /
- IPA_WIGIG_STATUS_RING_EL_SIZE;
- gsi_scratch.tx_11ad.fixed_data_buffer_size_pow_2 =
- ilog2(tx_dbuff->data_buffer_size);
- }
- gsi_scratch.tx_11ad.update_status_hwtail_mod_threshold =
- tx_hwtail_mod_threshold;
- IPADBG("tx scratch: status_ring_hwtail_address_lsb 0x%X\n",
- gsi_scratch.tx_11ad.status_ring_hwtail_address_lsb);
- IPADBG("tx scratch: status_ring_hwhead_address_lsb 0x%X\n",
- gsi_scratch.tx_11ad.status_ring_hwhead_address_lsb);
- IPADBG("tx scratch: status_ring_hwhead_hwtail_8_msb 0x%X\n",
- gsi_scratch.tx_11ad.status_ring_hwhead_hwtail_8_msb);
- IPADBG("tx scratch:status_ring_num_elem %d\n",
- gsi_scratch.tx_11ad.status_ring_num_elem);
- IPADBG("tx scratch:fixed_data_buffer_size_pow_2 %d\n",
- gsi_scratch.tx_11ad.fixed_data_buffer_size_pow_2);
- IPADBG("tx scratch 0x[%X][%X][%X][%X]\n",
- gsi_scratch.data.word1,
- gsi_scratch.data.word2,
- gsi_scratch.data.word3,
- gsi_scratch.data.word4);
- }
- IPADBG("ch_id: %d\n", channel_props.ch_id);
- IPADBG("evt_ring_hdl: %ld\n", channel_props.evt_ring_hdl);
- IPADBG("re_size: %d\n", channel_props.re_size);
- IPADBG("GSI channel ring len: %d\n", channel_props.ring_len);
- IPADBG("channel ring base addr = 0x%llX\n",
- (unsigned long long)channel_props.ring_base_addr);
- IPADBG("Allocating GSI channel\n");
- gsi_res = gsi_alloc_channel(&channel_props,
- ipa3_ctx->gsi_dev_hdl,
- &ep->gsi_chan_hdl);
- if (gsi_res != GSI_STATUS_SUCCESS) {
- IPAERR("gsi_alloc_channel failed %d\n", gsi_res);
- goto fail_alloc_channel;
- }
- IPADBG("Writing Channel scratch\n");
- ep->gsi_mem_info.chan_ring_len = channel_props.ring_len;
- ep->gsi_mem_info.chan_ring_base_addr = channel_props.ring_base_addr;
- ep->gsi_mem_info.chan_ring_base_vaddr =
- channel_props.ring_base_vaddr;
- gsi_res = gsi_write_channel_scratch(ep->gsi_chan_hdl,
- gsi_scratch);
- if (gsi_res != GSI_STATUS_SUCCESS) {
- IPAERR("gsi_write_channel_scratch failed %d\n",
- gsi_res);
- goto fail_write_channel_scratch;
- }
- IPADBG("exit\n");
- return 0;
- fail_write_channel_scratch:
- gsi_dealloc_channel(ep->gsi_chan_hdl);
- fail_alloc_channel:
- fail_write_evt_scratch:
- gsi_dealloc_evt_ring(ep->gsi_evt_ring_hdl);
- return -EFAULT;
- }
- static int ipa3_wigig_config_uc(bool init,
- bool Rx,
- u8 wifi_ch,
- u8 gsi_ch,
- phys_addr_t HWHEAD)
- {
- struct ipa_mem_buffer cmd;
- enum ipa_cpu_2_hw_offload_commands command;
- int result;
- IPADBG("%s\n", init ? "init" : "Deinit");
- if (init) {
- struct IpaHwOffloadSetUpCmdData_t_v4_0 *cmd_data;
- cmd.size = sizeof(*cmd_data);
- cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
- &cmd.phys_base, GFP_KERNEL);
- if (cmd.base == NULL) {
- IPAERR("fail to get DMA memory.\n");
- return -ENOMEM;
- }
- cmd_data =
- (struct IpaHwOffloadSetUpCmdData_t_v4_0 *)cmd.base;
- cmd_data->protocol = IPA_HW_PROTOCOL_11ad;
- cmd_data->SetupCh_params.W11AdSetupCh_params.dir =
- Rx ? W11AD_RX : W11AD_TX;
- cmd_data->SetupCh_params.W11AdSetupCh_params.gsi_ch = gsi_ch;
- cmd_data->SetupCh_params.W11AdSetupCh_params.wifi_ch = wifi_ch;
- cmd_data->SetupCh_params.W11AdSetupCh_params.wifi_hp_addr_msb =
- IPA_WIGIG_MSB(HWHEAD);
- cmd_data->SetupCh_params.W11AdSetupCh_params.wifi_hp_addr_lsb =
- IPA_WIGIG_LSB(HWHEAD);
- command = IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP;
- } else {
- struct IpaHwOffloadCommonChCmdData_t_v4_0 *cmd_data;
- cmd.size = sizeof(*cmd_data);
- cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
- &cmd.phys_base, GFP_KERNEL);
- if (cmd.base == NULL) {
- IPAERR("fail to get DMA memory.\n");
- return -ENOMEM;
- }
- cmd_data =
- (struct IpaHwOffloadCommonChCmdData_t_v4_0 *)cmd.base;
- cmd_data->protocol = IPA_HW_PROTOCOL_11ad;
- cmd_data->CommonCh_params.W11AdCommonCh_params.gsi_ch = gsi_ch;
- command = IPA_CPU_2_HW_CMD_OFFLOAD_TEAR_DOWN;
- }
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
- command,
- IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
- false, 10 * HZ);
- if (result) {
- IPAERR("fail to %s uc for %s gsi channel %d\n",
- init ? "init" : "deinit",
- Rx ? "Rx" : "Tx", gsi_ch);
- }
- dma_free_coherent(ipa3_ctx->uc_pdev,
- cmd.size, cmd.base, cmd.phys_base);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- IPADBG("exit\n");
- return result;
- }
- int ipa3_conn_wigig_rx_pipe_i(void *in, struct ipa_wigig_conn_out_params *out,
- struct dentry **parent)
- {
- int ipa_ep_idx;
- struct ipa3_ep_context *ep;
- struct ipa_ep_cfg ep_cfg;
- enum ipa_client_type rx_client = IPA_CLIENT_WIGIG_PROD;
- bool is_smmu_enabled;
- struct ipa_wigig_conn_rx_in_params_smmu *input_smmu = NULL;
- struct ipa_wigig_conn_rx_in_params *input = NULL;
- const struct ipa_gsi_ep_config *ep_gsi;
- void *pipe_info;
- void *buff;
- phys_addr_t status_ring_HWHEAD_pa;
- int result;
- IPADBG("\n");
- *parent = wigig_dent;
- ipa_ep_idx = ipa_get_ep_mapping(rx_client);
- if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to get ep (IPA_CLIENT_WIGIG_PROD) %d.\n",
- ipa_ep_idx);
- return -EFAULT;
- }
- ep = &ipa3_ctx->ep[ipa_ep_idx];
- if (ep->valid) {
- IPAERR("EP %d already allocated.\n", ipa_ep_idx);
- return -EFAULT;
- }
- if (ep->gsi_offload_state) {
- IPAERR("WIGIG channel bad state 0x%X\n",
- ep->gsi_offload_state);
- return -EFAULT;
- }
- ep_gsi = ipa3_get_gsi_ep_info(rx_client);
- if (!ep_gsi) {
- IPAERR("Failed getting GSI EP info for client=%d\n",
- rx_client);
- return -EPERM;
- }
- memset(ep, 0, offsetof(struct ipa3_ep_context, sys));
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- /* setup rx ep cfg */
- ep->valid = 1;
- ep->client = rx_client;
- result = ipa3_disable_data_path(ipa_ep_idx);
- if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
- ipa_ep_idx);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return -EFAULT;
- }
- is_smmu_enabled = !ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_11AD];
- if (is_smmu_enabled) {
- struct ipa_wigig_rx_pipe_data_buffer_info_smmu *dbuff_smmu;
- input_smmu = (struct ipa_wigig_conn_rx_in_params_smmu *)in;
- dbuff_smmu = &input_smmu->dbuff_smmu;
- ep->client_notify = input_smmu->notify;
- ep->priv = input_smmu->priv;
- IPADBG(
- "desc_ring_base_iova 0x%llX desc_ring_size %d status_ring_base_iova 0x%llX status_ring_size %d",
- (unsigned long long)input_smmu->pipe_smmu.desc_ring_base_iova,
- input_smmu->pipe_smmu.desc_ring_size,
- (unsigned long long)input_smmu->pipe_smmu.status_ring_base_iova,
- input_smmu->pipe_smmu.status_ring_size);
- IPADBG("data_buffer_base_iova 0x%llX data_buffer_size %d",
- (unsigned long long)dbuff_smmu->data_buffer_base_iova,
- input_smmu->dbuff_smmu.data_buffer_size);
- if (IPA_WIGIG_MSB(
- dbuff_smmu->data_buffer_base_iova) &
- 0xFFFFFF00) {
- IPAERR(
- "data_buffers_base_address_msb is over the 8 bit limit (0x%llX)\n",
- (unsigned long long)dbuff_smmu->data_buffer_base_iova);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return -EFAULT;
- }
- if (dbuff_smmu->data_buffer_size >> 16) {
- IPAERR(
- "data_buffer_size is over the 16 bit limit (%d)\n"
- , dbuff_smmu->data_buffer_size);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return -EFAULT;
- }
- } else {
- input = (struct ipa_wigig_conn_rx_in_params *)in;
- ep->client_notify = input->notify;
- ep->priv = input->priv;
- IPADBG(
- "desc_ring_base_pa %pa desc_ring_size %d status_ring_base_pa %pa status_ring_size %d",
- &input->pipe.desc_ring_base_pa,
- input->pipe.desc_ring_size,
- &input->pipe.status_ring_base_pa,
- input->pipe.status_ring_size);
- IPADBG("data_buffer_base_pa %pa data_buffer_size %d",
- &input->dbuff.data_buffer_base_pa,
- input->dbuff.data_buffer_size);
- if (
- IPA_WIGIG_MSB(input->dbuff.data_buffer_base_pa) & 0xFFFFFF00) {
- IPAERR(
- "data_buffers_base_address_msb is over the 8 bit limit (0x%pa)\n"
- , &input->dbuff.data_buffer_base_pa);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return -EFAULT;
- }
- if (input->dbuff.data_buffer_size >> 16) {
- IPAERR(
- "data_buffer_size is over the 16 bit limit (0x%X)\n"
- , input->dbuff.data_buffer_size);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return -EFAULT;
- }
- }
- memset(&ep_cfg, 0, sizeof(ep_cfg));
- ep_cfg.nat.nat_en = IPA_SRC_NAT;
- ep_cfg.hdr.hdr_len = ETH_HLEN;
- ep_cfg.hdr.hdr_ofst_pkt_size_valid = 0;
- ep_cfg.hdr.hdr_ofst_pkt_size = 0;
- ep_cfg.hdr.hdr_additional_const_len = 0;
- ep_cfg.hdr_ext.hdr_little_endian = true;
- ep_cfg.hdr.hdr_ofst_metadata_valid = 0;
- ep_cfg.hdr.hdr_metadata_reg_valid = 1;
- ep_cfg.mode.mode = IPA_BASIC;
- if (ipa3_cfg_ep(ipa_ep_idx, &ep_cfg)) {
- IPAERR("fail to setup rx pipe cfg\n");
- result = -EFAULT;
- goto fail;
- }
- if (is_smmu_enabled) {
- result = ipa3_wigig_smmu_map_channel(true,
- &input_smmu->pipe_smmu,
- &input_smmu->dbuff_smmu,
- true);
- if (result) {
- IPAERR("failed to setup rx pipe smmu map\n");
- result = -EFAULT;
- goto fail;
- }
- pipe_info = &input_smmu->pipe_smmu;
- buff = &input_smmu->dbuff_smmu;
- status_ring_HWHEAD_pa =
- input_smmu->pipe_smmu.status_ring_HWHEAD_pa;
- } else {
- pipe_info = &input->pipe;
- buff = &input->dbuff;
- status_ring_HWHEAD_pa =
- input->pipe.status_ring_HWHEAD_pa;
- }
- result = ipa3_wigig_config_gsi(true,
- is_smmu_enabled,
- pipe_info,
- buff,
- ep_gsi, ep);
- if (result)
- goto fail_gsi;
- result = ipa3_wigig_config_uc(
- true, true, 0,
- ep_gsi->ipa_gsi_chan_num,
- status_ring_HWHEAD_pa);
- if (result)
- goto fail_uc_config;
- ipa3_install_dflt_flt_rules(ipa_ep_idx);
- out->client = IPA_CLIENT_WIGIG_PROD;
- ep->gsi_offload_state |= IPA_WIGIG_CONNECTED;
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- IPADBG("wigig rx pipe connected successfully\n");
- IPADBG("exit\n");
- return 0;
- fail_uc_config:
- /* Release channel and evt*/
- ipa3_release_gsi_channel(ipa_ep_idx);
- fail_gsi:
- if (input_smmu)
- ipa3_wigig_smmu_map_channel(true, &input_smmu->pipe_smmu,
- &input_smmu->dbuff_smmu, false);
- fail:
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return result;
- }
- int ipa3_conn_wigig_client_i(void *in,
- struct ipa_wigig_conn_out_params *out,
- ipa_notify_cb tx_notify,
- void *priv)
- {
- int ipa_ep_idx;
- struct ipa3_ep_context *ep;
- struct ipa_ep_cfg ep_cfg;
- enum ipa_client_type tx_client;
- bool is_smmu_enabled;
- struct ipa_wigig_conn_tx_in_params_smmu *input_smmu = NULL;
- struct ipa_wigig_conn_tx_in_params *input = NULL;
- const struct ipa_gsi_ep_config *ep_gsi;
- u32 aggr_byte_limit;
- int result;
- void *pipe_info;
- void *buff;
- phys_addr_t desc_ring_HWHEAD_pa;
- u8 wifi_ch;
- IPADBG("\n");
- is_smmu_enabled = !ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_11AD];
- if (is_smmu_enabled) {
- input_smmu = (struct ipa_wigig_conn_tx_in_params_smmu *)in;
- IPADBG(
- "desc_ring_base_iova 0x%llX desc_ring_size %d status_ring_base_iova 0x%llX status_ring_size %d",
- (unsigned long long)input_smmu->pipe_smmu.desc_ring_base_iova,
- input_smmu->pipe_smmu.desc_ring_size,
- (unsigned long long)input_smmu->pipe_smmu.status_ring_base_iova,
- input_smmu->pipe_smmu.status_ring_size);
- IPADBG("num buffers %d, data buffer size %d\n",
- input_smmu->dbuff_smmu.num_buffers,
- input_smmu->dbuff_smmu.data_buffer_size);
- if (ipa3_wigig_tx_bit_to_ep(input_smmu->int_gen_tx_bit_num,
- &tx_client)) {
- return -EINVAL;
- }
- if (input_smmu->dbuff_smmu.data_buffer_size >> 16) {
- IPAERR(
- "data_buffer_size is over the 16 bit limit (0x%X)\n"
- , input_smmu->dbuff_smmu.data_buffer_size);
- return -EFAULT;
- }
- if (IPA_WIGIG_8_MSB(
- input_smmu->pipe_smmu.status_ring_HWHEAD_pa)
- != IPA_WIGIG_8_MSB(
- input_smmu->pipe_smmu.status_ring_HWTAIL_pa)) {
- IPAERR(
- "status ring HWHEAD and HWTAIL differ in 8 MSbs head 0x%llX tail 0x%llX\n"
- , input_smmu->pipe_smmu.status_ring_HWHEAD_pa,
- input_smmu->pipe_smmu.status_ring_HWTAIL_pa);
- return -EFAULT;
- }
- wifi_ch = input_smmu->int_gen_tx_bit_num;
- /* convert to kBytes */
- aggr_byte_limit = IPA_ADJUST_AGGR_BYTE_HARD_LIMIT(
- input_smmu->dbuff_smmu.data_buffer_size);
- } else {
- input = (struct ipa_wigig_conn_tx_in_params *)in;
- IPADBG(
- "desc_ring_base_pa %pa desc_ring_size %d status_ring_base_pa %pa status_ring_size %d",
- &input->pipe.desc_ring_base_pa,
- input->pipe.desc_ring_size,
- &input->pipe.status_ring_base_pa,
- input->pipe.status_ring_size);
- IPADBG("data_buffer_size %d", input->dbuff.data_buffer_size);
- if (ipa3_wigig_tx_bit_to_ep(input->int_gen_tx_bit_num,
- &tx_client)) {
- return -EINVAL;
- }
- if (input->dbuff.data_buffer_size >> 16) {
- IPAERR(
- "data_buffer_size is over the 16 bit limit (0x%X)\n"
- , input->dbuff.data_buffer_size);
- return -EFAULT;
- }
- if (IPA_WIGIG_8_MSB(
- input->pipe.status_ring_HWHEAD_pa)
- != IPA_WIGIG_8_MSB(
- input->pipe.status_ring_HWTAIL_pa)) {
- IPAERR(
- "status ring HWHEAD and HWTAIL differ in 8 MSbs head 0x%llX tail 0x%llX\n"
- , input->pipe.status_ring_HWHEAD_pa,
- input->pipe.status_ring_HWTAIL_pa);
- return -EFAULT;
- }
- wifi_ch = input->int_gen_tx_bit_num;
- /* convert to kBytes */
- aggr_byte_limit = IPA_ADJUST_AGGR_BYTE_HARD_LIMIT(
- input->dbuff.data_buffer_size);
- }
- IPADBG("client type is %d\n", tx_client);
- ipa_ep_idx = ipa_get_ep_mapping(tx_client);
- if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to get ep (%d) %d.\n",
- tx_client, ipa_ep_idx);
- return -EFAULT;
- }
- ep = &ipa3_ctx->ep[ipa_ep_idx];
- if (ep->valid) {
- IPAERR("EP %d already allocated.\n", ipa_ep_idx);
- return -EFAULT;
- }
- if (ep->gsi_offload_state) {
- IPAERR("WIGIG channel bad state 0x%X\n",
- ep->gsi_offload_state);
- return -EFAULT;
- }
- ep_gsi = ipa3_get_gsi_ep_info(tx_client);
- if (!ep_gsi) {
- IPAERR("Failed getting GSI EP info for client=%d\n",
- tx_client);
- return -EFAULT;
- }
- memset(ep, 0, offsetof(struct ipa3_ep_context, sys));
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- /* setup tx ep cfg */
- ep->valid = 1;
- ep->client = tx_client;
- result = ipa3_disable_data_path(ipa_ep_idx);
- if (result) {
- IPAERR("disable data path failed res=%d clnt=%d.\n", result,
- ipa_ep_idx);
- goto fail;
- }
- ep->client_notify = tx_notify;
- ep->priv = priv;
- memset(&ep_cfg, 0, sizeof(ep_cfg));
- ep_cfg.nat.nat_en = IPA_DST_NAT;
- ep_cfg.hdr.hdr_len = ETH_HLEN;
- ep_cfg.hdr.hdr_ofst_pkt_size_valid = 0;
- ep_cfg.hdr.hdr_ofst_pkt_size = 0;
- ep_cfg.hdr.hdr_additional_const_len = 0;
- ep_cfg.hdr_ext.hdr_little_endian = true;
- ep_cfg.mode.mode = IPA_BASIC;
- /* config hard byte limit, max is the buffer size (in kB)*/
- ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR;
- ep_cfg.aggr.aggr = IPA_GENERIC;
- ep_cfg.aggr.aggr_pkt_limit = 1;
- ep_cfg.aggr.aggr_byte_limit = aggr_byte_limit;
- ep_cfg.aggr.aggr_hard_byte_limit_en = IPA_ENABLE_AGGR;
- if (ipa3_cfg_ep(ipa_ep_idx, &ep_cfg)) {
- IPAERR("fail to setup rx pipe cfg\n");
- result = -EFAULT;
- goto fail;
- }
- if (is_smmu_enabled) {
- result = ipa3_wigig_smmu_map_channel(false,
- &input_smmu->pipe_smmu,
- &input_smmu->dbuff_smmu,
- true);
- if (result) {
- IPAERR(
- "failed to setup tx pipe smmu map client %d (ep %d)\n"
- , tx_client, ipa_ep_idx);
- result = -EFAULT;
- goto fail;
- }
- pipe_info = &input_smmu->pipe_smmu;
- buff = &input_smmu->dbuff_smmu;
- desc_ring_HWHEAD_pa =
- input_smmu->pipe_smmu.desc_ring_HWHEAD_pa;
- } else {
- pipe_info = &input->pipe;
- buff = &input->dbuff;
- desc_ring_HWHEAD_pa =
- input->pipe.desc_ring_HWHEAD_pa;
- }
- result = ipa3_wigig_config_gsi(false,
- is_smmu_enabled,
- pipe_info,
- buff,
- ep_gsi, ep);
- if (result)
- goto fail_gsi;
- result = ipa3_wigig_config_uc(
- true, false, wifi_ch,
- ep_gsi->ipa_gsi_chan_num,
- desc_ring_HWHEAD_pa);
- if (result)
- goto fail_uc_config;
- out->client = tx_client;
- ep->gsi_offload_state |= IPA_WIGIG_CONNECTED;
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- IPADBG("wigig client %d (ep %d) connected successfully\n", tx_client,
- ipa_ep_idx);
- return 0;
- fail_uc_config:
- /* Release channel and evt*/
- ipa3_release_gsi_channel(ipa_ep_idx);
- fail_gsi:
- if (input_smmu)
- ipa3_wigig_smmu_map_channel(false, &input_smmu->pipe_smmu,
- &input_smmu->dbuff_smmu, false);
- fail:
- ep->valid = 0;
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return result;
- }
- int ipa3_disconn_wigig_pipe_i(enum ipa_client_type client,
- struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu,
- void *dbuff)
- {
- bool is_smmu_enabled;
- int ipa_ep_idx;
- struct ipa3_ep_context *ep;
- const struct ipa_gsi_ep_config *ep_gsi;
- int result;
- bool rx = false;
- IPADBG("\n");
- ipa_ep_idx = ipa_get_ep_mapping(client);
- if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to get ep (%d) %d.\n",
- client, ipa_ep_idx);
- return -EFAULT;
- }
- ep = &ipa3_ctx->ep[ipa_ep_idx];
- if (!ep->valid) {
- IPAERR("Invalid EP\n");
- return -EFAULT;
- }
- ep_gsi = ipa3_get_gsi_ep_info(client);
- if (!ep_gsi) {
- IPAERR("Failed getting GSI EP info for client=%d\n",
- client);
- return -EFAULT;
- }
- if (ep->gsi_offload_state != IPA_WIGIG_CONNECTED) {
- IPAERR("client in bad state(client %d) 0x%X\n",
- client, ep->gsi_offload_state);
- return -EFAULT;
- }
- if (client == IPA_CLIENT_WIGIG_PROD)
- rx = true;
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- /* Release channel and evt*/
- result = ipa3_release_gsi_channel(ipa_ep_idx);
- if (result) {
- IPAERR("failed to deallocate channel\n");
- goto fail;
- }
- /* only gsi ch number and dir are necessary */
- result = ipa3_wigig_config_uc(
- false, rx, 0,
- ep_gsi->ipa_gsi_chan_num, 0);
- if (result) {
- IPAERR("failed uC channel teardown %d\n", result);
- WARN_ON(1);
- }
- is_smmu_enabled = !ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_11AD];
- if (is_smmu_enabled) {
- if (!pipe_smmu || !dbuff) {
- IPAERR("smmu input is null %pK %pK\n",
- pipe_smmu, dbuff);
- WARN_ON(1);
- } else {
- result = ipa3_wigig_smmu_map_channel(rx,
- pipe_smmu,
- dbuff,
- false);
- if (result) {
- IPAERR(
- "failed to unmap pipe smmu %d (ep %d)\n"
- , client, ipa_ep_idx);
- result = -EFAULT;
- goto fail;
- }
- }
- if (rx) {
- if (!list_empty(&smmu_reg_addr_list)) {
- IPAERR("smmu_reg_addr_list not empty\n");
- WARN_ON(1);
- }
- if (!list_empty(&smmu_ring_addr_list)) {
- IPAERR("smmu_ring_addr_list not empty\n");
- WARN_ON(1);
- }
- }
- } else if (pipe_smmu || dbuff) {
- IPAERR("smmu input is not null %pK %pK\n",
- pipe_smmu, dbuff);
- WARN_ON(1);
- }
- memset(ep, 0, sizeof(struct ipa3_ep_context));
- ep->gsi_offload_state = 0;
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- IPADBG("client (ep: %d) disconnected\n", ipa_ep_idx);
- IPADBG("exit\n");
- return 0;
- fail:
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- return result;
- }
- int ipa3_wigig_uc_msi_init(bool init,
- phys_addr_t periph_baddr_pa,
- phys_addr_t pseudo_cause_pa,
- phys_addr_t int_gen_tx_pa,
- phys_addr_t int_gen_rx_pa,
- phys_addr_t dma_ep_misc_pa)
- {
- int result;
- struct ipa_mem_buffer cmd;
- enum ipa_cpu_2_hw_offload_commands command;
- bool map = false;
- IPADBG("params: %s, %pa, %pa, %pa, %pa, %pa\n",
- init ? "init" : "deInit",
- &periph_baddr_pa,
- &pseudo_cause_pa,
- &int_gen_tx_pa,
- &int_gen_rx_pa,
- &dma_ep_misc_pa);
- /* first make sure registers are SMMU mapped if necessary*/
- if ((!ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC])) {
- if (init)
- map = true;
- IPADBG("SMMU enabled, map %d\n", map);
- result = ipa3_smmu_map_peer_reg(
- rounddown(pseudo_cause_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR(
- "failed to %s pseudo_cause reg %d\n",
- map ? "map" : "unmap",
- result);
- goto fail;
- }
- result = ipa3_smmu_map_peer_reg(
- rounddown(int_gen_tx_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR(
- "failed to %s int_gen_tx reg %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_gen_tx;
- }
- result = ipa3_smmu_map_peer_reg(
- rounddown(int_gen_rx_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR(
- "failed to %s int_gen_rx reg %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_gen_rx;
- }
- result = ipa3_smmu_map_peer_reg(
- rounddown(dma_ep_misc_pa, PAGE_SIZE),
- map,
- IPA_SMMU_CB_UC);
- if (result) {
- IPAERR(
- "failed to %s dma_ep_misc reg %d\n",
- map ? "map" : "unmap",
- result);
- goto fail_dma_ep_misc;
- }
- }
- /* now send the wigig hw base address to uC*/
- if (init) {
- struct IpaHwPeripheralInitCmdData_t *cmd_data;
- cmd.size = sizeof(*cmd_data);
- cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
- &cmd.phys_base, GFP_KERNEL);
- if (cmd.base == NULL) {
- IPAERR("fail to get DMA memory.\n");
- result = -ENOMEM;
- if (map)
- goto fail_alloc;
- return result;
- }
- cmd_data = (struct IpaHwPeripheralInitCmdData_t *)cmd.base;
- cmd_data->protocol = IPA_HW_PROTOCOL_11ad;
- cmd_data->Init_params.W11AdInit_params.periph_baddr_msb =
- IPA_WIGIG_MSB(periph_baddr_pa);
- cmd_data->Init_params.W11AdInit_params.periph_baddr_lsb =
- IPA_WIGIG_LSB(periph_baddr_pa);
- command = IPA_CPU_2_HW_CMD_PERIPHERAL_INIT;
- } else {
- struct IpaHwPeripheralDeinitCmdData_t *cmd_data;
- cmd.size = sizeof(*cmd_data);
- cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
- &cmd.phys_base, GFP_KERNEL);
- if (cmd.base == NULL) {
- IPAERR("fail to get DMA memory.\n");
- result = -ENOMEM;
- if (map)
- goto fail_alloc;
- return result;
- }
- cmd_data = (struct IpaHwPeripheralDeinitCmdData_t *)cmd.base;
- cmd_data->protocol = IPA_HW_PROTOCOL_11ad;
- command = IPA_CPU_2_HW_CMD_PERIPHERAL_DEINIT;
- }
- IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
- command,
- IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
- false, 10 * HZ);
- if (result) {
- IPAERR("fail to %s uc MSI config\n", init ? "init" : "deinit");
- goto fail_command;
- }
- dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size,
- cmd.base, cmd.phys_base);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- IPADBG("exit\n");
- return 0;
- fail_command:
- dma_free_coherent(ipa3_ctx->uc_pdev,
- cmd.size,
- cmd.base, cmd.phys_base);
- IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
- fail_alloc:
- ipa3_smmu_map_peer_reg(
- rounddown(dma_ep_misc_pa, PAGE_SIZE), !map, IPA_SMMU_CB_UC);
- fail_dma_ep_misc:
- ipa3_smmu_map_peer_reg(
- rounddown(int_gen_rx_pa, PAGE_SIZE), !map, IPA_SMMU_CB_UC);
- fail_gen_rx:
- ipa3_smmu_map_peer_reg(
- rounddown(int_gen_tx_pa, PAGE_SIZE), !map, IPA_SMMU_CB_UC);
- fail_gen_tx:
- ipa3_smmu_map_peer_reg(
- rounddown(pseudo_cause_pa, PAGE_SIZE), !map, IPA_SMMU_CB_UC);
- fail:
- return result;
- }
- int ipa3_enable_wigig_pipe_i(enum ipa_client_type client)
- {
- int ipa_ep_idx, res;
- struct ipa3_ep_context *ep;
- struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
- int retry_cnt = 0;
- uint64_t val;
- IPADBG("\n");
- ipa_ep_idx = ipa_get_ep_mapping(client);
- if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to get ep (%d) %d.\n",
- client, ipa_ep_idx);
- return -EFAULT;
- }
- ep = &ipa3_ctx->ep[ipa_ep_idx];
- if (!ep->valid) {
- IPAERR("Invalid EP\n");
- return -EFAULT;
- }
- if (ep->gsi_offload_state != IPA_WIGIG_CONNECTED) {
- IPAERR("WIGIG channel bad state 0x%X\n",
- ep->gsi_offload_state);
- return -EFAULT;
- }
- IPA_ACTIVE_CLIENTS_INC_EP(client);
- res = ipa3_enable_data_path(ipa_ep_idx);
- if (res)
- goto fail_enable_datapath;
- memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
- ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl);
- /* ring the event db (outside the ring boundary)*/
- val = ep->gsi_mem_info.evt_ring_base_addr +
- ep->gsi_mem_info.evt_ring_len;
- res = gsi_ring_evt_ring_db(ep->gsi_evt_ring_hdl, val);
- if (res) {
- IPAERR(
- "fail to ring evt ring db %d. hdl=%lu wp=0x%llx\n"
- , res, ep->gsi_evt_ring_hdl,
- (unsigned long long)val);
- res = -EFAULT;
- goto fail_ring_evt;
- }
- IPADBG("start channel\n");
- res = gsi_start_channel(ep->gsi_chan_hdl);
- if (res != GSI_STATUS_SUCCESS) {
- IPAERR("gsi_start_channel failed %d\n", res);
- WARN_ON(1);
- res = -EFAULT;
- goto fail_gsi_start;
- }
- /* for TX we have to ring the channel db (last desc in the ring) */
- if (client != IPA_CLIENT_WIGIG_PROD) {
- uint64_t val;
- val = ep->gsi_mem_info.chan_ring_base_addr +
- ep->gsi_mem_info.chan_ring_len -
- IPA_WIGIG_DESC_RING_EL_SIZE;
- IPADBG("ring ch doorbell (0x%llX) TX %ld\n", val,
- ep->gsi_chan_hdl);
- res = gsi_ring_ch_ring_db(ep->gsi_chan_hdl, val);
- if (res) {
- IPAERR(
- "fail to ring channel db %d. hdl=%lu wp=0x%llx\n"
- , res, ep->gsi_chan_hdl,
- (unsigned long long)val);
- res = -EFAULT;
- goto fail_ring_ch;
- }
- }
- ep->gsi_offload_state |= IPA_WIGIG_ENABLED;
- IPADBG("exit\n");
- return 0;
- fail_ring_ch:
- res = ipa3_stop_gsi_channel(ipa_ep_idx);
- if (res != 0 && res != -GSI_STATUS_AGAIN &&
- res != -GSI_STATUS_TIMED_OUT) {
- IPAERR("failed to stop channel res = %d\n", res);
- } else if (res == -GSI_STATUS_AGAIN) {
- IPADBG("GSI stop channel failed retry cnt = %d\n",
- retry_cnt);
- retry_cnt++;
- if (retry_cnt < GSI_STOP_MAX_RETRY_CNT)
- goto fail_ring_ch;
- } else {
- IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl);
- }
- res = -EFAULT;
- fail_gsi_start:
- fail_ring_evt:
- ipa3_disable_data_path(ipa_ep_idx);
- fail_enable_datapath:
- IPA_ACTIVE_CLIENTS_DEC_EP(client);
- return res;
- }
- int ipa3_disable_wigig_pipe_i(enum ipa_client_type client)
- {
- int ipa_ep_idx, res;
- struct ipa3_ep_context *ep;
- struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 };
- struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
- bool disable_force_clear = false;
- u32 source_pipe_bitmask = 0;
- int retry_cnt = 0;
- IPADBG("\n");
- ipa_ep_idx = ipa_get_ep_mapping(client);
- if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED ||
- ipa_ep_idx >= IPA3_MAX_NUM_PIPES) {
- IPAERR("fail to get ep (%d) %d.\n",
- client, ipa_ep_idx);
- return -EFAULT;
- }
- if (ipa_ep_idx >= IPA3_MAX_NUM_PIPES) {
- IPAERR("ep %d out of range.\n", ipa_ep_idx);
- return -EFAULT;
- }
- ep = &ipa3_ctx->ep[ipa_ep_idx];
- if (!ep->valid) {
- IPAERR("Invalid EP\n");
- return -EFAULT;
- }
- if (ep->gsi_offload_state !=
- (IPA_WIGIG_CONNECTED | IPA_WIGIG_ENABLED)) {
- IPAERR("WIGIG channel bad state 0x%X\n",
- ep->gsi_offload_state);
- return -EFAULT;
- }
- IPADBG("pipe %d\n", ipa_ep_idx);
- source_pipe_bitmask = 1 << ipa_ep_idx;
- res = ipa3_enable_force_clear(ipa_ep_idx,
- false, source_pipe_bitmask);
- if (res) {
- /*
- * assuming here modem SSR, AP can remove
- * the delay in this case
- */
- IPAERR("failed to force clear %d\n", res);
- IPAERR("remove delay from SCND reg\n");
- ep_ctrl_scnd.endp_delay = false;
- ipahal_write_reg_n_fields(
- IPA_ENDP_INIT_CTRL_SCND_n, ipa_ep_idx,
- &ep_ctrl_scnd);
- } else {
- disable_force_clear = true;
- }
- retry_gsi_stop:
- res = ipa3_stop_gsi_channel(ipa_ep_idx);
- if (res != 0 && res != -GSI_STATUS_AGAIN &&
- res != -GSI_STATUS_TIMED_OUT) {
- IPAERR("failed to stop channel res = %d\n", res);
- goto fail_stop_channel;
- } else if (res == -GSI_STATUS_AGAIN) {
- IPADBG("GSI stop channel failed retry cnt = %d\n",
- retry_cnt);
- retry_cnt++;
- if (retry_cnt >= GSI_STOP_MAX_RETRY_CNT)
- goto fail_stop_channel;
- goto retry_gsi_stop;
- } else {
- IPADBG("GSI channel %ld STOP\n", ep->gsi_chan_hdl);
- }
- res = ipa3_reset_gsi_channel(ipa_ep_idx);
- if (res != GSI_STATUS_SUCCESS) {
- IPAERR("Failed to reset chan: %d.\n", res);
- goto fail_stop_channel;
- }
- if (disable_force_clear)
- ipa3_disable_force_clear(ipa_ep_idx);
- res = ipa3_disable_data_path(ipa_ep_idx);
- if (res) {
- WARN_ON(1);
- return res;
- }
- /* Set the delay after disabling IPA Producer pipe */
- if (IPA_CLIENT_IS_PROD(ep->client)) {
- memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
- ep_cfg_ctrl.ipa_ep_delay = true;
- ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl);
- }
- ep->gsi_offload_state &= ~IPA_WIGIG_ENABLED;
- IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(ipa_ep_idx));
- IPADBG("exit\n");
- return 0;
- fail_stop_channel:
- ipa_assert();
- return res;
- }
- #ifndef CONFIG_DEBUG_FS
- int ipa3_wigig_init_debugfs_i(struct dentry *parent) { return 0; }
- #else
- int ipa3_wigig_init_debugfs_i(struct dentry *parent)
- {
- const mode_t read_write_mode = 0664;
- struct dentry *file = NULL;
- struct dentry *dent;
- dent = debugfs_create_dir("ipa_wigig", parent);
- if (IS_ERR_OR_NULL(dent)) {
- IPAERR("fail to create folder in debug_fs\n");
- return -EFAULT;
- }
- wigig_dent = dent;
- file = debugfs_create_u8("modc", read_write_mode, dent,
- &int_modc);
- if (IS_ERR_OR_NULL(file)) {
- IPAERR("fail to create file modc\n");
- goto fail;
- }
- file = debugfs_create_u16("modt", read_write_mode, dent,
- &int_modt);
- if (IS_ERR_OR_NULL(file)) {
- IPAERR("fail to create file modt\n");
- goto fail;
- }
- file = debugfs_create_u8("rx_mod_th", read_write_mode, dent,
- &rx_hwtail_mod_threshold);
- if (IS_ERR_OR_NULL(file)) {
- IPAERR("fail to create file rx_mod_th\n");
- goto fail;
- }
- file = debugfs_create_u8("tx_mod_th", read_write_mode, dent,
- &tx_hwtail_mod_threshold);
- if (IS_ERR_OR_NULL(file)) {
- IPAERR("fail to create file tx_mod_th\n");
- goto fail;
- }
- return 0;
- fail:
- debugfs_remove_recursive(dent);
- wigig_dent = NULL;
- return -EFAULT;
- }
- #endif
|