bmi.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /*
  2. * copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
  3. *
  4. * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  5. *
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for
  8. * any purpose with or without fee is hereby granted, provided that the
  9. * above copyright notice and this permission notice appear in all
  10. * copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  13. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  15. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  16. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  17. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  18. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  19. * PERFORMANCE OF THIS SOFTWARE.
  20. */
  21. /*
  22. * This file was originally distributed by Qualcomm Atheros, Inc.
  23. * under proprietary terms before Copyright ownership was assigned
  24. * to the Linux Foundation.
  25. */
  26. #include "i_bmi.h"
  27. #include "cds_api.h"
  28. /* APIs visible to the driver */
  29. /* BMI_1 refers QCA6174 target; the ADDR is AXI addr */
  30. #define BMI_1_TEST_ADDR (0xa0000)
  31. /* BMI_2 ; */
  32. #define BMI_2_TEST_ADDR (0x6E0000)
  33. /* Enable BMI_TEST COMMANDs; The Value 0x09 is randomly choosen */
  34. #define BMI_TEST_ENABLE (0x09)
  35. static QDF_STATUS
  36. bmi_command_test(uint32_t command, uint32_t address, uint8_t *data,
  37. uint32_t length, struct ol_context *ol_ctx)
  38. {
  39. switch (command) {
  40. case BMI_NO_COMMAND:
  41. return bmi_no_command(ol_ctx);
  42. case BMI_WRITE_MEMORY:
  43. return bmi_write_memory(address, data, length, ol_ctx);
  44. case BMI_READ_MEMORY:
  45. return bmi_read_memory(address, data, length, ol_ctx);
  46. case BMI_EXECUTE:
  47. return bmi_execute(address, (uint32_t *)data, ol_ctx);
  48. default:
  49. break;
  50. }
  51. return QDF_STATUS_SUCCESS;
  52. }
  53. QDF_STATUS bmi_init(struct ol_context *ol_ctx)
  54. {
  55. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  56. struct hif_opaque_softc *scn = ol_ctx->scn;
  57. qdf_device_t qdf_dev = ol_ctx->qdf_dev;
  58. if (!scn) {
  59. BMI_ERR("Invalid scn Context");
  60. bmi_assert(0);
  61. return QDF_STATUS_NOT_INITIALIZED;
  62. }
  63. if (!qdf_dev->dev) {
  64. BMI_ERR("%s: Invalid Device Pointer", __func__);
  65. return QDF_STATUS_NOT_INITIALIZED;
  66. }
  67. info->bmi_done = false;
  68. if (!info->bmi_cmd_buff) {
  69. info->bmi_cmd_buff =
  70. qdf_mem_alloc_consistent(qdf_dev, qdf_dev->dev, MAX_BMI_CMDBUF_SZ,
  71. &info->bmi_cmd_da);
  72. if (!info->bmi_cmd_buff) {
  73. BMI_ERR("No Memory for BMI Command");
  74. return QDF_STATUS_E_NOMEM;
  75. }
  76. }
  77. if (!info->bmi_rsp_buff) {
  78. info->bmi_rsp_buff =
  79. qdf_mem_alloc_consistent(qdf_dev, qdf_dev->dev, MAX_BMI_CMDBUF_SZ,
  80. &info->bmi_rsp_da);
  81. if (!info->bmi_rsp_buff) {
  82. BMI_ERR("No Memory for BMI Response");
  83. goto end;
  84. }
  85. }
  86. return QDF_STATUS_SUCCESS;
  87. end:
  88. qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, MAX_BMI_CMDBUF_SZ,
  89. info->bmi_cmd_buff, info->bmi_cmd_da, 0);
  90. info->bmi_cmd_buff = NULL;
  91. return QDF_STATUS_E_NOMEM;
  92. }
  93. void bmi_cleanup(struct ol_context *ol_ctx)
  94. {
  95. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  96. qdf_device_t qdf_dev;
  97. if (!info || !ol_ctx) {
  98. BMI_WARN("%s: no bmi to cleanup", __func__);
  99. return;
  100. }
  101. qdf_dev = ol_ctx->qdf_dev;
  102. if (!qdf_dev || !qdf_dev->dev) {
  103. BMI_ERR("%s: Invalid Device Pointer", __func__);
  104. return;
  105. }
  106. if (info->bmi_cmd_buff) {
  107. qdf_mem_free_consistent(qdf_dev, qdf_dev->dev,
  108. MAX_BMI_CMDBUF_SZ,
  109. info->bmi_cmd_buff, info->bmi_cmd_da, 0);
  110. info->bmi_cmd_buff = NULL;
  111. info->bmi_cmd_da = 0;
  112. }
  113. if (info->bmi_rsp_buff) {
  114. qdf_mem_free_consistent(qdf_dev, qdf_dev->dev,
  115. MAX_BMI_CMDBUF_SZ,
  116. info->bmi_rsp_buff, info->bmi_rsp_da, 0);
  117. info->bmi_rsp_buff = NULL;
  118. info->bmi_rsp_da = 0;
  119. }
  120. }
  121. /**
  122. * bmi_done() - finish the bmi opperation
  123. * @ol_ctx: the bmi context
  124. *
  125. * does some sanity checking.
  126. * exchanges one last message with firmware.
  127. * frees some buffers.
  128. *
  129. * Return: QDF_STATUS_SUCCESS if bmi isn't needed.
  130. * QDF_STATUS_SUCCESS if bmi finishes.
  131. * otherwise returns failure.
  132. */
  133. QDF_STATUS bmi_done(struct ol_context *ol_ctx)
  134. {
  135. QDF_STATUS status = QDF_STATUS_SUCCESS;
  136. if (NO_BMI)
  137. return QDF_STATUS_SUCCESS;
  138. if (!ol_ctx) {
  139. BMI_ERR("%s: null context", __func__);
  140. return QDF_STATUS_E_NOMEM;
  141. }
  142. if (!hif_needs_bmi(ol_ctx->scn))
  143. return QDF_STATUS_SUCCESS;
  144. status = bmi_done_local(ol_ctx);
  145. if (status != QDF_STATUS_SUCCESS)
  146. BMI_ERR("BMI_DONE Failed status:%d", status);
  147. return status;
  148. }
  149. QDF_STATUS
  150. bmi_get_target_info(struct bmi_target_info *targ_info,
  151. struct ol_context *ol_ctx)
  152. {
  153. int status = 0;
  154. struct hif_opaque_softc *scn = ol_ctx->scn;
  155. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  156. uint8_t *bmi_cmd_buff = info->bmi_cmd_buff;
  157. uint8_t *bmi_rsp_buff = info->bmi_rsp_buff;
  158. uint32_t cid, length;
  159. qdf_dma_addr_t cmd = info->bmi_cmd_da;
  160. qdf_dma_addr_t rsp = info->bmi_rsp_da;
  161. if (info->bmi_done) {
  162. BMI_ERR("BMI Phase is Already Done");
  163. return QDF_STATUS_E_PERM;
  164. }
  165. if (!bmi_cmd_buff || !bmi_rsp_buff) {
  166. BMI_ERR("%s:BMI CMD/RSP Buffer is NULL", __func__);
  167. return QDF_STATUS_NOT_INITIALIZED;
  168. }
  169. cid = BMI_GET_TARGET_INFO;
  170. qdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid));
  171. length = sizeof(struct bmi_target_info);
  172. status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, sizeof(cid),
  173. (uint8_t *)bmi_rsp_buff, &length,
  174. BMI_EXCHANGE_TIMEOUT_MS);
  175. if (status) {
  176. BMI_ERR("Failed to target info: status:%d", status);
  177. return QDF_STATUS_E_FAILURE;
  178. }
  179. qdf_mem_copy(targ_info, bmi_rsp_buff, length);
  180. return QDF_STATUS_SUCCESS;
  181. }
  182. #ifdef FEATURE_BMI_2
  183. static inline uint32_t bmi_get_test_addr(void)
  184. {
  185. return BMI_2_TEST_ADDR;
  186. }
  187. #else
  188. static inline uint32_t bmi_get_test_addr(void)
  189. {
  190. return BMI_1_TEST_ADDR;
  191. }
  192. #endif
  193. QDF_STATUS bmi_download_firmware(struct ol_context *ol_ctx)
  194. {
  195. uint8_t data[10], out[10];
  196. uint32_t address;
  197. int32_t ret;
  198. struct hif_opaque_softc *scn = ol_ctx->scn;
  199. if (NO_BMI || !hif_needs_bmi(scn))
  200. return QDF_STATUS_SUCCESS;
  201. if (!scn) {
  202. BMI_ERR("Invalid scn context");
  203. bmi_assert(0);
  204. return QDF_STATUS_NOT_INITIALIZED;
  205. }
  206. #ifdef CONFIG_CNSS
  207. if (BMI_TEST_ENABLE == cnss_get_bmi_setup()) {
  208. ret = snprintf(data, 10, "ABCDEFGHI");
  209. BMI_DBG("ret:%d writing data:%s\n", ret, data);
  210. address = bmi_get_test_addr();
  211. if (bmi_init(ol_ctx) != QDF_STATUS_SUCCESS) {
  212. BMI_WARN("BMI_INIT Failed; No Memory!");
  213. goto end;
  214. }
  215. bmi_command_test(BMI_NO_COMMAND, address, data, 9, ol_ctx);
  216. bmi_command_test(BMI_WRITE_MEMORY, address, data, 9, ol_ctx);
  217. bmi_command_test(BMI_READ_MEMORY, address, out, 9, ol_ctx);
  218. BMI_DBG("Output:%s", out);
  219. }
  220. #endif
  221. end:
  222. return bmi_firmware_download(ol_ctx);
  223. }
  224. QDF_STATUS bmi_read_soc_register(uint32_t address, uint32_t *param,
  225. struct ol_context *ol_ctx)
  226. {
  227. struct hif_opaque_softc *scn = ol_ctx->scn;
  228. uint32_t cid;
  229. int status;
  230. uint32_t offset, param_len;
  231. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  232. uint8_t *bmi_cmd_buff = info->bmi_cmd_buff;
  233. uint8_t *bmi_rsp_buff = info->bmi_rsp_buff;
  234. qdf_dma_addr_t cmd = info->bmi_cmd_da;
  235. qdf_dma_addr_t rsp = info->bmi_rsp_da;
  236. bmi_assert(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
  237. qdf_mem_set(bmi_cmd_buff, 0, sizeof(cid) + sizeof(address));
  238. qdf_mem_set(bmi_rsp_buff, 0, sizeof(cid) + sizeof(address));
  239. if (info->bmi_done) {
  240. BMI_DBG("Command disallowed");
  241. return QDF_STATUS_E_PERM;
  242. }
  243. BMI_DBG("BMI Read SOC Register:device: 0x%p, address: 0x%x",
  244. scn, address);
  245. cid = BMI_READ_SOC_REGISTER;
  246. offset = 0;
  247. qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid));
  248. offset += sizeof(cid);
  249. qdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address));
  250. offset += sizeof(address);
  251. param_len = sizeof(*param);
  252. status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, offset,
  253. bmi_rsp_buff, &param_len, BMI_EXCHANGE_TIMEOUT_MS);
  254. if (status) {
  255. BMI_DBG("Unable to read from the device; status:%d", status);
  256. return QDF_STATUS_E_FAILURE;
  257. }
  258. qdf_mem_copy(param, bmi_rsp_buff, sizeof(*param));
  259. BMI_DBG("BMI Read SOC Register: Exit value: %d", *param);
  260. return QDF_STATUS_SUCCESS;
  261. }
  262. QDF_STATUS bmi_write_soc_register(uint32_t address, uint32_t param,
  263. struct ol_context *ol_ctx)
  264. {
  265. struct hif_opaque_softc *scn = ol_ctx->scn;
  266. uint32_t cid;
  267. int status;
  268. uint32_t offset;
  269. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  270. uint8_t *bmi_cmd_buff = info->bmi_cmd_buff;
  271. uint32_t size = sizeof(cid) + sizeof(address) + sizeof(param);
  272. qdf_dma_addr_t cmd = info->bmi_cmd_da;
  273. qdf_dma_addr_t rsp = info->bmi_rsp_da;
  274. bmi_assert(BMI_COMMAND_FITS(size));
  275. qdf_mem_set(bmi_cmd_buff, 0, size);
  276. if (info->bmi_done) {
  277. BMI_DBG("Command disallowed");
  278. return QDF_STATUS_E_FAILURE;
  279. }
  280. BMI_DBG("SOC Register Write:device:0x%p, addr:0x%x, param:%d",
  281. scn, address, param);
  282. cid = BMI_WRITE_SOC_REGISTER;
  283. offset = 0;
  284. qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid));
  285. offset += sizeof(cid);
  286. qdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address));
  287. offset += sizeof(address);
  288. qdf_mem_copy(&(bmi_cmd_buff[offset]), &param, sizeof(param));
  289. offset += sizeof(param);
  290. status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, offset,
  291. NULL, NULL, 0);
  292. if (status) {
  293. BMI_ERR("Unable to write to the device: status:%d", status);
  294. return QDF_STATUS_E_FAILURE;
  295. }
  296. BMI_DBG("BMI Read SOC Register: Exit");
  297. return QDF_STATUS_SUCCESS;
  298. }
  299. QDF_STATUS
  300. bmilz_data(uint8_t *buffer, uint32_t length, struct ol_context *ol_ctx)
  301. {
  302. uint32_t cid;
  303. int status;
  304. uint32_t offset;
  305. uint32_t remaining, txlen;
  306. const uint32_t header = sizeof(cid) + sizeof(length);
  307. struct hif_opaque_softc *scn = ol_ctx->scn;
  308. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  309. uint8_t *bmi_cmd_buff = info->bmi_cmd_buff;
  310. qdf_dma_addr_t cmd = info->bmi_cmd_da;
  311. qdf_dma_addr_t rsp = info->bmi_rsp_da;
  312. bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
  313. qdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header);
  314. if (info->bmi_done) {
  315. BMI_ERR("Command disallowed");
  316. return QDF_STATUS_E_PERM;
  317. }
  318. BMI_DBG("BMI Send LZ Data: device: 0x%p, length: %d",
  319. scn, length);
  320. cid = BMI_LZ_DATA;
  321. remaining = length;
  322. while (remaining) {
  323. txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
  324. remaining : (BMI_DATASZ_MAX - header);
  325. offset = 0;
  326. qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid));
  327. offset += sizeof(cid);
  328. qdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen));
  329. offset += sizeof(txlen);
  330. qdf_mem_copy(&(bmi_cmd_buff[offset]),
  331. &buffer[length - remaining], txlen);
  332. offset += txlen;
  333. status = hif_exchange_bmi_msg(scn, cmd, rsp,
  334. bmi_cmd_buff, offset,
  335. NULL, NULL, 0);
  336. if (status) {
  337. BMI_ERR("Failed to write to the device: status:%d",
  338. status);
  339. return QDF_STATUS_E_FAILURE;
  340. }
  341. remaining -= txlen;
  342. }
  343. BMI_DBG("BMI LZ Data: Exit");
  344. return QDF_STATUS_SUCCESS;
  345. }
  346. QDF_STATUS bmi_sign_stream_start(uint32_t address, uint8_t *buffer,
  347. uint32_t length, struct ol_context *ol_ctx)
  348. {
  349. uint32_t cid;
  350. int status;
  351. uint32_t offset;
  352. const uint32_t header = sizeof(cid) + sizeof(address) + sizeof(length);
  353. uint8_t aligned_buf[BMI_DATASZ_MAX + 4];
  354. uint8_t *src;
  355. struct hif_opaque_softc *scn = ol_ctx->scn;
  356. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  357. uint8_t *bmi_cmd_buff = info->bmi_cmd_buff;
  358. uint32_t remaining, txlen;
  359. qdf_dma_addr_t cmd = info->bmi_cmd_da;
  360. qdf_dma_addr_t rsp = info->bmi_rsp_da;
  361. bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
  362. qdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header);
  363. if (info->bmi_done) {
  364. BMI_ERR("Command disallowed");
  365. return QDF_STATUS_E_PERM;
  366. }
  367. BMI_ERR("Sign Stream start:device:0x%p, addr:0x%x, length:%d",
  368. scn, address, length);
  369. cid = BMI_SIGN_STREAM_START;
  370. remaining = length;
  371. while (remaining) {
  372. src = &buffer[length - remaining];
  373. if (remaining < (BMI_DATASZ_MAX - header)) {
  374. if (remaining & 0x3) {
  375. remaining = remaining + (4 - (remaining & 0x3));
  376. memcpy(aligned_buf, src, remaining);
  377. src = aligned_buf;
  378. }
  379. txlen = remaining;
  380. } else {
  381. txlen = (BMI_DATASZ_MAX - header);
  382. }
  383. offset = 0;
  384. qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid));
  385. offset += sizeof(cid);
  386. qdf_mem_copy(&(bmi_cmd_buff[offset]), &address,
  387. sizeof(address));
  388. offset += sizeof(offset);
  389. qdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen));
  390. offset += sizeof(txlen);
  391. qdf_mem_copy(&(bmi_cmd_buff[offset]), src, txlen);
  392. offset += txlen;
  393. status = hif_exchange_bmi_msg(scn, cmd, rsp,
  394. bmi_cmd_buff, offset, NULL,
  395. NULL, BMI_EXCHANGE_TIMEOUT_MS);
  396. if (status) {
  397. BMI_ERR("Unable to write to the device: status:%d",
  398. status);
  399. return QDF_STATUS_E_FAILURE;
  400. }
  401. remaining -= txlen;
  402. }
  403. BMI_DBG("BMI SIGN Stream Start: Exit");
  404. return QDF_STATUS_SUCCESS;
  405. }
  406. QDF_STATUS
  407. bmilz_stream_start(uint32_t address, struct ol_context *ol_ctx)
  408. {
  409. uint32_t cid;
  410. int status;
  411. uint32_t offset;
  412. struct hif_opaque_softc *scn = ol_ctx->scn;
  413. struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx);
  414. uint8_t *bmi_cmd_buff = info->bmi_cmd_buff;
  415. qdf_dma_addr_t cmd = info->bmi_cmd_da;
  416. qdf_dma_addr_t rsp = info->bmi_rsp_da;
  417. bmi_assert(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
  418. qdf_mem_set(bmi_cmd_buff, 0, sizeof(cid) + sizeof(address));
  419. if (info->bmi_done) {
  420. BMI_DBG("Command disallowed");
  421. return QDF_STATUS_E_PERM;
  422. }
  423. BMI_DBG("BMI LZ Stream Start: (device: 0x%p, address: 0x%x)",
  424. scn, address);
  425. cid = BMI_LZ_STREAM_START;
  426. offset = 0;
  427. qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid));
  428. offset += sizeof(cid);
  429. qdf_mem_copy(&(bmi_cmd_buff[offset]), &address, sizeof(address));
  430. offset += sizeof(address);
  431. status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, offset,
  432. NULL, NULL, 0);
  433. if (status) {
  434. BMI_ERR("Unable to Start LZ Stream to the device status:%d",
  435. status);
  436. return QDF_STATUS_E_FAILURE;
  437. }
  438. BMI_DBG("BMI LZ Stream: Exit");
  439. return QDF_STATUS_SUCCESS;
  440. }
  441. QDF_STATUS
  442. bmi_fast_download(uint32_t address, uint8_t *buffer,
  443. uint32_t length, struct ol_context *ol_ctx)
  444. {
  445. QDF_STATUS status = QDF_STATUS_E_FAILURE;
  446. uint32_t last_word = 0;
  447. uint32_t last_word_offset = length & ~0x3;
  448. uint32_t unaligned_bytes = length & 0x3;
  449. status = bmilz_stream_start(address, ol_ctx);
  450. if (status != QDF_STATUS_SUCCESS)
  451. goto end;
  452. /* copy the last word into a zero padded buffer */
  453. if (unaligned_bytes)
  454. qdf_mem_copy(&last_word, &buffer[last_word_offset],
  455. unaligned_bytes);
  456. status = bmilz_data(buffer, last_word_offset, ol_ctx);
  457. if (status != QDF_STATUS_SUCCESS)
  458. goto end;
  459. if (unaligned_bytes)
  460. status = bmilz_data((uint8_t *) &last_word, 4, ol_ctx);
  461. if (status != QDF_STATUS_SUCCESS)
  462. /*
  463. * Close compressed stream and open a new (fake) one.
  464. * This serves mainly to flush Target caches.
  465. */
  466. status = bmilz_stream_start(0x00, ol_ctx);
  467. end:
  468. return status;
  469. }
  470. /**
  471. * ol_cds_init() - API to initialize global CDS OL Context
  472. * @qdf_dev: QDF Device
  473. * @hif_ctx: HIF Context
  474. *
  475. * Return: Success/Failure
  476. */
  477. QDF_STATUS ol_cds_init(qdf_device_t qdf_dev, void *hif_ctx)
  478. {
  479. struct ol_context *ol_info;
  480. QDF_STATUS status = QDF_STATUS_SUCCESS;
  481. if (NO_BMI)
  482. return QDF_STATUS_SUCCESS; /* no BMI for Q6 bring up */
  483. status = cds_alloc_context(cds_get_global_context(), QDF_MODULE_ID_BMI,
  484. (void **)&ol_info, sizeof(*ol_info));
  485. if (status != QDF_STATUS_SUCCESS) {
  486. BMI_ERR("%s: CDS Allocation failed for ol_bmi context",
  487. __func__);
  488. return status;
  489. }
  490. ol_info->qdf_dev = qdf_dev;
  491. ol_info->scn = hif_ctx;
  492. ol_info->tgt_def.targetdef = hif_get_targetdef(hif_ctx);
  493. qdf_create_work(qdf_dev, &ol_info->ramdump_work, ramdump_work_handler, ol_info);
  494. return status;
  495. }
  496. /**
  497. * ol_cds_free() - API to free the global CDS OL Context
  498. *
  499. * Return: void
  500. */
  501. void ol_cds_free(void)
  502. {
  503. struct ol_context *ol_info = cds_get_context(QDF_MODULE_ID_BMI);
  504. if (NO_BMI)
  505. return;
  506. cds_free_context(cds_get_global_context(), QDF_MODULE_ID_BMI, ol_info);
  507. }