ipa_wigig.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/ipa_wigig.h>
  6. #include <linux/string.h>
  7. #include "../ipa_common_i.h"
  8. #include "../ipa_v3/ipa_pm.h"
  9. #define OFFLOAD_DRV_NAME "ipa_wigig"
  10. #define IPA_WIGIG_DBG(fmt, args...) \
  11. do { \
  12. pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
  13. __func__, __LINE__, ## args); \
  14. IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
  15. OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
  16. IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
  17. OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
  18. } while (0)
  19. #define IPA_WIGIG_DBG_LOW(fmt, args...) \
  20. do { \
  21. pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
  22. __func__, __LINE__, ## args); \
  23. IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
  24. OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
  25. } while (0)
  26. #define IPA_WIGIG_ERR(fmt, args...) \
  27. do { \
  28. pr_err(OFFLOAD_DRV_NAME " %s:%d " fmt, \
  29. __func__, __LINE__, ## args); \
  30. IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
  31. OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
  32. IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
  33. OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
  34. } while (0)
  35. #define IPA_WIGIG_ERR_RL(fmt, args...) \
  36. do { \
  37. pr_err_ratelimited_ipa( \
  38. OFFLOAD_DRV_NAME " %s:%d " fmt, __func__,\
  39. __LINE__, ## args);\
  40. IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
  41. OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
  42. } while (0)
  43. #define IPA_WIGIG_TX_PIPE_NUM 4
  44. enum ipa_wigig_pipes_idx {
  45. IPA_CLIENT_WIGIG_PROD_IDX = 0,
  46. IPA_CLIENT_WIGIG1_CONS_IDX = 1,
  47. IPA_CLIENT_WIGIG2_CONS_IDX = 2,
  48. IPA_CLIENT_WIGIG3_CONS_IDX = 3,
  49. IPA_CLIENT_WIGIG4_CONS_IDX = 4,
  50. IPA_WIGIG_MAX_PIPES
  51. };
  52. struct ipa_wigig_intf_info {
  53. char netdev_name[IPA_RESOURCE_NAME_MAX];
  54. u8 netdev_mac[IPA_MAC_ADDR_SIZE];
  55. u8 hdr_len;
  56. u32 partial_hdr_hdl[IPA_IP_MAX];
  57. struct list_head link;
  58. };
  59. struct ipa_wigig_pipe_values {
  60. uint8_t dir;
  61. uint8_t tx_ring_id;
  62. uint32_t desc_ring_HWHEAD;
  63. uint32_t desc_ring_HWTAIL;
  64. uint32_t status_ring_HWHEAD;
  65. uint32_t status_ring_HWTAIL;
  66. };
  67. struct ipa_wigig_regs_save {
  68. struct ipa_wigig_pipe_values pipes_val[IPA_WIGIG_MAX_PIPES];
  69. u32 int_gen_tx_val;
  70. u32 int_gen_rx_val;
  71. };
  72. struct ipa_wigig_context {
  73. struct list_head head_intf_list;
  74. struct mutex lock;
  75. u32 ipa_pm_hdl;
  76. phys_addr_t periph_baddr_pa;
  77. phys_addr_t pseudo_cause_pa;
  78. phys_addr_t int_gen_tx_pa;
  79. phys_addr_t int_gen_rx_pa;
  80. phys_addr_t dma_ep_misc_pa;
  81. union pipes {
  82. struct ipa_wigig_pipe_setup_info flat[IPA_WIGIG_MAX_PIPES];
  83. struct ipa_wigig_pipe_setup_info_smmu
  84. smmu[IPA_WIGIG_MAX_PIPES];
  85. } pipes;
  86. struct ipa_wigig_rx_pipe_data_buffer_info_smmu rx_buff_smmu;
  87. struct ipa_wigig_tx_pipe_data_buffer_info_smmu
  88. tx_buff_smmu[IPA_WIGIG_TX_PIPE_NUM];
  89. char clients_mac[IPA_WIGIG_TX_PIPE_NUM][IPA_MAC_ADDR_SIZE];
  90. struct ipa_wigig_regs_save regs_save;
  91. bool smmu_en;
  92. bool shared_cb;
  93. u8 conn_pipes;
  94. };
  95. static struct ipa_wigig_context *ipa_wigig_ctx;
  96. int ipa_wigig_init(struct ipa_wigig_init_in_params *in,
  97. struct ipa_wigig_init_out_params *out)
  98. {
  99. struct ipa_wdi_uc_ready_params inout;
  100. if (!in || !out) {
  101. IPA_WIGIG_ERR("invalid params in=%pK, out %pK\n", in, out);
  102. return -EINVAL;
  103. }
  104. IPA_WIGIG_DBG("\n");
  105. if (ipa_wigig_ctx) {
  106. IPA_WIGIG_ERR("ipa_wigig_ctx was initialized before\n");
  107. return -EINVAL;
  108. }
  109. ipa_wigig_ctx = kzalloc(sizeof(*ipa_wigig_ctx), GFP_KERNEL);
  110. if (ipa_wigig_ctx == NULL)
  111. return -ENOMEM;
  112. mutex_init(&ipa_wigig_ctx->lock);
  113. INIT_LIST_HEAD(&ipa_wigig_ctx->head_intf_list);
  114. ipa_wigig_ctx->pseudo_cause_pa = in->pseudo_cause_pa;
  115. ipa_wigig_ctx->int_gen_tx_pa = in->int_gen_tx_pa;
  116. ipa_wigig_ctx->int_gen_rx_pa = in->int_gen_rx_pa;
  117. ipa_wigig_ctx->dma_ep_misc_pa = in->dma_ep_misc_pa;
  118. ipa_wigig_ctx->periph_baddr_pa = in->periph_baddr_pa;
  119. IPA_WIGIG_DBG(
  120. "periph_baddr_pa 0x%pa pseudo_cause_pa 0x%pa, int_gen_tx_pa 0x%pa, int_gen_rx_pa 0x%pa, dma_ep_misc_pa 0x%pa"
  121. , &ipa_wigig_ctx->periph_baddr_pa,
  122. &ipa_wigig_ctx->pseudo_cause_pa,
  123. &ipa_wigig_ctx->int_gen_tx_pa,
  124. &ipa_wigig_ctx->int_gen_rx_pa,
  125. &ipa_wigig_ctx->dma_ep_misc_pa);
  126. inout.notify = in->notify;
  127. inout.priv = in->priv;
  128. if (ipa_wigig_uc_init(&inout, in->int_notify, &out->uc_db_pa)) {
  129. kfree(ipa_wigig_ctx);
  130. ipa_wigig_ctx = NULL;
  131. return -EFAULT;
  132. }
  133. IPA_WIGIG_DBG("uc_db_pa 0x%pa\n", &out->uc_db_pa);
  134. out->is_uc_ready = inout.is_uC_ready;
  135. IPA_WIGIG_DBG("exit\n");
  136. return 0;
  137. }
  138. EXPORT_SYMBOL(ipa_wigig_init);
  139. int ipa_wigig_cleanup(void)
  140. {
  141. struct ipa_wigig_intf_info *entry;
  142. struct ipa_wigig_intf_info *next;
  143. IPA_WIGIG_DBG("\n");
  144. if (!ipa_wigig_ctx)
  145. return -ENODEV;
  146. /* clear interface list */
  147. list_for_each_entry_safe(entry, next,
  148. &ipa_wigig_ctx->head_intf_list, link) {
  149. list_del(&entry->link);
  150. kfree(entry);
  151. }
  152. mutex_destroy(&ipa_wigig_ctx->lock);
  153. kfree(ipa_wigig_ctx);
  154. ipa_wigig_ctx = NULL;
  155. IPA_WIGIG_DBG("exit\n");
  156. return 0;
  157. }
  158. EXPORT_SYMBOL(ipa_wigig_cleanup);
  159. bool ipa_wigig_is_smmu_enabled(void)
  160. {
  161. struct ipa_smmu_in_params in;
  162. struct ipa_smmu_out_params out;
  163. IPA_WIGIG_DBG("\n");
  164. in.smmu_client = IPA_SMMU_WIGIG_CLIENT;
  165. ipa_get_smmu_params(&in, &out);
  166. IPA_WIGIG_DBG("exit (%d)\n", out.smmu_enable);
  167. return out.smmu_enable;
  168. }
  169. EXPORT_SYMBOL(ipa_wigig_is_smmu_enabled);
  170. static int ipa_wigig_init_smmu_params(void)
  171. {
  172. struct ipa_smmu_in_params in;
  173. struct ipa_smmu_out_params out;
  174. int ret;
  175. IPA_WIGIG_DBG("\n");
  176. in.smmu_client = IPA_SMMU_WIGIG_CLIENT;
  177. ret = ipa_get_smmu_params(&in, &out);
  178. if (ret) {
  179. IPA_WIGIG_ERR("couldn't get SMMU params %d\n", ret);
  180. return ret;
  181. }
  182. ipa_wigig_ctx->smmu_en = out.smmu_enable;
  183. ipa_wigig_ctx->shared_cb = out.shared_cb;
  184. IPA_WIGIG_DBG("SMMU (%s), 11ad CB (%s)\n",
  185. out.smmu_enable ? "enabled" : "disabled",
  186. out.shared_cb ? "shared" : "not shared");
  187. return 0;
  188. }
  189. static int ipa_wigig_commit_partial_hdr(
  190. struct ipa_ioc_add_hdr *hdr,
  191. const char *netdev_name,
  192. struct ipa_wigig_hdr_info *hdr_info)
  193. {
  194. int i;
  195. IPA_WIGIG_DBG("\n");
  196. if (!netdev_name) {
  197. IPA_WIGIG_ERR("Invalid input\n");
  198. return -EINVAL;
  199. }
  200. IPA_WIGIG_DBG("dst_mac_addr_offset %d hdr_len %d hdr_type %d\n",
  201. hdr_info->dst_mac_addr_offset,
  202. hdr_info->hdr_len,
  203. hdr_info->hdr_type);
  204. hdr->commit = 1;
  205. hdr->num_hdrs = 2;
  206. snprintf(hdr->hdr[0].name, sizeof(hdr->hdr[0].name),
  207. "%s_ipv4", netdev_name);
  208. snprintf(hdr->hdr[1].name, sizeof(hdr->hdr[1].name),
  209. "%s_ipv6", netdev_name);
  210. for (i = IPA_IP_v4; i < IPA_IP_MAX; i++) {
  211. hdr->hdr[i].hdr_len = hdr_info[i].hdr_len;
  212. memcpy(hdr->hdr[i].hdr, hdr_info[i].hdr, hdr->hdr[i].hdr_len);
  213. hdr->hdr[i].type = hdr_info[i].hdr_type;
  214. hdr->hdr[i].is_partial = 1;
  215. hdr->hdr[i].is_eth2_ofst_valid = 1;
  216. hdr->hdr[i].eth2_ofst = hdr_info[i].dst_mac_addr_offset;
  217. }
  218. if (ipa_add_hdr(hdr)) {
  219. IPA_WIGIG_ERR("fail to add partial headers\n");
  220. return -EFAULT;
  221. }
  222. IPA_WIGIG_DBG("exit\n");
  223. return 0;
  224. }
  225. static void ipa_wigig_free_msg(void *msg, uint32_t len, uint32_t type)
  226. {
  227. IPA_WIGIG_DBG("free msg type:%d, len:%d, buff %pK", type, len, msg);
  228. kfree(msg);
  229. IPA_WIGIG_DBG("exit\n");
  230. }
  231. static int ipa_wigig_send_wlan_msg(enum ipa_wlan_event msg_type,
  232. const char *netdev_name, u8 *mac)
  233. {
  234. struct ipa_msg_meta msg_meta;
  235. struct ipa_wlan_msg *wlan_msg;
  236. int ret;
  237. IPA_WIGIG_DBG("%d\n", msg_type);
  238. wlan_msg = kzalloc(sizeof(*wlan_msg), GFP_KERNEL);
  239. if (wlan_msg == NULL)
  240. return -ENOMEM;
  241. strlcpy(wlan_msg->name, netdev_name, IPA_RESOURCE_NAME_MAX);
  242. memcpy(wlan_msg->mac_addr, mac, IPA_MAC_ADDR_SIZE);
  243. msg_meta.msg_len = sizeof(struct ipa_wlan_msg);
  244. msg_meta.msg_type = msg_type;
  245. IPA_WIGIG_DBG("send msg type:%d, len:%d, buff %pK", msg_meta.msg_type,
  246. msg_meta.msg_len, wlan_msg);
  247. ret = ipa_send_msg(&msg_meta, wlan_msg, ipa_wigig_free_msg);
  248. IPA_WIGIG_DBG("exit\n");
  249. return ret;
  250. }
  251. int ipa_wigig_send_msg(int msg_type,
  252. const char *netdev_name, u8 *mac,
  253. enum ipa_client_type client, bool to_wigig)
  254. {
  255. struct ipa_msg_meta msg_meta;
  256. struct ipa_wigig_msg *wigig_msg;
  257. int ret;
  258. IPA_WIGIG_DBG("\n");
  259. wigig_msg = kzalloc(sizeof(struct ipa_wigig_msg), GFP_KERNEL);
  260. if (wigig_msg == NULL)
  261. return -ENOMEM;
  262. strlcpy(wigig_msg->name, netdev_name, IPA_RESOURCE_NAME_MAX);
  263. memcpy(wigig_msg->client_mac_addr, mac, IPA_MAC_ADDR_SIZE);
  264. if (msg_type == WIGIG_CLIENT_CONNECT)
  265. wigig_msg->u.ipa_client = client;
  266. else
  267. wigig_msg->u.to_wigig = to_wigig;
  268. msg_meta.msg_type = msg_type;
  269. msg_meta.msg_len = sizeof(struct ipa_wigig_msg);
  270. IPA_WIGIG_DBG("send msg type:%d, len:%d, buff %pK", msg_meta.msg_type,
  271. msg_meta.msg_len, wigig_msg);
  272. ret = ipa_send_msg(&msg_meta, wigig_msg, ipa_wigig_free_msg);
  273. IPA_WIGIG_DBG("exit\n");
  274. return ret;
  275. }
  276. static int ipa_wigig_get_devname(char *netdev_name)
  277. {
  278. struct ipa_wigig_intf_info *entry;
  279. mutex_lock(&ipa_wigig_ctx->lock);
  280. if (!list_is_singular(&ipa_wigig_ctx->head_intf_list)) {
  281. IPA_WIGIG_DBG("list is not singular, was an IF registered?\n");
  282. mutex_unlock(&ipa_wigig_ctx->lock);
  283. return -EFAULT;
  284. }
  285. entry = list_first_entry(&ipa_wigig_ctx->head_intf_list,
  286. struct ipa_wigig_intf_info,
  287. link);
  288. strlcpy(netdev_name, entry->netdev_name, IPA_RESOURCE_NAME_MAX);
  289. mutex_unlock(&ipa_wigig_ctx->lock);
  290. return 0;
  291. }
  292. int ipa_wigig_reg_intf(
  293. struct ipa_wigig_reg_intf_in_params *in)
  294. {
  295. struct ipa_wigig_intf_info *new_intf;
  296. struct ipa_wigig_intf_info *entry;
  297. struct ipa_tx_intf tx;
  298. struct ipa_rx_intf rx;
  299. struct ipa_ioc_tx_intf_prop tx_prop[2];
  300. struct ipa_ioc_rx_intf_prop rx_prop[2];
  301. struct ipa_ioc_add_hdr *hdr;
  302. struct ipa_ioc_del_hdr *del_hdr = NULL;
  303. u32 len;
  304. int ret = 0;
  305. IPA_WIGIG_DBG("\n");
  306. if (in == NULL) {
  307. IPA_WIGIG_ERR("invalid params in=%pK\n", in);
  308. return -EINVAL;
  309. }
  310. if (!ipa_wigig_ctx) {
  311. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  312. return -EPERM;
  313. }
  314. IPA_WIGIG_DBG(
  315. "register interface for netdev %s, MAC 0x[%X][%X][%X][%X][%X][%X]\n"
  316. , in->netdev_name,
  317. in->netdev_mac[0], in->netdev_mac[1], in->netdev_mac[2],
  318. in->netdev_mac[3], in->netdev_mac[4], in->netdev_mac[5]);
  319. mutex_lock(&ipa_wigig_ctx->lock);
  320. list_for_each_entry(entry, &ipa_wigig_ctx->head_intf_list, link)
  321. if (strcmp(entry->netdev_name, in->netdev_name) == 0) {
  322. IPA_WIGIG_DBG("intf was added before.\n");
  323. mutex_unlock(&ipa_wigig_ctx->lock);
  324. return 0;
  325. }
  326. IPA_WIGIG_DBG("intf was not added before, proceed.\n");
  327. new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
  328. if (new_intf == NULL) {
  329. ret = -ENOMEM;
  330. goto fail;
  331. }
  332. INIT_LIST_HEAD(&new_intf->link);
  333. strlcpy(new_intf->netdev_name, in->netdev_name,
  334. sizeof(new_intf->netdev_name));
  335. new_intf->hdr_len = in->hdr_info[0].hdr_len;
  336. memcpy(new_intf->netdev_mac, in->netdev_mac, IPA_MAC_ADDR_SIZE);
  337. /* add partial header */
  338. len = sizeof(struct ipa_ioc_add_hdr) + 2 * sizeof(struct ipa_hdr_add);
  339. hdr = kzalloc(len, GFP_KERNEL);
  340. if (hdr == NULL) {
  341. ret = -EFAULT;
  342. goto fail_alloc_hdr;
  343. }
  344. if (ipa_wigig_commit_partial_hdr(hdr,
  345. in->netdev_name,
  346. in->hdr_info)) {
  347. IPA_WIGIG_ERR("fail to commit partial headers\n");
  348. ret = -EFAULT;
  349. goto fail_commit_hdr;
  350. }
  351. new_intf->partial_hdr_hdl[IPA_IP_v4] = hdr->hdr[IPA_IP_v4].hdr_hdl;
  352. new_intf->partial_hdr_hdl[IPA_IP_v6] = hdr->hdr[IPA_IP_v6].hdr_hdl;
  353. IPA_WIGIG_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
  354. hdr->hdr[IPA_IP_v4].hdr_hdl, hdr->hdr[IPA_IP_v6].hdr_hdl);
  355. /* populate tx prop */
  356. tx.num_props = 2;
  357. tx.prop = tx_prop;
  358. memset(tx_prop, 0, sizeof(tx_prop));
  359. tx_prop[0].ip = IPA_IP_v4;
  360. /*
  361. * for consumers, we register a default pipe, but IPACM will determine
  362. * the actual pipe according to the relevant client MAC
  363. */
  364. tx_prop[0].dst_pipe = IPA_CLIENT_WIGIG1_CONS;
  365. tx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
  366. strlcpy(tx_prop[0].hdr_name, hdr->hdr[IPA_IP_v4].name,
  367. sizeof(tx_prop[0].hdr_name));
  368. tx_prop[1].ip = IPA_IP_v6;
  369. tx_prop[1].dst_pipe = IPA_CLIENT_WIGIG1_CONS;
  370. tx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
  371. strlcpy(tx_prop[1].hdr_name, hdr->hdr[IPA_IP_v6].name,
  372. sizeof(tx_prop[1].hdr_name));
  373. /* populate rx prop */
  374. rx.num_props = 2;
  375. rx.prop = rx_prop;
  376. memset(rx_prop, 0, sizeof(rx_prop));
  377. rx_prop[0].ip = IPA_IP_v4;
  378. rx_prop[0].src_pipe = IPA_CLIENT_WIGIG_PROD;
  379. rx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
  380. rx_prop[1].ip = IPA_IP_v6;
  381. rx_prop[1].src_pipe = IPA_CLIENT_WIGIG_PROD;
  382. rx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
  383. if (ipa_register_intf(in->netdev_name, &tx, &rx)) {
  384. IPA_WIGIG_ERR("fail to add interface prop\n");
  385. ret = -EFAULT;
  386. goto fail_register;
  387. }
  388. if (ipa_wigig_send_wlan_msg(WLAN_AP_CONNECT,
  389. in->netdev_name,
  390. in->netdev_mac)) {
  391. IPA_WIGIG_ERR("couldn't send msg to IPACM\n");
  392. ret = -EFAULT;
  393. goto fail_sendmsg;
  394. }
  395. list_add(&new_intf->link, &ipa_wigig_ctx->head_intf_list);
  396. kfree(hdr);
  397. mutex_unlock(&ipa_wigig_ctx->lock);
  398. IPA_WIGIG_DBG("exit\n");
  399. return 0;
  400. fail_sendmsg:
  401. ipa_deregister_intf(in->netdev_name);
  402. fail_register:
  403. del_hdr = kzalloc(sizeof(struct ipa_ioc_del_hdr) +
  404. 2 * sizeof(struct ipa_hdr_del), GFP_KERNEL);
  405. if (del_hdr) {
  406. del_hdr->commit = 1;
  407. del_hdr->num_hdls = 2;
  408. del_hdr->hdl[0].hdl = new_intf->partial_hdr_hdl[IPA_IP_v4];
  409. del_hdr->hdl[1].hdl = new_intf->partial_hdr_hdl[IPA_IP_v6];
  410. ipa_del_hdr(del_hdr);
  411. kfree(del_hdr);
  412. }
  413. new_intf->partial_hdr_hdl[IPA_IP_v4] = 0;
  414. new_intf->partial_hdr_hdl[IPA_IP_v6] = 0;
  415. fail_commit_hdr:
  416. kfree(hdr);
  417. fail_alloc_hdr:
  418. kfree(new_intf);
  419. fail:
  420. mutex_unlock(&ipa_wigig_ctx->lock);
  421. return ret;
  422. }
  423. EXPORT_SYMBOL(ipa_wigig_reg_intf);
  424. int ipa_wigig_dereg_intf(const char *netdev_name)
  425. {
  426. int len, ret;
  427. struct ipa_ioc_del_hdr *hdr = NULL;
  428. struct ipa_wigig_intf_info *entry;
  429. struct ipa_wigig_intf_info *next;
  430. if (!netdev_name) {
  431. IPA_WIGIG_ERR("no netdev name\n");
  432. return -EINVAL;
  433. }
  434. IPA_WIGIG_DBG("netdev %s\n", netdev_name);
  435. if (!ipa_wigig_ctx) {
  436. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  437. return -EPERM;
  438. }
  439. mutex_lock(&ipa_wigig_ctx->lock);
  440. ret = -EFAULT;
  441. list_for_each_entry_safe(entry, next, &ipa_wigig_ctx->head_intf_list,
  442. link)
  443. if (strcmp(entry->netdev_name, netdev_name) == 0) {
  444. len = sizeof(struct ipa_ioc_del_hdr) +
  445. 2 * sizeof(struct ipa_hdr_del);
  446. hdr = kzalloc(len, GFP_KERNEL);
  447. if (hdr == NULL) {
  448. mutex_unlock(&ipa_wigig_ctx->lock);
  449. return -ENOMEM;
  450. }
  451. hdr->commit = 1;
  452. hdr->num_hdls = 2;
  453. hdr->hdl[0].hdl = entry->partial_hdr_hdl[0];
  454. hdr->hdl[1].hdl = entry->partial_hdr_hdl[1];
  455. IPA_WIGIG_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
  456. hdr->hdl[0].hdl, hdr->hdl[1].hdl);
  457. if (ipa_del_hdr(hdr)) {
  458. IPA_WIGIG_ERR(
  459. "fail to delete partial header\n");
  460. ret = -EFAULT;
  461. goto fail;
  462. }
  463. if (ipa_deregister_intf(entry->netdev_name)) {
  464. IPA_WIGIG_ERR("fail to del interface props\n");
  465. ret = -EFAULT;
  466. goto fail;
  467. }
  468. if (ipa_wigig_send_wlan_msg(WLAN_AP_DISCONNECT,
  469. entry->netdev_name,
  470. entry->netdev_mac)) {
  471. IPA_WIGIG_ERR("couldn't send msg to IPACM\n");
  472. ret = -EFAULT;
  473. goto fail;
  474. }
  475. list_del(&entry->link);
  476. kfree(entry);
  477. ret = 0;
  478. break;
  479. }
  480. IPA_WIGIG_DBG("exit\n");
  481. fail:
  482. kfree(hdr);
  483. mutex_unlock(&ipa_wigig_ctx->lock);
  484. return ret;
  485. }
  486. EXPORT_SYMBOL(ipa_wigig_dereg_intf);
  487. static void ipa_wigig_pm_cb(void *p, enum ipa_pm_cb_event event)
  488. {
  489. IPA_WIGIG_DBG("received pm event %d\n", event);
  490. }
  491. static int ipa_wigig_store_pipe_info(struct ipa_wigig_pipe_setup_info *pipe,
  492. unsigned int idx)
  493. {
  494. IPA_WIGIG_DBG(
  495. "idx %d: desc_ring HWHEAD_pa %pa, HWTAIL_pa %pa, status_ring HWHEAD_pa %pa, HWTAIL_pa %pa\n",
  496. idx,
  497. &pipe->desc_ring_HWHEAD_pa,
  498. &pipe->desc_ring_HWTAIL_pa,
  499. &pipe->status_ring_HWHEAD_pa,
  500. &pipe->status_ring_HWTAIL_pa);
  501. /* store regs */
  502. ipa_wigig_ctx->pipes.flat[idx].desc_ring_HWHEAD_pa =
  503. pipe->desc_ring_HWHEAD_pa;
  504. ipa_wigig_ctx->pipes.flat[idx].desc_ring_HWTAIL_pa =
  505. pipe->desc_ring_HWTAIL_pa;
  506. ipa_wigig_ctx->pipes.flat[idx].status_ring_HWHEAD_pa =
  507. pipe->status_ring_HWHEAD_pa;
  508. ipa_wigig_ctx->pipes.flat[idx].status_ring_HWTAIL_pa =
  509. pipe->status_ring_HWTAIL_pa;
  510. IPA_WIGIG_DBG("exit\n");
  511. return 0;
  512. }
  513. static u8 ipa_wigig_pipe_to_bit_val(int client)
  514. {
  515. u8 shift_val;
  516. switch (client) {
  517. case IPA_CLIENT_WIGIG_PROD:
  518. shift_val = 0x1 << IPA_CLIENT_WIGIG_PROD_IDX;
  519. break;
  520. case IPA_CLIENT_WIGIG1_CONS:
  521. shift_val = 0x1 << IPA_CLIENT_WIGIG1_CONS_IDX;
  522. break;
  523. case IPA_CLIENT_WIGIG2_CONS:
  524. shift_val = 0x1 << IPA_CLIENT_WIGIG2_CONS_IDX;
  525. break;
  526. case IPA_CLIENT_WIGIG3_CONS:
  527. shift_val = 0x1 << IPA_CLIENT_WIGIG3_CONS_IDX;
  528. break;
  529. case IPA_CLIENT_WIGIG4_CONS:
  530. shift_val = 0x1 << IPA_CLIENT_WIGIG4_CONS_IDX;
  531. break;
  532. default:
  533. IPA_WIGIG_ERR("invalid pipe %d\n", client);
  534. return 1;
  535. }
  536. return shift_val;
  537. }
  538. int ipa_wigig_conn_rx_pipe(struct ipa_wigig_conn_rx_in_params *in,
  539. struct ipa_wigig_conn_out_params *out)
  540. {
  541. int ret;
  542. struct ipa_pm_register_params pm_params;
  543. IPA_WIGIG_DBG("\n");
  544. if (!in || !out) {
  545. IPA_WIGIG_ERR("empty parameters. in=%pK out=%pK\n", in, out);
  546. return -EINVAL;
  547. }
  548. if (!ipa_wigig_ctx) {
  549. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  550. return -EPERM;
  551. }
  552. ret = ipa_uc_state_check();
  553. if (ret) {
  554. IPA_WIGIG_ERR("uC not ready\n");
  555. return ret;
  556. }
  557. if (ipa_wigig_init_smmu_params())
  558. return -EINVAL;
  559. if (ipa_wigig_ctx->smmu_en) {
  560. IPA_WIGIG_ERR("IPA SMMU is enabled, wrong API used\n");
  561. return -EFAULT;
  562. }
  563. memset(&pm_params, 0, sizeof(pm_params));
  564. pm_params.name = "wigig";
  565. pm_params.callback = ipa_wigig_pm_cb;
  566. pm_params.user_data = NULL;
  567. pm_params.group = IPA_PM_GROUP_DEFAULT;
  568. if (ipa_pm_register(&pm_params, &ipa_wigig_ctx->ipa_pm_hdl)) {
  569. IPA_WIGIG_ERR("fail to register ipa pm\n");
  570. ret = -EFAULT;
  571. goto fail_pm;
  572. }
  573. IPA_WIGIG_DBG("pm hdl %d\n", ipa_wigig_ctx->ipa_pm_hdl);
  574. ret = ipa_wigig_uc_msi_init(true,
  575. ipa_wigig_ctx->periph_baddr_pa,
  576. ipa_wigig_ctx->pseudo_cause_pa,
  577. ipa_wigig_ctx->int_gen_tx_pa,
  578. ipa_wigig_ctx->int_gen_rx_pa,
  579. ipa_wigig_ctx->dma_ep_misc_pa);
  580. if (ret) {
  581. IPA_WIGIG_ERR("failed configuring msi regs at uC\n");
  582. ret = -EFAULT;
  583. goto fail_msi;
  584. }
  585. if (ipa_conn_wigig_rx_pipe_i(in, out)) {
  586. IPA_WIGIG_ERR("fail to connect rx pipe\n");
  587. ret = -EFAULT;
  588. goto fail_connect_pipe;
  589. }
  590. ipa_wigig_store_pipe_info(ipa_wigig_ctx->pipes.flat,
  591. IPA_CLIENT_WIGIG_PROD_IDX);
  592. ipa_wigig_ctx->conn_pipes |=
  593. ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD);
  594. IPA_WIGIG_DBG("exit\n");
  595. return 0;
  596. fail_connect_pipe:
  597. ipa_wigig_uc_msi_init(false,
  598. ipa_wigig_ctx->periph_baddr_pa,
  599. ipa_wigig_ctx->pseudo_cause_pa,
  600. ipa_wigig_ctx->int_gen_tx_pa,
  601. ipa_wigig_ctx->int_gen_rx_pa,
  602. ipa_wigig_ctx->dma_ep_misc_pa);
  603. fail_msi:
  604. ipa_pm_deregister(ipa_wigig_ctx->ipa_pm_hdl);
  605. fail_pm:
  606. return ret;
  607. }
  608. EXPORT_SYMBOL(ipa_wigig_conn_rx_pipe);
  609. static int ipa_wigig_client_to_idx(enum ipa_client_type client,
  610. unsigned int *idx)
  611. {
  612. switch (client) {
  613. case IPA_CLIENT_WIGIG1_CONS:
  614. *idx = 1;
  615. break;
  616. case IPA_CLIENT_WIGIG2_CONS:
  617. *idx = 2;
  618. break;
  619. case IPA_CLIENT_WIGIG3_CONS:
  620. *idx = 3;
  621. break;
  622. case IPA_CLIENT_WIGIG4_CONS:
  623. *idx = 4;
  624. break;
  625. default:
  626. IPA_WIGIG_ERR("invalid client %d\n", client);
  627. return -EINVAL;
  628. }
  629. return 0;
  630. }
  631. static int ipa_wigig_clean_pipe_info(unsigned int idx)
  632. {
  633. IPA_WIGIG_DBG("cleaning pipe %d info\n", idx);
  634. if (idx >= IPA_WIGIG_MAX_PIPES) {
  635. IPA_WIGIG_ERR("invalid index %d\n", idx);
  636. return -EINVAL;
  637. }
  638. if (ipa_wigig_ctx->smmu_en) {
  639. sg_free_table(
  640. &ipa_wigig_ctx->pipes.smmu[idx].desc_ring_base);
  641. sg_free_table(
  642. &ipa_wigig_ctx->pipes.smmu[idx].status_ring_base);
  643. memset(ipa_wigig_ctx->pipes.smmu + idx,
  644. 0,
  645. sizeof(ipa_wigig_ctx->pipes.smmu[idx]));
  646. } else {
  647. memset(ipa_wigig_ctx->pipes.flat + idx, 0,
  648. sizeof(ipa_wigig_ctx->pipes.flat[idx]));
  649. }
  650. IPA_WIGIG_DBG("exit\n");
  651. return 0;
  652. }
  653. static int ipa_wigig_clone_sg_table(struct sg_table *source,
  654. struct sg_table *dst)
  655. {
  656. struct scatterlist *next, *s, *sglist;
  657. int i, nents = source->nents;
  658. if (sg_alloc_table(dst, nents, GFP_KERNEL))
  659. return -EINVAL;
  660. next = dst->sgl;
  661. sglist = source->sgl;
  662. for_each_sg(sglist, s, nents, i) {
  663. *next = *s;
  664. next = sg_next(next);
  665. }
  666. dst->nents = nents;
  667. dst->orig_nents = source->orig_nents;
  668. return 0;
  669. }
  670. static int ipa_wigig_store_pipe_smmu_info
  671. (struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu, unsigned int idx)
  672. {
  673. int ret;
  674. IPA_WIGIG_DBG(
  675. "idx %d: desc_ring HWHEAD_pa %pa, HWTAIL_pa %pa, status_ring HWHEAD_pa %pa, HWTAIL_pa %pa, desc_ring_base 0x%llx, status_ring_base 0x%llx\n",
  676. idx,
  677. &pipe_smmu->desc_ring_HWHEAD_pa,
  678. &pipe_smmu->desc_ring_HWTAIL_pa,
  679. &pipe_smmu->status_ring_HWHEAD_pa,
  680. &pipe_smmu->status_ring_HWTAIL_pa,
  681. (unsigned long long)pipe_smmu->desc_ring_base_iova,
  682. (unsigned long long)pipe_smmu->status_ring_base_iova);
  683. /* store regs */
  684. ipa_wigig_ctx->pipes.smmu[idx].desc_ring_HWHEAD_pa =
  685. pipe_smmu->desc_ring_HWHEAD_pa;
  686. ipa_wigig_ctx->pipes.smmu[idx].desc_ring_HWTAIL_pa =
  687. pipe_smmu->desc_ring_HWTAIL_pa;
  688. ipa_wigig_ctx->pipes.smmu[idx].status_ring_HWHEAD_pa =
  689. pipe_smmu->status_ring_HWHEAD_pa;
  690. ipa_wigig_ctx->pipes.smmu[idx].status_ring_HWTAIL_pa =
  691. pipe_smmu->status_ring_HWTAIL_pa;
  692. /* store rings IOVAs */
  693. ipa_wigig_ctx->pipes.smmu[idx].desc_ring_base_iova =
  694. pipe_smmu->desc_ring_base_iova;
  695. ipa_wigig_ctx->pipes.smmu[idx].status_ring_base_iova =
  696. pipe_smmu->status_ring_base_iova;
  697. /* copy sgt */
  698. ret = ipa_wigig_clone_sg_table(
  699. &pipe_smmu->desc_ring_base,
  700. &ipa_wigig_ctx->pipes.smmu[idx].desc_ring_base);
  701. if (ret)
  702. goto fail_desc;
  703. ret = ipa_wigig_clone_sg_table(
  704. &pipe_smmu->status_ring_base,
  705. &ipa_wigig_ctx->pipes.smmu[idx].status_ring_base);
  706. if (ret)
  707. goto fail_stat;
  708. IPA_WIGIG_DBG("exit\n");
  709. return 0;
  710. fail_stat:
  711. sg_free_table(&ipa_wigig_ctx->pipes.smmu[idx].desc_ring_base);
  712. memset(&ipa_wigig_ctx->pipes.smmu[idx].desc_ring_base, 0,
  713. sizeof(ipa_wigig_ctx->pipes.smmu[idx].desc_ring_base));
  714. fail_desc:
  715. return ret;
  716. }
  717. static int ipa_wigig_get_pipe_smmu_info(
  718. struct ipa_wigig_pipe_setup_info_smmu **pipe_smmu, unsigned int idx)
  719. {
  720. if (idx >= IPA_WIGIG_MAX_PIPES) {
  721. IPA_WIGIG_ERR("exceeded pipe num %d > %d\n",
  722. idx, IPA_WIGIG_MAX_PIPES);
  723. return -EINVAL;
  724. }
  725. *pipe_smmu = &ipa_wigig_ctx->pipes.smmu[idx];
  726. return 0;
  727. }
  728. static int ipa_wigig_get_pipe_info(
  729. struct ipa_wigig_pipe_setup_info **pipe, unsigned int idx)
  730. {
  731. if (idx >= IPA_WIGIG_MAX_PIPES) {
  732. IPA_WIGIG_ERR("exceeded pipe num %d >= %d\n", idx,
  733. IPA_WIGIG_MAX_PIPES);
  734. return -EINVAL;
  735. }
  736. *pipe = &ipa_wigig_ctx->pipes.flat[idx];
  737. return 0;
  738. }
  739. static int ipa_wigig_get_regs_addr(
  740. void __iomem **desc_ring_h, void __iomem **desc_ring_t,
  741. void __iomem **status_ring_h, void __iomem **status_ring_t,
  742. unsigned int idx)
  743. {
  744. struct ipa_wigig_pipe_setup_info *pipe;
  745. struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu;
  746. int ret = 0;
  747. IPA_WIGIG_DBG("\n");
  748. if (idx >= IPA_WIGIG_MAX_PIPES) {
  749. IPA_WIGIG_DBG("exceeded pipe num %d >= %d\n", idx,
  750. IPA_WIGIG_MAX_PIPES);
  751. return -EINVAL;
  752. }
  753. if (!ipa_wigig_ctx) {
  754. IPA_WIGIG_DBG("wigig ctx is not initialized\n");
  755. return -EPERM;
  756. }
  757. if (!(ipa_wigig_ctx->conn_pipes &
  758. ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD))) {
  759. IPA_WIGIG_DBG(
  760. "must connect rx pipe before connecting any client\n");
  761. return -EINVAL;
  762. }
  763. if (ipa_wigig_ctx->smmu_en) {
  764. ret = ipa_wigig_get_pipe_smmu_info(&pipe_smmu, idx);
  765. if (ret)
  766. return -EINVAL;
  767. *desc_ring_h =
  768. ioremap(pipe_smmu->desc_ring_HWHEAD_pa, sizeof(u32));
  769. if (!*desc_ring_h) {
  770. IPA_WIGIG_DBG(
  771. "couldn't ioremap desc ring head address\n");
  772. ret = -EINVAL;
  773. goto fail_map_desc_h;
  774. }
  775. *desc_ring_t =
  776. ioremap(pipe_smmu->desc_ring_HWTAIL_pa, sizeof(u32));
  777. if (!*desc_ring_t) {
  778. IPA_WIGIG_DBG(
  779. "couldn't ioremap desc ring tail address\n");
  780. ret = -EINVAL;
  781. goto fail_map_desc_t;
  782. }
  783. *status_ring_h =
  784. ioremap(pipe_smmu->status_ring_HWHEAD_pa, sizeof(u32));
  785. if (!*status_ring_h) {
  786. IPA_WIGIG_DBG(
  787. "couldn't ioremap status ring head address\n");
  788. ret = -EINVAL;
  789. goto fail_map_status_h;
  790. }
  791. *status_ring_t =
  792. ioremap(pipe_smmu->status_ring_HWTAIL_pa, sizeof(u32));
  793. if (!*status_ring_t) {
  794. IPA_WIGIG_DBG(
  795. "couldn't ioremap status ring tail address\n");
  796. ret = -EINVAL;
  797. goto fail_map_status_t;
  798. }
  799. } else {
  800. ret = ipa_wigig_get_pipe_info(&pipe, idx);
  801. if (ret)
  802. return -EINVAL;
  803. *desc_ring_h = ioremap(pipe->desc_ring_HWHEAD_pa, sizeof(u32));
  804. if (!*desc_ring_h) {
  805. IPA_WIGIG_DBG(
  806. "couldn't ioremap desc ring head address\n");
  807. ret = -EINVAL;
  808. goto fail_map_desc_h;
  809. }
  810. *desc_ring_t = ioremap(pipe->desc_ring_HWTAIL_pa, sizeof(u32));
  811. if (!*desc_ring_t) {
  812. IPA_WIGIG_DBG(
  813. "couldn't ioremap desc ring tail address\n");
  814. ret = -EINVAL;
  815. goto fail_map_desc_t;
  816. }
  817. *status_ring_h =
  818. ioremap(pipe->status_ring_HWHEAD_pa, sizeof(u32));
  819. if (!*status_ring_h) {
  820. IPA_WIGIG_DBG(
  821. "couldn't ioremap status ring head address\n");
  822. ret = -EINVAL;
  823. goto fail_map_status_h;
  824. }
  825. *status_ring_t =
  826. ioremap(pipe->status_ring_HWTAIL_pa, sizeof(u32));
  827. if (!*status_ring_t) {
  828. IPA_WIGIG_DBG(
  829. "couldn't ioremap status ring tail address\n");
  830. ret = -EINVAL;
  831. goto fail_map_status_t;
  832. }
  833. }
  834. IPA_WIGIG_DBG("exit\n");
  835. return 0;
  836. fail_map_status_t:
  837. iounmap(*status_ring_h);
  838. fail_map_status_h:
  839. iounmap(*desc_ring_t);
  840. fail_map_desc_t:
  841. iounmap(*desc_ring_h);
  842. fail_map_desc_h:
  843. IPA_WIGIG_DBG("couldn't get regs information idx %d\n", idx);
  844. return ret;
  845. }
  846. int ipa_wigig_save_regs(void)
  847. {
  848. void __iomem *desc_ring_h = NULL, *desc_ring_t = NULL,
  849. *status_ring_h = NULL, *status_ring_t = NULL,
  850. *int_gen_rx_pa = NULL, *int_gen_tx_pa = NULL;
  851. uint32_t readval;
  852. u8 pipe_connected;
  853. int i, ret = 0;
  854. IPA_WIGIG_DBG("Start collecting pipes information\n");
  855. if (!ipa_wigig_ctx) {
  856. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  857. return -EPERM;
  858. }
  859. if (!(ipa_wigig_ctx->conn_pipes &
  860. ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD))) {
  861. IPA_WIGIG_ERR(
  862. "must connect rx pipe before connecting any client\n");
  863. return -EINVAL;
  864. }
  865. for (i = 0; i < IPA_WIGIG_MAX_PIPES; i++) {
  866. pipe_connected = (ipa_wigig_ctx->conn_pipes & (0x1 << i));
  867. if (pipe_connected) {
  868. ret = ipa_wigig_get_regs_addr(
  869. &desc_ring_h, &desc_ring_t,
  870. &status_ring_h, &status_ring_t, i);
  871. if (ret) {
  872. IPA_WIGIG_ERR(
  873. "couldn't get registers information on client %d\n",
  874. i);
  875. return -EINVAL;
  876. }
  877. IPA_WIGIG_DBG("collecting pipe info of index %d\n", i);
  878. if (i == IPA_CLIENT_WIGIG_PROD_IDX) {
  879. ipa_wigig_ctx->regs_save.pipes_val[i].dir = 0;
  880. } else {
  881. ipa_wigig_ctx->regs_save.pipes_val[i].dir = 1;
  882. /* TX ids start from 2 */
  883. ipa_wigig_ctx->regs_save.pipes_val[i]
  884. .tx_ring_id = i + 1;
  885. }
  886. readval = readl_relaxed(desc_ring_h);
  887. ipa_wigig_ctx->regs_save.pipes_val[i].desc_ring_HWHEAD =
  888. readval;
  889. readval = readl_relaxed(desc_ring_t);
  890. ipa_wigig_ctx->regs_save.pipes_val[i].desc_ring_HWTAIL =
  891. readval;
  892. readval = readl_relaxed(status_ring_h);
  893. ipa_wigig_ctx->regs_save.pipes_val[i]
  894. .status_ring_HWHEAD = readval;
  895. readval = readl_relaxed(status_ring_t);
  896. ipa_wigig_ctx->regs_save.pipes_val[i]
  897. .status_ring_HWTAIL = readval;
  898. /* unmap all regs */
  899. iounmap(desc_ring_h);
  900. iounmap(desc_ring_t);
  901. iounmap(status_ring_h);
  902. iounmap(status_ring_t);
  903. }
  904. }
  905. int_gen_rx_pa = ioremap(ipa_wigig_ctx->int_gen_rx_pa, sizeof(u32));
  906. if (!int_gen_rx_pa) {
  907. IPA_WIGIG_ERR("couldn't ioremap gen rx address\n");
  908. ret = -EINVAL;
  909. goto fail_map_gen_rx;
  910. }
  911. int_gen_tx_pa = ioremap(ipa_wigig_ctx->int_gen_tx_pa, sizeof(u32));
  912. if (!int_gen_tx_pa) {
  913. IPA_WIGIG_ERR("couldn't ioremap gen tx address\n");
  914. ret = -EINVAL;
  915. goto fail_map_gen_tx;
  916. }
  917. IPA_WIGIG_DBG("collecting int_gen_rx_pa info\n");
  918. readval = readl_relaxed(int_gen_rx_pa);
  919. ipa_wigig_ctx->regs_save.int_gen_rx_val = readval;
  920. IPA_WIGIG_DBG("collecting int_gen_tx_pa info\n");
  921. readval = readl_relaxed(int_gen_tx_pa);
  922. ipa_wigig_ctx->regs_save.int_gen_tx_val = readval;
  923. IPA_WIGIG_DBG("Finish collecting pipes info\n");
  924. IPA_WIGIG_DBG("exit\n");
  925. iounmap(int_gen_tx_pa);
  926. fail_map_gen_tx:
  927. iounmap(int_gen_rx_pa);
  928. fail_map_gen_rx:
  929. return ret;
  930. }
  931. static void ipa_wigig_clean_rx_buff_smmu_info(void)
  932. {
  933. IPA_WIGIG_DBG("clearing rx buff smmu info\n");
  934. sg_free_table(&ipa_wigig_ctx->rx_buff_smmu.data_buffer_base);
  935. memset(&ipa_wigig_ctx->rx_buff_smmu,
  936. 0,
  937. sizeof(ipa_wigig_ctx->rx_buff_smmu));
  938. IPA_WIGIG_DBG("\n");
  939. }
  940. static int ipa_wigig_store_rx_buff_smmu_info(
  941. struct ipa_wigig_rx_pipe_data_buffer_info_smmu *dbuff_smmu)
  942. {
  943. IPA_WIGIG_DBG("\n");
  944. if (ipa_wigig_clone_sg_table(&dbuff_smmu->data_buffer_base,
  945. &ipa_wigig_ctx->rx_buff_smmu.data_buffer_base))
  946. return -EINVAL;
  947. ipa_wigig_ctx->rx_buff_smmu.data_buffer_base_iova =
  948. dbuff_smmu->data_buffer_base_iova;
  949. ipa_wigig_ctx->rx_buff_smmu.data_buffer_size =
  950. dbuff_smmu->data_buffer_size;
  951. IPA_WIGIG_DBG("exit\n");
  952. return 0;
  953. }
  954. static int ipa_wigig_get_rx_buff_smmu_info(
  955. struct ipa_wigig_rx_pipe_data_buffer_info_smmu **dbuff_smmu)
  956. {
  957. IPA_WIGIG_DBG("\n");
  958. *dbuff_smmu = &ipa_wigig_ctx->rx_buff_smmu;
  959. IPA_WIGIG_DBG("exit\n");
  960. return 0;
  961. }
  962. static int ipa_wigig_store_tx_buff_smmu_info(
  963. struct ipa_wigig_tx_pipe_data_buffer_info_smmu *dbuff_smmu,
  964. unsigned int idx)
  965. {
  966. int result, i;
  967. struct ipa_wigig_tx_pipe_data_buffer_info_smmu *tx_buff_smmu;
  968. IPA_WIGIG_DBG("\n");
  969. if (idx > (IPA_WIGIG_TX_PIPE_NUM - 1)) {
  970. IPA_WIGIG_ERR("invalid tx index %d\n", idx);
  971. return -EINVAL;
  972. }
  973. tx_buff_smmu = ipa_wigig_ctx->tx_buff_smmu + idx;
  974. tx_buff_smmu->data_buffer_base =
  975. kcalloc(dbuff_smmu->num_buffers,
  976. sizeof(struct sg_table),
  977. GFP_KERNEL);
  978. if (!tx_buff_smmu->data_buffer_base)
  979. return -ENOMEM;
  980. tx_buff_smmu->data_buffer_base_iova =
  981. kcalloc(dbuff_smmu->num_buffers, sizeof(u64), GFP_KERNEL);
  982. if (!tx_buff_smmu->data_buffer_base_iova) {
  983. result = -ENOMEM;
  984. goto fail_iova;
  985. }
  986. for (i = 0; i < dbuff_smmu->num_buffers; i++) {
  987. result = ipa_wigig_clone_sg_table(
  988. dbuff_smmu->data_buffer_base + i,
  989. tx_buff_smmu->data_buffer_base + i);
  990. if (result)
  991. goto fail_sg_clone;
  992. tx_buff_smmu->data_buffer_base_iova[i] =
  993. dbuff_smmu->data_buffer_base_iova[i];
  994. }
  995. tx_buff_smmu->num_buffers = dbuff_smmu->num_buffers;
  996. tx_buff_smmu->data_buffer_size =
  997. dbuff_smmu->data_buffer_size;
  998. IPA_WIGIG_DBG("exit\n");
  999. return 0;
  1000. fail_sg_clone:
  1001. i--;
  1002. for (; i >= 0; i--)
  1003. sg_free_table(tx_buff_smmu->data_buffer_base + i);
  1004. kfree(tx_buff_smmu->data_buffer_base_iova);
  1005. tx_buff_smmu->data_buffer_base_iova = NULL;
  1006. fail_iova:
  1007. kfree(tx_buff_smmu->data_buffer_base);
  1008. tx_buff_smmu->data_buffer_base = NULL;
  1009. return result;
  1010. }
  1011. static int ipa_wigig_clean_tx_buff_smmu_info(unsigned int idx)
  1012. {
  1013. unsigned int i;
  1014. struct ipa_wigig_tx_pipe_data_buffer_info_smmu *dbuff_smmu;
  1015. IPA_WIGIG_DBG("\n");
  1016. if (idx > (IPA_WIGIG_TX_PIPE_NUM - 1)) {
  1017. IPA_WIGIG_ERR("invalid tx index %d\n", idx);
  1018. return -EINVAL;
  1019. }
  1020. dbuff_smmu = &ipa_wigig_ctx->tx_buff_smmu[idx];
  1021. if (!dbuff_smmu->data_buffer_base) {
  1022. IPA_WIGIG_ERR("no pa has been allocated\n");
  1023. return -EFAULT;
  1024. }
  1025. for (i = 0; i < dbuff_smmu->num_buffers; i++)
  1026. sg_free_table(dbuff_smmu->data_buffer_base + i);
  1027. kfree(dbuff_smmu->data_buffer_base);
  1028. dbuff_smmu->data_buffer_base = NULL;
  1029. kfree(dbuff_smmu->data_buffer_base_iova);
  1030. dbuff_smmu->data_buffer_base_iova = NULL;
  1031. dbuff_smmu->data_buffer_size = 0;
  1032. dbuff_smmu->num_buffers = 0;
  1033. IPA_WIGIG_DBG("exit\n");
  1034. return 0;
  1035. }
  1036. static int ipa_wigig_get_tx_buff_smmu_info(
  1037. struct ipa_wigig_tx_pipe_data_buffer_info_smmu **dbuff_smmu,
  1038. unsigned int idx)
  1039. {
  1040. if (idx > (IPA_WIGIG_TX_PIPE_NUM - 1)) {
  1041. IPA_WIGIG_ERR("invalid tx index %d\n", idx);
  1042. return -EINVAL;
  1043. }
  1044. *dbuff_smmu = &ipa_wigig_ctx->tx_buff_smmu[idx];
  1045. return 0;
  1046. }
  1047. static int ipa_wigig_store_rx_smmu_info
  1048. (struct ipa_wigig_conn_rx_in_params_smmu *in)
  1049. {
  1050. int ret;
  1051. IPA_WIGIG_DBG("\n");
  1052. ret = ipa_wigig_store_pipe_smmu_info(&in->pipe_smmu,
  1053. IPA_CLIENT_WIGIG_PROD_IDX);
  1054. if (ret)
  1055. return ret;
  1056. if (!ipa_wigig_ctx->shared_cb) {
  1057. ret = ipa_wigig_store_rx_buff_smmu_info(&in->dbuff_smmu);
  1058. if (ret)
  1059. goto fail_buff;
  1060. }
  1061. IPA_WIGIG_DBG("exit\n");
  1062. return 0;
  1063. fail_buff:
  1064. ipa_wigig_clean_pipe_info(IPA_CLIENT_WIGIG_PROD_IDX);
  1065. return ret;
  1066. }
  1067. static int ipa_wigig_store_client_smmu_info
  1068. (struct ipa_wigig_conn_tx_in_params_smmu *in, enum ipa_client_type client)
  1069. {
  1070. int ret;
  1071. unsigned int idx;
  1072. IPA_WIGIG_DBG("\n");
  1073. ret = ipa_wigig_client_to_idx(client, &idx);
  1074. if (ret)
  1075. return ret;
  1076. ret = ipa_wigig_store_pipe_smmu_info(&in->pipe_smmu, idx);
  1077. if (ret)
  1078. return ret;
  1079. if (!ipa_wigig_ctx->shared_cb) {
  1080. ret = ipa_wigig_store_tx_buff_smmu_info(
  1081. &in->dbuff_smmu, idx - 1);
  1082. if (ret)
  1083. goto fail_buff;
  1084. }
  1085. IPA_WIGIG_DBG("exit\n");
  1086. return 0;
  1087. fail_buff:
  1088. ipa_wigig_clean_pipe_info(IPA_CLIENT_WIGIG_PROD_IDX);
  1089. return ret;
  1090. }
  1091. static int ipa_wigig_get_rx_smmu_info(
  1092. struct ipa_wigig_pipe_setup_info_smmu **pipe_smmu,
  1093. struct ipa_wigig_rx_pipe_data_buffer_info_smmu **dbuff_smmu)
  1094. {
  1095. int ret;
  1096. ret = ipa_wigig_get_pipe_smmu_info(pipe_smmu,
  1097. IPA_CLIENT_WIGIG_PROD_IDX);
  1098. if (ret)
  1099. return ret;
  1100. ret = ipa_wigig_get_rx_buff_smmu_info(dbuff_smmu);
  1101. if (ret)
  1102. return ret;
  1103. return 0;
  1104. }
  1105. static int ipa_wigig_get_tx_smmu_info(
  1106. struct ipa_wigig_pipe_setup_info_smmu **pipe_smmu,
  1107. struct ipa_wigig_tx_pipe_data_buffer_info_smmu **dbuff_smmu,
  1108. enum ipa_client_type client)
  1109. {
  1110. unsigned int idx;
  1111. int ret;
  1112. ret = ipa_wigig_client_to_idx(client, &idx);
  1113. if (ret)
  1114. return ret;
  1115. ret = ipa_wigig_get_pipe_smmu_info(pipe_smmu, idx);
  1116. if (ret)
  1117. return ret;
  1118. ret = ipa_wigig_get_tx_buff_smmu_info(dbuff_smmu, idx - 1);
  1119. if (ret)
  1120. return ret;
  1121. return 0;
  1122. }
  1123. static int ipa_wigig_clean_smmu_info(enum ipa_client_type client)
  1124. {
  1125. int ret;
  1126. if (client == IPA_CLIENT_WIGIG_PROD) {
  1127. ret = ipa_wigig_clean_pipe_info(IPA_CLIENT_WIGIG_PROD_IDX);
  1128. if (ret)
  1129. return ret;
  1130. if (!ipa_wigig_ctx->shared_cb)
  1131. ipa_wigig_clean_rx_buff_smmu_info();
  1132. } else {
  1133. unsigned int idx;
  1134. ret = ipa_wigig_client_to_idx(client, &idx);
  1135. if (ret)
  1136. return ret;
  1137. ret = ipa_wigig_clean_pipe_info(idx);
  1138. if (ret)
  1139. return ret;
  1140. if (!ipa_wigig_ctx->shared_cb) {
  1141. ret = ipa_wigig_clean_tx_buff_smmu_info(idx - 1);
  1142. if (ret) {
  1143. IPA_WIGIG_ERR(
  1144. "cleaned tx pipe info but wasn't able to clean buff info, client %d\n"
  1145. , client);
  1146. WARN_ON(1);
  1147. return ret;
  1148. }
  1149. }
  1150. }
  1151. return 0;
  1152. }
  1153. int ipa_wigig_conn_rx_pipe_smmu(
  1154. struct ipa_wigig_conn_rx_in_params_smmu *in,
  1155. struct ipa_wigig_conn_out_params *out)
  1156. {
  1157. int ret;
  1158. struct ipa_pm_register_params pm_params;
  1159. IPA_WIGIG_DBG("\n");
  1160. if (!in || !out) {
  1161. IPA_WIGIG_ERR("empty parameters. in=%pK out=%pK\n", in, out);
  1162. return -EINVAL;
  1163. }
  1164. if (!ipa_wigig_ctx) {
  1165. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  1166. return -EPERM;
  1167. }
  1168. ret = ipa_uc_state_check();
  1169. if (ret) {
  1170. IPA_WIGIG_ERR("uC not ready\n");
  1171. return ret;
  1172. }
  1173. if (ipa_wigig_init_smmu_params())
  1174. return -EINVAL;
  1175. if (!ipa_wigig_ctx->smmu_en) {
  1176. IPA_WIGIG_ERR("IPA SMMU is disabled, wrong API used\n");
  1177. return -EFAULT;
  1178. }
  1179. memset(&pm_params, 0, sizeof(pm_params));
  1180. pm_params.name = "wigig";
  1181. pm_params.callback = ipa_wigig_pm_cb;
  1182. pm_params.user_data = NULL;
  1183. pm_params.group = IPA_PM_GROUP_DEFAULT;
  1184. if (ipa_pm_register(&pm_params, &ipa_wigig_ctx->ipa_pm_hdl)) {
  1185. IPA_WIGIG_ERR("fail to register ipa pm\n");
  1186. ret = -EFAULT;
  1187. goto fail_pm;
  1188. }
  1189. ret = ipa_wigig_uc_msi_init(true,
  1190. ipa_wigig_ctx->periph_baddr_pa,
  1191. ipa_wigig_ctx->pseudo_cause_pa,
  1192. ipa_wigig_ctx->int_gen_tx_pa,
  1193. ipa_wigig_ctx->int_gen_rx_pa,
  1194. ipa_wigig_ctx->dma_ep_misc_pa);
  1195. if (ret) {
  1196. IPA_WIGIG_ERR("failed configuring msi regs at uC\n");
  1197. ret = -EFAULT;
  1198. goto fail_msi;
  1199. }
  1200. if (ipa_conn_wigig_rx_pipe_i(in, out)) {
  1201. IPA_WIGIG_ERR("fail to connect rx pipe\n");
  1202. ret = -EFAULT;
  1203. goto fail_connect_pipe;
  1204. }
  1205. if (ipa_wigig_store_rx_smmu_info(in)) {
  1206. IPA_WIGIG_ERR("fail to store smmu data for rx pipe\n");
  1207. ret = -EFAULT;
  1208. goto fail_smmu_store;
  1209. }
  1210. ipa_wigig_ctx->conn_pipes |=
  1211. ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD);
  1212. IPA_WIGIG_DBG("exit\n");
  1213. return 0;
  1214. fail_smmu_store:
  1215. ipa_disconn_wigig_pipe_i(IPA_CLIENT_WIGIG_PROD,
  1216. &in->pipe_smmu,
  1217. &in->dbuff_smmu);
  1218. fail_connect_pipe:
  1219. ipa_wigig_uc_msi_init(false,
  1220. ipa_wigig_ctx->periph_baddr_pa,
  1221. ipa_wigig_ctx->pseudo_cause_pa,
  1222. ipa_wigig_ctx->int_gen_tx_pa,
  1223. ipa_wigig_ctx->int_gen_rx_pa,
  1224. ipa_wigig_ctx->dma_ep_misc_pa);
  1225. fail_msi:
  1226. ipa_pm_deregister(ipa_wigig_ctx->ipa_pm_hdl);
  1227. fail_pm:
  1228. return ret;
  1229. }
  1230. EXPORT_SYMBOL(ipa_wigig_conn_rx_pipe_smmu);
  1231. int ipa_wigig_set_perf_profile(u32 max_supported_bw_mbps)
  1232. {
  1233. IPA_WIGIG_DBG("setting throughput to %d\n", max_supported_bw_mbps);
  1234. if (!ipa_wigig_ctx) {
  1235. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  1236. return -EPERM;
  1237. }
  1238. IPA_WIGIG_DBG("ipa_pm handle %d\n", ipa_wigig_ctx->ipa_pm_hdl);
  1239. if (ipa_pm_set_throughput(ipa_wigig_ctx->ipa_pm_hdl,
  1240. max_supported_bw_mbps)) {
  1241. IPA_WIGIG_ERR("fail to setup pm perf profile\n");
  1242. return -EFAULT;
  1243. }
  1244. IPA_WIGIG_DBG("exit\n");
  1245. return 0;
  1246. }
  1247. EXPORT_SYMBOL(ipa_wigig_set_perf_profile);
  1248. static int ipa_wigig_store_client_mac(enum ipa_client_type client,
  1249. const char *mac)
  1250. {
  1251. unsigned int idx;
  1252. if (ipa_wigig_client_to_idx(client, &idx)) {
  1253. IPA_WIGIG_ERR("couldn't acquire idx\n");
  1254. return -EFAULT;
  1255. }
  1256. memcpy(ipa_wigig_ctx->clients_mac[idx - 1], mac, IPA_MAC_ADDR_SIZE);
  1257. return 0;
  1258. }
  1259. static int ipa_wigig_get_client_mac(enum ipa_client_type client, char *mac)
  1260. {
  1261. unsigned int idx;
  1262. if (ipa_wigig_client_to_idx(client, &idx)) {
  1263. IPA_WIGIG_ERR("couldn't acquire idx\n");
  1264. return -EFAULT;
  1265. }
  1266. memcpy(mac, ipa_wigig_ctx->clients_mac[idx - 1], IPA_MAC_ADDR_SIZE);
  1267. return 0;
  1268. }
  1269. static int ipa_wigig_clean_client_mac(enum ipa_client_type client)
  1270. {
  1271. char zero_mac[IPA_MAC_ADDR_SIZE] = { 0 };
  1272. return ipa_wigig_store_client_mac(client, zero_mac);
  1273. }
  1274. int ipa_wigig_conn_client(struct ipa_wigig_conn_tx_in_params *in,
  1275. struct ipa_wigig_conn_out_params *out)
  1276. {
  1277. char dev_name[IPA_RESOURCE_NAME_MAX];
  1278. unsigned int idx;
  1279. IPA_WIGIG_DBG("\n");
  1280. if (!in || !out) {
  1281. IPA_WIGIG_ERR("empty parameters. in=%pK out=%pK\n", in, out);
  1282. return -EINVAL;
  1283. }
  1284. if (!ipa_wigig_ctx) {
  1285. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  1286. return -EPERM;
  1287. }
  1288. if (!(ipa_wigig_ctx->conn_pipes &
  1289. ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD))) {
  1290. IPA_WIGIG_ERR(
  1291. "must connect rx pipe before connecting any client\n"
  1292. );
  1293. return -EINVAL;
  1294. }
  1295. if (ipa_wigig_ctx->smmu_en) {
  1296. IPA_WIGIG_ERR("IPA SMMU is enabled, wrong API used\n");
  1297. return -EFAULT;
  1298. }
  1299. if (ipa_uc_state_check()) {
  1300. IPA_WIGIG_ERR("uC not ready\n");
  1301. return -EFAULT;
  1302. }
  1303. if (ipa_wigig_get_devname(dev_name)) {
  1304. IPA_WIGIG_ERR("couldn't get dev name\n");
  1305. return -EFAULT;
  1306. }
  1307. if (ipa_conn_wigig_client_i(in, out)) {
  1308. IPA_WIGIG_ERR(
  1309. "fail to connect client. MAC [%X][%X][%X][%X][%X][%X]\n"
  1310. , in->client_mac[0], in->client_mac[1], in->client_mac[2]
  1311. , in->client_mac[3], in->client_mac[4], in->client_mac[5]);
  1312. return -EFAULT;
  1313. }
  1314. if (ipa_wigig_client_to_idx(out->client, &idx)) {
  1315. IPA_WIGIG_ERR("couldn't acquire idx\n");
  1316. goto fail_convert_client_to_idx;
  1317. }
  1318. ipa_wigig_store_pipe_info(&in->pipe, idx);
  1319. if (ipa_wigig_send_msg(WIGIG_CLIENT_CONNECT,
  1320. dev_name,
  1321. in->client_mac, out->client, false)) {
  1322. IPA_WIGIG_ERR("couldn't send msg to IPACM\n");
  1323. goto fail_sendmsg;
  1324. }
  1325. /* update connected clients */
  1326. ipa_wigig_ctx->conn_pipes |=
  1327. ipa_wigig_pipe_to_bit_val(out->client);
  1328. ipa_wigig_store_client_mac(out->client, in->client_mac);
  1329. IPA_WIGIG_DBG("exit\n");
  1330. return 0;
  1331. fail_sendmsg:
  1332. ipa_wigig_clean_pipe_info(idx);
  1333. fail_convert_client_to_idx:
  1334. ipa_disconn_wigig_pipe_i(out->client, NULL, NULL);
  1335. return -EINVAL;
  1336. }
  1337. EXPORT_SYMBOL(ipa_wigig_conn_client);
  1338. int ipa_wigig_conn_client_smmu(
  1339. struct ipa_wigig_conn_tx_in_params_smmu *in,
  1340. struct ipa_wigig_conn_out_params *out)
  1341. {
  1342. char netdev_name[IPA_RESOURCE_NAME_MAX];
  1343. int ret;
  1344. IPA_WIGIG_DBG("\n");
  1345. if (!in || !out) {
  1346. IPA_WIGIG_ERR("empty parameters. in=%pK out=%pK\n", in, out);
  1347. return -EINVAL;
  1348. }
  1349. if (!ipa_wigig_ctx) {
  1350. IPA_WIGIG_ERR("wigig ctx is not initialized\n");
  1351. return -EPERM;
  1352. }
  1353. if (!(ipa_wigig_ctx->conn_pipes &
  1354. ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD))) {
  1355. IPA_WIGIG_ERR(
  1356. "must connect rx pipe before connecting any client\n"
  1357. );
  1358. return -EINVAL;
  1359. }
  1360. if (!ipa_wigig_ctx->smmu_en) {
  1361. IPA_WIGIG_ERR("IPA SMMU is disabled, wrong API used\n");
  1362. return -EFAULT;
  1363. }
  1364. ret = ipa_uc_state_check();
  1365. if (ret) {
  1366. IPA_WIGIG_ERR("uC not ready\n");
  1367. return ret;
  1368. }
  1369. if (ipa_wigig_get_devname(netdev_name)) {
  1370. IPA_WIGIG_ERR("couldn't get dev name\n");
  1371. return -EFAULT;
  1372. }
  1373. if (ipa_conn_wigig_client_i(in, out)) {
  1374. IPA_WIGIG_ERR(
  1375. "fail to connect client. MAC [%X][%X][%X][%X][%X][%X]\n"
  1376. , in->client_mac[0], in->client_mac[1]
  1377. , in->client_mac[2], in->client_mac[3]
  1378. , in->client_mac[4], in->client_mac[5]);
  1379. return -EFAULT;
  1380. }
  1381. if (ipa_wigig_send_msg(WIGIG_CLIENT_CONNECT,
  1382. netdev_name,
  1383. in->client_mac, out->client, false)) {
  1384. IPA_WIGIG_ERR("couldn't send msg to IPACM\n");
  1385. ret = -EFAULT;
  1386. goto fail_sendmsg;
  1387. }
  1388. ret = ipa_wigig_store_client_smmu_info(in, out->client);
  1389. if (ret)
  1390. goto fail_smmu;
  1391. /* update connected clients */
  1392. ipa_wigig_ctx->conn_pipes |=
  1393. ipa_wigig_pipe_to_bit_val(out->client);
  1394. ipa_wigig_store_client_mac(out->client, in->client_mac);
  1395. IPA_WIGIG_DBG("exit\n");
  1396. return 0;
  1397. fail_smmu:
  1398. /*
  1399. * wigig clients are disconnected with legacy message since there is
  1400. * no need to send ep, client MAC is sufficient for disconnect
  1401. */
  1402. ipa_wigig_send_wlan_msg(WLAN_CLIENT_DISCONNECT, netdev_name,
  1403. in->client_mac);
  1404. fail_sendmsg:
  1405. ipa_disconn_wigig_pipe_i(out->client, &in->pipe_smmu, &in->dbuff_smmu);
  1406. return ret;
  1407. }
  1408. EXPORT_SYMBOL(ipa_wigig_conn_client_smmu);
  1409. static inline int ipa_wigig_validate_client_type(enum ipa_client_type client)
  1410. {
  1411. switch (client) {
  1412. case IPA_CLIENT_WIGIG_PROD:
  1413. case IPA_CLIENT_WIGIG1_CONS:
  1414. case IPA_CLIENT_WIGIG2_CONS:
  1415. case IPA_CLIENT_WIGIG3_CONS:
  1416. case IPA_CLIENT_WIGIG4_CONS:
  1417. break;
  1418. default:
  1419. IPA_WIGIG_ERR_RL("invalid client type %d\n", client);
  1420. return -EINVAL;
  1421. }
  1422. return 0;
  1423. }
  1424. int ipa_wigig_disconn_pipe(enum ipa_client_type client)
  1425. {
  1426. int ret;
  1427. char dev_name[IPA_RESOURCE_NAME_MAX];
  1428. char client_mac[IPA_MAC_ADDR_SIZE];
  1429. IPA_WIGIG_DBG("\n");
  1430. ret = ipa_wigig_validate_client_type(client);
  1431. if (ret)
  1432. return ret;
  1433. if (client != IPA_CLIENT_WIGIG_PROD) {
  1434. if (ipa_wigig_get_devname(dev_name)) {
  1435. IPA_WIGIG_ERR("couldn't get dev name\n");
  1436. return -EFAULT;
  1437. }
  1438. if (ipa_wigig_get_client_mac(client, client_mac)) {
  1439. IPA_WIGIG_ERR("couldn't get client mac\n");
  1440. return -EFAULT;
  1441. }
  1442. }
  1443. IPA_WIGIG_DBG("disconnecting ipa_client_type %d\n", client);
  1444. if (ipa_wigig_is_smmu_enabled()) {
  1445. struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu;
  1446. struct ipa_wigig_rx_pipe_data_buffer_info_smmu *rx_dbuff_smmu;
  1447. struct ipa_wigig_tx_pipe_data_buffer_info_smmu *tx_dbuff_smmu;
  1448. if (client == IPA_CLIENT_WIGIG_PROD) {
  1449. ret = ipa_wigig_get_rx_smmu_info(&pipe_smmu,
  1450. &rx_dbuff_smmu);
  1451. if (ret)
  1452. return ret;
  1453. ret = ipa_disconn_wigig_pipe_i(client,
  1454. pipe_smmu,
  1455. rx_dbuff_smmu);
  1456. } else {
  1457. ret = ipa_wigig_get_tx_smmu_info(&pipe_smmu,
  1458. &tx_dbuff_smmu, client);
  1459. if (ret)
  1460. return ret;
  1461. ret = ipa_disconn_wigig_pipe_i(client,
  1462. pipe_smmu,
  1463. tx_dbuff_smmu);
  1464. }
  1465. } else {
  1466. ret = ipa_disconn_wigig_pipe_i(client, NULL, NULL);
  1467. }
  1468. if (ret) {
  1469. IPA_WIGIG_ERR("couldn't disconnect client %d\n", client);
  1470. return ret;
  1471. }
  1472. /* RX will be disconnected last, deinit uC msi config */
  1473. if (client == IPA_CLIENT_WIGIG_PROD) {
  1474. IPA_WIGIG_DBG("Rx pipe disconnected, deIniting uc\n");
  1475. ret = ipa_wigig_uc_msi_init(false,
  1476. ipa_wigig_ctx->periph_baddr_pa,
  1477. ipa_wigig_ctx->pseudo_cause_pa,
  1478. ipa_wigig_ctx->int_gen_tx_pa,
  1479. ipa_wigig_ctx->int_gen_rx_pa,
  1480. ipa_wigig_ctx->dma_ep_misc_pa);
  1481. if (ret) {
  1482. IPA_WIGIG_ERR("failed unmapping msi regs\n");
  1483. WARN_ON(1);
  1484. }
  1485. ret = ipa_pm_deregister(ipa_wigig_ctx->ipa_pm_hdl);
  1486. if (ret) {
  1487. IPA_WIGIG_ERR("failed dereg pm\n");
  1488. WARN_ON(1);
  1489. }
  1490. ipa_wigig_ctx->conn_pipes &=
  1491. ~ipa_wigig_pipe_to_bit_val(IPA_CLIENT_WIGIG_PROD);
  1492. WARN_ON(ipa_wigig_ctx->conn_pipes);
  1493. } else {
  1494. /*
  1495. * wigig clients are disconnected with legacy message since
  1496. * there is no need to send ep, client MAC is sufficient for
  1497. * disconnect.
  1498. */
  1499. ipa_wigig_send_wlan_msg(WLAN_CLIENT_DISCONNECT, dev_name,
  1500. client_mac);
  1501. ipa_wigig_clean_client_mac(client);
  1502. }
  1503. if (ipa_wigig_is_smmu_enabled())
  1504. ipa_wigig_clean_smmu_info(client);
  1505. IPA_WIGIG_DBG("exit\n");
  1506. return 0;
  1507. }
  1508. EXPORT_SYMBOL(ipa_wigig_disconn_pipe);
  1509. int ipa_wigig_enable_pipe(enum ipa_client_type client)
  1510. {
  1511. int ret;
  1512. IPA_WIGIG_DBG("\n");
  1513. ret = ipa_wigig_validate_client_type(client);
  1514. if (ret)
  1515. return ret;
  1516. IPA_WIGIG_DBG("enabling pipe %d\n", client);
  1517. ret = ipa_enable_wigig_pipe_i(client);
  1518. if (ret)
  1519. return ret;
  1520. /* do only when Rx pipe is enabled */
  1521. if (client == IPA_CLIENT_WIGIG_PROD) {
  1522. ret = ipa_pm_activate_sync(ipa_wigig_ctx->ipa_pm_hdl);
  1523. if (ret) {
  1524. IPA_WIGIG_ERR("fail to activate ipa pm\n");
  1525. ret = -EFAULT;
  1526. goto fail_pm_active;
  1527. }
  1528. }
  1529. IPA_WIGIG_DBG("exit\n");
  1530. return 0;
  1531. fail_pm_active:
  1532. ipa_disable_wigig_pipe_i(client);
  1533. return ret;
  1534. }
  1535. EXPORT_SYMBOL(ipa_wigig_enable_pipe);
  1536. int ipa_wigig_disable_pipe(enum ipa_client_type client)
  1537. {
  1538. int ret;
  1539. IPA_WIGIG_DBG("\n");
  1540. ret = ipa_wigig_validate_client_type(client);
  1541. if (ret)
  1542. return ret;
  1543. ret = ipa_disable_wigig_pipe_i(client);
  1544. if (ret)
  1545. return ret;
  1546. /* do only when Rx pipe is disabled */
  1547. if (client == IPA_CLIENT_WIGIG_PROD) {
  1548. ret = ipa_pm_deactivate_sync(ipa_wigig_ctx->ipa_pm_hdl);
  1549. if (ret) {
  1550. IPA_WIGIG_ERR("fail to deactivate ipa pm\n");
  1551. return -EFAULT;
  1552. }
  1553. }
  1554. IPA_WIGIG_DBG("exit\n");
  1555. return 0;
  1556. }
  1557. EXPORT_SYMBOL(ipa_wigig_disable_pipe);
  1558. int ipa_wigig_tx_dp(enum ipa_client_type dst, struct sk_buff *skb)
  1559. {
  1560. int ret;
  1561. IPA_WIGIG_DBG_LOW("\n");
  1562. ret = ipa_wigig_validate_client_type(dst);
  1563. if (unlikely(ret))
  1564. return ret;
  1565. ret = ipa_tx_dp(dst, skb, NULL);
  1566. if (unlikely(ret))
  1567. return ret;
  1568. IPA_WIGIG_DBG_LOW("exit\n");
  1569. return 0;
  1570. }
  1571. EXPORT_SYMBOL(ipa_wigig_tx_dp);