ipa_wigig.c 49 KB

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