fjes_hw.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * FUJITSU Extended Socket Network Device driver
  4. * Copyright (c) 2015 FUJITSU LIMITED
  5. */
  6. #include "fjes_hw.h"
  7. #include "fjes.h"
  8. #include "fjes_trace.h"
  9. static void fjes_hw_update_zone_task(struct work_struct *);
  10. static void fjes_hw_epstop_task(struct work_struct *);
  11. /* supported MTU list */
  12. const u32 fjes_support_mtu[] = {
  13. FJES_MTU_DEFINE(8 * 1024),
  14. FJES_MTU_DEFINE(16 * 1024),
  15. FJES_MTU_DEFINE(32 * 1024),
  16. FJES_MTU_DEFINE(64 * 1024),
  17. 0
  18. };
  19. u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg)
  20. {
  21. u8 *base = hw->base;
  22. u32 value = 0;
  23. value = readl(&base[reg]);
  24. return value;
  25. }
  26. static u8 *fjes_hw_iomap(struct fjes_hw *hw)
  27. {
  28. u8 *base;
  29. if (!request_mem_region(hw->hw_res.start, hw->hw_res.size,
  30. fjes_driver_name)) {
  31. pr_err("request_mem_region failed\n");
  32. return NULL;
  33. }
  34. base = (u8 *)ioremap_nocache(hw->hw_res.start, hw->hw_res.size);
  35. return base;
  36. }
  37. static void fjes_hw_iounmap(struct fjes_hw *hw)
  38. {
  39. iounmap(hw->base);
  40. release_mem_region(hw->hw_res.start, hw->hw_res.size);
  41. }
  42. int fjes_hw_reset(struct fjes_hw *hw)
  43. {
  44. union REG_DCTL dctl;
  45. int timeout;
  46. dctl.reg = 0;
  47. dctl.bits.reset = 1;
  48. wr32(XSCT_DCTL, dctl.reg);
  49. timeout = FJES_DEVICE_RESET_TIMEOUT * 1000;
  50. dctl.reg = rd32(XSCT_DCTL);
  51. while ((dctl.bits.reset == 1) && (timeout > 0)) {
  52. msleep(1000);
  53. dctl.reg = rd32(XSCT_DCTL);
  54. timeout -= 1000;
  55. }
  56. return timeout > 0 ? 0 : -EIO;
  57. }
  58. static int fjes_hw_get_max_epid(struct fjes_hw *hw)
  59. {
  60. union REG_MAX_EP info;
  61. info.reg = rd32(XSCT_MAX_EP);
  62. return info.bits.maxep;
  63. }
  64. static int fjes_hw_get_my_epid(struct fjes_hw *hw)
  65. {
  66. union REG_OWNER_EPID info;
  67. info.reg = rd32(XSCT_OWNER_EPID);
  68. return info.bits.epid;
  69. }
  70. static int fjes_hw_alloc_shared_status_region(struct fjes_hw *hw)
  71. {
  72. size_t size;
  73. size = sizeof(struct fjes_device_shared_info) +
  74. (sizeof(u8) * hw->max_epid);
  75. hw->hw_info.share = kzalloc(size, GFP_KERNEL);
  76. if (!hw->hw_info.share)
  77. return -ENOMEM;
  78. hw->hw_info.share->epnum = hw->max_epid;
  79. return 0;
  80. }
  81. static void fjes_hw_free_shared_status_region(struct fjes_hw *hw)
  82. {
  83. kfree(hw->hw_info.share);
  84. hw->hw_info.share = NULL;
  85. }
  86. static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
  87. {
  88. void *mem;
  89. mem = vzalloc(EP_BUFFER_SIZE);
  90. if (!mem)
  91. return -ENOMEM;
  92. epbh->buffer = mem;
  93. epbh->size = EP_BUFFER_SIZE;
  94. epbh->info = (union ep_buffer_info *)mem;
  95. epbh->ring = (u8 *)(mem + sizeof(union ep_buffer_info));
  96. return 0;
  97. }
  98. static void fjes_hw_free_epbuf(struct epbuf_handler *epbh)
  99. {
  100. vfree(epbh->buffer);
  101. epbh->buffer = NULL;
  102. epbh->size = 0;
  103. epbh->info = NULL;
  104. epbh->ring = NULL;
  105. }
  106. void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
  107. {
  108. union ep_buffer_info *info = epbh->info;
  109. u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];
  110. int i;
  111. for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
  112. vlan_id[i] = info->v1i.vlan_id[i];
  113. memset(info, 0, sizeof(union ep_buffer_info));
  114. info->v1i.version = 0; /* version 0 */
  115. for (i = 0; i < ETH_ALEN; i++)
  116. info->v1i.mac_addr[i] = mac_addr[i];
  117. info->v1i.head = 0;
  118. info->v1i.tail = 1;
  119. info->v1i.info_size = sizeof(union ep_buffer_info);
  120. info->v1i.buffer_size = epbh->size - info->v1i.info_size;
  121. info->v1i.frame_max = FJES_MTU_TO_FRAME_SIZE(mtu);
  122. info->v1i.count_max =
  123. EP_RING_NUM(info->v1i.buffer_size, info->v1i.frame_max);
  124. for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
  125. info->v1i.vlan_id[i] = vlan_id[i];
  126. info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE;
  127. }
  128. void
  129. fjes_hw_init_command_registers(struct fjes_hw *hw,
  130. struct fjes_device_command_param *param)
  131. {
  132. /* Request Buffer length */
  133. wr32(XSCT_REQBL, (__le32)(param->req_len));
  134. /* Response Buffer Length */
  135. wr32(XSCT_RESPBL, (__le32)(param->res_len));
  136. /* Request Buffer Address */
  137. wr32(XSCT_REQBAL,
  138. (__le32)(param->req_start & GENMASK_ULL(31, 0)));
  139. wr32(XSCT_REQBAH,
  140. (__le32)((param->req_start & GENMASK_ULL(63, 32)) >> 32));
  141. /* Response Buffer Address */
  142. wr32(XSCT_RESPBAL,
  143. (__le32)(param->res_start & GENMASK_ULL(31, 0)));
  144. wr32(XSCT_RESPBAH,
  145. (__le32)((param->res_start & GENMASK_ULL(63, 32)) >> 32));
  146. /* Share status address */
  147. wr32(XSCT_SHSTSAL,
  148. (__le32)(param->share_start & GENMASK_ULL(31, 0)));
  149. wr32(XSCT_SHSTSAH,
  150. (__le32)((param->share_start & GENMASK_ULL(63, 32)) >> 32));
  151. }
  152. static int fjes_hw_setup(struct fjes_hw *hw)
  153. {
  154. u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  155. struct fjes_device_command_param param;
  156. struct ep_share_mem_info *buf_pair;
  157. unsigned long flags;
  158. size_t mem_size;
  159. int result;
  160. int epidx;
  161. void *buf;
  162. hw->hw_info.max_epid = &hw->max_epid;
  163. hw->hw_info.my_epid = &hw->my_epid;
  164. buf = kcalloc(hw->max_epid, sizeof(struct ep_share_mem_info),
  165. GFP_KERNEL);
  166. if (!buf)
  167. return -ENOMEM;
  168. hw->ep_shm_info = (struct ep_share_mem_info *)buf;
  169. mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid);
  170. hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL);
  171. if (!(hw->hw_info.req_buf))
  172. return -ENOMEM;
  173. hw->hw_info.req_buf_size = mem_size;
  174. mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid);
  175. hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL);
  176. if (!(hw->hw_info.res_buf))
  177. return -ENOMEM;
  178. hw->hw_info.res_buf_size = mem_size;
  179. result = fjes_hw_alloc_shared_status_region(hw);
  180. if (result)
  181. return result;
  182. hw->hw_info.buffer_share_bit = 0;
  183. hw->hw_info.buffer_unshare_reserve_bit = 0;
  184. for (epidx = 0; epidx < hw->max_epid; epidx++) {
  185. if (epidx != hw->my_epid) {
  186. buf_pair = &hw->ep_shm_info[epidx];
  187. result = fjes_hw_alloc_epbuf(&buf_pair->tx);
  188. if (result)
  189. return result;
  190. result = fjes_hw_alloc_epbuf(&buf_pair->rx);
  191. if (result)
  192. return result;
  193. spin_lock_irqsave(&hw->rx_status_lock, flags);
  194. fjes_hw_setup_epbuf(&buf_pair->tx, mac,
  195. fjes_support_mtu[0]);
  196. fjes_hw_setup_epbuf(&buf_pair->rx, mac,
  197. fjes_support_mtu[0]);
  198. spin_unlock_irqrestore(&hw->rx_status_lock, flags);
  199. }
  200. }
  201. memset(&param, 0, sizeof(param));
  202. param.req_len = hw->hw_info.req_buf_size;
  203. param.req_start = __pa(hw->hw_info.req_buf);
  204. param.res_len = hw->hw_info.res_buf_size;
  205. param.res_start = __pa(hw->hw_info.res_buf);
  206. param.share_start = __pa(hw->hw_info.share->ep_status);
  207. fjes_hw_init_command_registers(hw, &param);
  208. return 0;
  209. }
  210. static void fjes_hw_cleanup(struct fjes_hw *hw)
  211. {
  212. int epidx;
  213. if (!hw->ep_shm_info)
  214. return;
  215. fjes_hw_free_shared_status_region(hw);
  216. kfree(hw->hw_info.req_buf);
  217. hw->hw_info.req_buf = NULL;
  218. kfree(hw->hw_info.res_buf);
  219. hw->hw_info.res_buf = NULL;
  220. for (epidx = 0; epidx < hw->max_epid ; epidx++) {
  221. if (epidx == hw->my_epid)
  222. continue;
  223. fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx);
  224. fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx);
  225. }
  226. kfree(hw->ep_shm_info);
  227. hw->ep_shm_info = NULL;
  228. }
  229. int fjes_hw_init(struct fjes_hw *hw)
  230. {
  231. int ret;
  232. hw->base = fjes_hw_iomap(hw);
  233. if (!hw->base)
  234. return -EIO;
  235. ret = fjes_hw_reset(hw);
  236. if (ret)
  237. return ret;
  238. fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
  239. INIT_WORK(&hw->update_zone_task, fjes_hw_update_zone_task);
  240. INIT_WORK(&hw->epstop_task, fjes_hw_epstop_task);
  241. mutex_init(&hw->hw_info.lock);
  242. spin_lock_init(&hw->rx_status_lock);
  243. hw->max_epid = fjes_hw_get_max_epid(hw);
  244. hw->my_epid = fjes_hw_get_my_epid(hw);
  245. if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid))
  246. return -ENXIO;
  247. ret = fjes_hw_setup(hw);
  248. hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE);
  249. hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
  250. return ret;
  251. }
  252. void fjes_hw_exit(struct fjes_hw *hw)
  253. {
  254. int ret;
  255. if (hw->base) {
  256. if (hw->debug_mode) {
  257. /* disable debug mode */
  258. mutex_lock(&hw->hw_info.lock);
  259. fjes_hw_stop_debug(hw);
  260. mutex_unlock(&hw->hw_info.lock);
  261. }
  262. vfree(hw->hw_info.trace);
  263. hw->hw_info.trace = NULL;
  264. hw->hw_info.trace_size = 0;
  265. hw->debug_mode = 0;
  266. ret = fjes_hw_reset(hw);
  267. if (ret)
  268. pr_err("%s: reset error", __func__);
  269. fjes_hw_iounmap(hw);
  270. hw->base = NULL;
  271. }
  272. fjes_hw_cleanup(hw);
  273. cancel_work_sync(&hw->update_zone_task);
  274. cancel_work_sync(&hw->epstop_task);
  275. }
  276. static enum fjes_dev_command_response_e
  277. fjes_hw_issue_request_command(struct fjes_hw *hw,
  278. enum fjes_dev_command_request_type type)
  279. {
  280. enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
  281. union REG_CR cr;
  282. union REG_CS cs;
  283. int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
  284. cr.reg = 0;
  285. cr.bits.req_start = 1;
  286. cr.bits.req_code = type;
  287. wr32(XSCT_CR, cr.reg);
  288. cr.reg = rd32(XSCT_CR);
  289. if (cr.bits.error == 0) {
  290. timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
  291. cs.reg = rd32(XSCT_CS);
  292. while ((cs.bits.complete != 1) && timeout > 0) {
  293. msleep(1000);
  294. cs.reg = rd32(XSCT_CS);
  295. timeout -= 1000;
  296. }
  297. if (cs.bits.complete == 1)
  298. ret = FJES_CMD_STATUS_NORMAL;
  299. else if (timeout <= 0)
  300. ret = FJES_CMD_STATUS_TIMEOUT;
  301. } else {
  302. switch (cr.bits.err_info) {
  303. case FJES_CMD_REQ_ERR_INFO_PARAM:
  304. ret = FJES_CMD_STATUS_ERROR_PARAM;
  305. break;
  306. case FJES_CMD_REQ_ERR_INFO_STATUS:
  307. ret = FJES_CMD_STATUS_ERROR_STATUS;
  308. break;
  309. default:
  310. ret = FJES_CMD_STATUS_UNKNOWN;
  311. break;
  312. }
  313. }
  314. trace_fjes_hw_issue_request_command(&cr, &cs, timeout, ret);
  315. return ret;
  316. }
  317. int fjes_hw_request_info(struct fjes_hw *hw)
  318. {
  319. union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
  320. union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
  321. enum fjes_dev_command_response_e ret;
  322. int result;
  323. memset(req_buf, 0, hw->hw_info.req_buf_size);
  324. memset(res_buf, 0, hw->hw_info.res_buf_size);
  325. req_buf->info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;
  326. res_buf->info.length = 0;
  327. res_buf->info.code = 0;
  328. ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
  329. trace_fjes_hw_request_info(hw, res_buf);
  330. result = 0;
  331. if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
  332. res_buf->info.length) {
  333. trace_fjes_hw_request_info_err("Invalid res_buf");
  334. result = -ENOMSG;
  335. } else if (ret == FJES_CMD_STATUS_NORMAL) {
  336. switch (res_buf->info.code) {
  337. case FJES_CMD_REQ_RES_CODE_NORMAL:
  338. result = 0;
  339. break;
  340. default:
  341. result = -EPERM;
  342. break;
  343. }
  344. } else {
  345. switch (ret) {
  346. case FJES_CMD_STATUS_UNKNOWN:
  347. result = -EPERM;
  348. break;
  349. case FJES_CMD_STATUS_TIMEOUT:
  350. trace_fjes_hw_request_info_err("Timeout");
  351. result = -EBUSY;
  352. break;
  353. case FJES_CMD_STATUS_ERROR_PARAM:
  354. result = -EPERM;
  355. break;
  356. case FJES_CMD_STATUS_ERROR_STATUS:
  357. result = -EPERM;
  358. break;
  359. default:
  360. result = -EPERM;
  361. break;
  362. }
  363. }
  364. return result;
  365. }
  366. int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
  367. struct ep_share_mem_info *buf_pair)
  368. {
  369. union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
  370. union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
  371. enum fjes_dev_command_response_e ret;
  372. int page_count;
  373. int timeout;
  374. int i, idx;
  375. void *addr;
  376. int result;
  377. if (test_bit(dest_epid, &hw->hw_info.buffer_share_bit))
  378. return 0;
  379. memset(req_buf, 0, hw->hw_info.req_buf_size);
  380. memset(res_buf, 0, hw->hw_info.res_buf_size);
  381. req_buf->share_buffer.length = FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(
  382. buf_pair->tx.size,
  383. buf_pair->rx.size);
  384. req_buf->share_buffer.epid = dest_epid;
  385. idx = 0;
  386. req_buf->share_buffer.buffer[idx++] = buf_pair->tx.size;
  387. page_count = buf_pair->tx.size / EP_BUFFER_INFO_SIZE;
  388. for (i = 0; i < page_count; i++) {
  389. addr = ((u8 *)(buf_pair->tx.buffer)) +
  390. (i * EP_BUFFER_INFO_SIZE);
  391. req_buf->share_buffer.buffer[idx++] =
  392. (__le64)(page_to_phys(vmalloc_to_page(addr)) +
  393. offset_in_page(addr));
  394. }
  395. req_buf->share_buffer.buffer[idx++] = buf_pair->rx.size;
  396. page_count = buf_pair->rx.size / EP_BUFFER_INFO_SIZE;
  397. for (i = 0; i < page_count; i++) {
  398. addr = ((u8 *)(buf_pair->rx.buffer)) +
  399. (i * EP_BUFFER_INFO_SIZE);
  400. req_buf->share_buffer.buffer[idx++] =
  401. (__le64)(page_to_phys(vmalloc_to_page(addr)) +
  402. offset_in_page(addr));
  403. }
  404. res_buf->share_buffer.length = 0;
  405. res_buf->share_buffer.code = 0;
  406. trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
  407. ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
  408. timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
  409. while ((ret == FJES_CMD_STATUS_NORMAL) &&
  410. (res_buf->share_buffer.length ==
  411. FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) &&
  412. (res_buf->share_buffer.code == FJES_CMD_REQ_RES_CODE_BUSY) &&
  413. (timeout > 0)) {
  414. msleep(200 + hw->my_epid * 20);
  415. timeout -= (200 + hw->my_epid * 20);
  416. res_buf->share_buffer.length = 0;
  417. res_buf->share_buffer.code = 0;
  418. ret = fjes_hw_issue_request_command(
  419. hw, FJES_CMD_REQ_SHARE_BUFFER);
  420. }
  421. result = 0;
  422. trace_fjes_hw_register_buff_addr(res_buf, timeout);
  423. if (res_buf->share_buffer.length !=
  424. FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
  425. trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
  426. result = -ENOMSG;
  427. } else if (ret == FJES_CMD_STATUS_NORMAL) {
  428. switch (res_buf->share_buffer.code) {
  429. case FJES_CMD_REQ_RES_CODE_NORMAL:
  430. result = 0;
  431. set_bit(dest_epid, &hw->hw_info.buffer_share_bit);
  432. break;
  433. case FJES_CMD_REQ_RES_CODE_BUSY:
  434. trace_fjes_hw_register_buff_addr_err("Busy Timeout");
  435. result = -EBUSY;
  436. break;
  437. default:
  438. result = -EPERM;
  439. break;
  440. }
  441. } else {
  442. switch (ret) {
  443. case FJES_CMD_STATUS_UNKNOWN:
  444. result = -EPERM;
  445. break;
  446. case FJES_CMD_STATUS_TIMEOUT:
  447. trace_fjes_hw_register_buff_addr_err("Timeout");
  448. result = -EBUSY;
  449. break;
  450. case FJES_CMD_STATUS_ERROR_PARAM:
  451. case FJES_CMD_STATUS_ERROR_STATUS:
  452. default:
  453. result = -EPERM;
  454. break;
  455. }
  456. }
  457. return result;
  458. }
  459. int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
  460. {
  461. union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
  462. union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
  463. struct fjes_device_shared_info *share = hw->hw_info.share;
  464. enum fjes_dev_command_response_e ret;
  465. int timeout;
  466. int result;
  467. if (!hw->base)
  468. return -EPERM;
  469. if (!req_buf || !res_buf || !share)
  470. return -EPERM;
  471. if (!test_bit(dest_epid, &hw->hw_info.buffer_share_bit))
  472. return 0;
  473. memset(req_buf, 0, hw->hw_info.req_buf_size);
  474. memset(res_buf, 0, hw->hw_info.res_buf_size);
  475. req_buf->unshare_buffer.length =
  476. FJES_DEV_COMMAND_UNSHARE_BUFFER_REQ_LEN;
  477. req_buf->unshare_buffer.epid = dest_epid;
  478. res_buf->unshare_buffer.length = 0;
  479. res_buf->unshare_buffer.code = 0;
  480. trace_fjes_hw_unregister_buff_addr_req(req_buf);
  481. ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
  482. timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
  483. while ((ret == FJES_CMD_STATUS_NORMAL) &&
  484. (res_buf->unshare_buffer.length ==
  485. FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) &&
  486. (res_buf->unshare_buffer.code ==
  487. FJES_CMD_REQ_RES_CODE_BUSY) &&
  488. (timeout > 0)) {
  489. msleep(200 + hw->my_epid * 20);
  490. timeout -= (200 + hw->my_epid * 20);
  491. res_buf->unshare_buffer.length = 0;
  492. res_buf->unshare_buffer.code = 0;
  493. ret =
  494. fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
  495. }
  496. result = 0;
  497. trace_fjes_hw_unregister_buff_addr(res_buf, timeout);
  498. if (res_buf->unshare_buffer.length !=
  499. FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) {
  500. trace_fjes_hw_unregister_buff_addr_err("Invalid res_buf");
  501. result = -ENOMSG;
  502. } else if (ret == FJES_CMD_STATUS_NORMAL) {
  503. switch (res_buf->unshare_buffer.code) {
  504. case FJES_CMD_REQ_RES_CODE_NORMAL:
  505. result = 0;
  506. clear_bit(dest_epid, &hw->hw_info.buffer_share_bit);
  507. break;
  508. case FJES_CMD_REQ_RES_CODE_BUSY:
  509. trace_fjes_hw_unregister_buff_addr_err("Busy Timeout");
  510. result = -EBUSY;
  511. break;
  512. default:
  513. result = -EPERM;
  514. break;
  515. }
  516. } else {
  517. switch (ret) {
  518. case FJES_CMD_STATUS_UNKNOWN:
  519. result = -EPERM;
  520. break;
  521. case FJES_CMD_STATUS_TIMEOUT:
  522. trace_fjes_hw_unregister_buff_addr_err("Timeout");
  523. result = -EBUSY;
  524. break;
  525. case FJES_CMD_STATUS_ERROR_PARAM:
  526. case FJES_CMD_STATUS_ERROR_STATUS:
  527. default:
  528. result = -EPERM;
  529. break;
  530. }
  531. }
  532. return result;
  533. }
  534. int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid,
  535. enum REG_ICTL_MASK mask)
  536. {
  537. u32 ig = mask | dest_epid;
  538. wr32(XSCT_IG, cpu_to_le32(ig));
  539. return 0;
  540. }
  541. u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw)
  542. {
  543. u32 cur_is;
  544. cur_is = rd32(XSCT_IS);
  545. return cur_is;
  546. }
  547. void fjes_hw_set_irqmask(struct fjes_hw *hw,
  548. enum REG_ICTL_MASK intr_mask, bool mask)
  549. {
  550. if (mask)
  551. wr32(XSCT_IMS, intr_mask);
  552. else
  553. wr32(XSCT_IMC, intr_mask);
  554. }
  555. bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid)
  556. {
  557. if (epid >= hw->max_epid)
  558. return false;
  559. if ((hw->ep_shm_info[epid].es_status !=
  560. FJES_ZONING_STATUS_ENABLE) ||
  561. (hw->ep_shm_info[hw->my_epid].zone ==
  562. FJES_ZONING_ZONE_TYPE_NONE))
  563. return false;
  564. else
  565. return (hw->ep_shm_info[epid].zone ==
  566. hw->ep_shm_info[hw->my_epid].zone);
  567. }
  568. int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share,
  569. int dest_epid)
  570. {
  571. int value = false;
  572. if (dest_epid < share->epnum)
  573. value = share->ep_status[dest_epid];
  574. return value;
  575. }
  576. static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid)
  577. {
  578. return test_bit(src_epid, &hw->txrx_stop_req_bit);
  579. }
  580. static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid)
  581. {
  582. return (hw->ep_shm_info[src_epid].tx.info->v1i.rx_status &
  583. FJES_RX_STOP_REQ_DONE);
  584. }
  585. enum ep_partner_status
  586. fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
  587. {
  588. enum ep_partner_status status;
  589. if (fjes_hw_epid_is_shared(hw->hw_info.share, epid)) {
  590. if (fjes_hw_epid_is_stop_requested(hw, epid)) {
  591. status = EP_PARTNER_WAITING;
  592. } else {
  593. if (fjes_hw_epid_is_stop_process_done(hw, epid))
  594. status = EP_PARTNER_COMPLETE;
  595. else
  596. status = EP_PARTNER_SHARED;
  597. }
  598. } else {
  599. status = EP_PARTNER_UNSHARE;
  600. }
  601. return status;
  602. }
  603. void fjes_hw_raise_epstop(struct fjes_hw *hw)
  604. {
  605. enum ep_partner_status status;
  606. unsigned long flags;
  607. int epidx;
  608. for (epidx = 0; epidx < hw->max_epid; epidx++) {
  609. if (epidx == hw->my_epid)
  610. continue;
  611. status = fjes_hw_get_partner_ep_status(hw, epidx);
  612. switch (status) {
  613. case EP_PARTNER_SHARED:
  614. fjes_hw_raise_interrupt(hw, epidx,
  615. REG_ICTL_MASK_TXRX_STOP_REQ);
  616. hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
  617. break;
  618. default:
  619. break;
  620. }
  621. set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
  622. set_bit(epidx, &hw->txrx_stop_req_bit);
  623. spin_lock_irqsave(&hw->rx_status_lock, flags);
  624. hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
  625. FJES_RX_STOP_REQ_REQUEST;
  626. spin_unlock_irqrestore(&hw->rx_status_lock, flags);
  627. }
  628. }
  629. int fjes_hw_wait_epstop(struct fjes_hw *hw)
  630. {
  631. enum ep_partner_status status;
  632. union ep_buffer_info *info;
  633. int wait_time = 0;
  634. int epidx;
  635. while (hw->hw_info.buffer_unshare_reserve_bit &&
  636. (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) {
  637. for (epidx = 0; epidx < hw->max_epid; epidx++) {
  638. if (epidx == hw->my_epid)
  639. continue;
  640. status = fjes_hw_epid_is_shared(hw->hw_info.share,
  641. epidx);
  642. info = hw->ep_shm_info[epidx].rx.info;
  643. if ((!status ||
  644. (info->v1i.rx_status &
  645. FJES_RX_STOP_REQ_DONE)) &&
  646. test_bit(epidx,
  647. &hw->hw_info.buffer_unshare_reserve_bit)) {
  648. clear_bit(epidx,
  649. &hw->hw_info.buffer_unshare_reserve_bit);
  650. }
  651. }
  652. msleep(100);
  653. wait_time += 100;
  654. }
  655. for (epidx = 0; epidx < hw->max_epid; epidx++) {
  656. if (epidx == hw->my_epid)
  657. continue;
  658. if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit))
  659. clear_bit(epidx,
  660. &hw->hw_info.buffer_unshare_reserve_bit);
  661. }
  662. return (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)
  663. ? 0 : -EBUSY;
  664. }
  665. bool fjes_hw_check_epbuf_version(struct epbuf_handler *epbh, u32 version)
  666. {
  667. union ep_buffer_info *info = epbh->info;
  668. return (info->common.version == version);
  669. }
  670. bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu)
  671. {
  672. union ep_buffer_info *info = epbh->info;
  673. return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) &&
  674. info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE);
  675. }
  676. bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
  677. {
  678. union ep_buffer_info *info = epbh->info;
  679. bool ret = false;
  680. int i;
  681. if (vlan_id == 0) {
  682. ret = true;
  683. } else {
  684. for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
  685. if (vlan_id == info->v1i.vlan_id[i]) {
  686. ret = true;
  687. break;
  688. }
  689. }
  690. }
  691. return ret;
  692. }
  693. bool fjes_hw_set_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
  694. {
  695. union ep_buffer_info *info = epbh->info;
  696. int i;
  697. for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
  698. if (info->v1i.vlan_id[i] == 0) {
  699. info->v1i.vlan_id[i] = vlan_id;
  700. return true;
  701. }
  702. }
  703. return false;
  704. }
  705. void fjes_hw_del_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
  706. {
  707. union ep_buffer_info *info = epbh->info;
  708. int i;
  709. if (0 != vlan_id) {
  710. for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
  711. if (vlan_id == info->v1i.vlan_id[i])
  712. info->v1i.vlan_id[i] = 0;
  713. }
  714. }
  715. }
  716. bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
  717. {
  718. union ep_buffer_info *info = epbh->info;
  719. if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
  720. return true;
  721. if (info->v1i.count_max == 0)
  722. return true;
  723. return EP_RING_EMPTY(info->v1i.head, info->v1i.tail,
  724. info->v1i.count_max);
  725. }
  726. void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
  727. size_t *psize)
  728. {
  729. union ep_buffer_info *info = epbh->info;
  730. struct esmem_frame *ring_frame;
  731. void *frame;
  732. ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
  733. (info->v1i.head,
  734. info->v1i.count_max) *
  735. info->v1i.frame_max]);
  736. *psize = (size_t)ring_frame->frame_size;
  737. frame = ring_frame->frame_data;
  738. return frame;
  739. }
  740. void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
  741. {
  742. union ep_buffer_info *info = epbh->info;
  743. if (fjes_hw_epbuf_rx_is_empty(epbh))
  744. return;
  745. EP_RING_INDEX_INC(epbh->info->v1i.head, info->v1i.count_max);
  746. }
  747. int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
  748. void *frame, size_t size)
  749. {
  750. union ep_buffer_info *info = epbh->info;
  751. struct esmem_frame *ring_frame;
  752. if (EP_RING_FULL(info->v1i.head, info->v1i.tail, info->v1i.count_max))
  753. return -ENOBUFS;
  754. ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
  755. (info->v1i.tail - 1,
  756. info->v1i.count_max) *
  757. info->v1i.frame_max]);
  758. ring_frame->frame_size = size;
  759. memcpy((void *)(ring_frame->frame_data), (void *)frame, size);
  760. EP_RING_INDEX_INC(epbh->info->v1i.tail, info->v1i.count_max);
  761. return 0;
  762. }
  763. static void fjes_hw_update_zone_task(struct work_struct *work)
  764. {
  765. struct fjes_hw *hw = container_of(work,
  766. struct fjes_hw, update_zone_task);
  767. struct my_s {u8 es_status; u8 zone; } *info;
  768. union fjes_device_command_res *res_buf;
  769. enum ep_partner_status pstatus;
  770. struct fjes_adapter *adapter;
  771. struct net_device *netdev;
  772. unsigned long flags;
  773. ulong unshare_bit = 0;
  774. ulong share_bit = 0;
  775. ulong irq_bit = 0;
  776. int epidx;
  777. int ret;
  778. adapter = (struct fjes_adapter *)hw->back;
  779. netdev = adapter->netdev;
  780. res_buf = hw->hw_info.res_buf;
  781. info = (struct my_s *)&res_buf->info.info;
  782. mutex_lock(&hw->hw_info.lock);
  783. ret = fjes_hw_request_info(hw);
  784. switch (ret) {
  785. case -ENOMSG:
  786. case -EBUSY:
  787. default:
  788. if (!work_pending(&adapter->force_close_task)) {
  789. adapter->force_reset = true;
  790. schedule_work(&adapter->force_close_task);
  791. }
  792. break;
  793. case 0:
  794. for (epidx = 0; epidx < hw->max_epid; epidx++) {
  795. if (epidx == hw->my_epid) {
  796. hw->ep_shm_info[epidx].es_status =
  797. info[epidx].es_status;
  798. hw->ep_shm_info[epidx].zone =
  799. info[epidx].zone;
  800. continue;
  801. }
  802. pstatus = fjes_hw_get_partner_ep_status(hw, epidx);
  803. switch (pstatus) {
  804. case EP_PARTNER_UNSHARE:
  805. default:
  806. if ((info[epidx].zone !=
  807. FJES_ZONING_ZONE_TYPE_NONE) &&
  808. (info[epidx].es_status ==
  809. FJES_ZONING_STATUS_ENABLE) &&
  810. (info[epidx].zone ==
  811. info[hw->my_epid].zone))
  812. set_bit(epidx, &share_bit);
  813. else
  814. set_bit(epidx, &unshare_bit);
  815. break;
  816. case EP_PARTNER_COMPLETE:
  817. case EP_PARTNER_WAITING:
  818. if ((info[epidx].zone ==
  819. FJES_ZONING_ZONE_TYPE_NONE) ||
  820. (info[epidx].es_status !=
  821. FJES_ZONING_STATUS_ENABLE) ||
  822. (info[epidx].zone !=
  823. info[hw->my_epid].zone)) {
  824. set_bit(epidx,
  825. &adapter->unshare_watch_bitmask);
  826. set_bit(epidx,
  827. &hw->hw_info.buffer_unshare_reserve_bit);
  828. }
  829. break;
  830. case EP_PARTNER_SHARED:
  831. if ((info[epidx].zone ==
  832. FJES_ZONING_ZONE_TYPE_NONE) ||
  833. (info[epidx].es_status !=
  834. FJES_ZONING_STATUS_ENABLE) ||
  835. (info[epidx].zone !=
  836. info[hw->my_epid].zone))
  837. set_bit(epidx, &irq_bit);
  838. break;
  839. }
  840. hw->ep_shm_info[epidx].es_status =
  841. info[epidx].es_status;
  842. hw->ep_shm_info[epidx].zone = info[epidx].zone;
  843. }
  844. break;
  845. }
  846. mutex_unlock(&hw->hw_info.lock);
  847. for (epidx = 0; epidx < hw->max_epid; epidx++) {
  848. if (epidx == hw->my_epid)
  849. continue;
  850. if (test_bit(epidx, &share_bit)) {
  851. spin_lock_irqsave(&hw->rx_status_lock, flags);
  852. fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
  853. netdev->dev_addr, netdev->mtu);
  854. spin_unlock_irqrestore(&hw->rx_status_lock, flags);
  855. mutex_lock(&hw->hw_info.lock);
  856. ret = fjes_hw_register_buff_addr(
  857. hw, epidx, &hw->ep_shm_info[epidx]);
  858. switch (ret) {
  859. case 0:
  860. break;
  861. case -ENOMSG:
  862. case -EBUSY:
  863. default:
  864. if (!work_pending(&adapter->force_close_task)) {
  865. adapter->force_reset = true;
  866. schedule_work(
  867. &adapter->force_close_task);
  868. }
  869. break;
  870. }
  871. mutex_unlock(&hw->hw_info.lock);
  872. hw->ep_shm_info[epidx].ep_stats
  873. .com_regist_buf_exec += 1;
  874. }
  875. if (test_bit(epidx, &unshare_bit)) {
  876. mutex_lock(&hw->hw_info.lock);
  877. ret = fjes_hw_unregister_buff_addr(hw, epidx);
  878. switch (ret) {
  879. case 0:
  880. break;
  881. case -ENOMSG:
  882. case -EBUSY:
  883. default:
  884. if (!work_pending(&adapter->force_close_task)) {
  885. adapter->force_reset = true;
  886. schedule_work(
  887. &adapter->force_close_task);
  888. }
  889. break;
  890. }
  891. mutex_unlock(&hw->hw_info.lock);
  892. hw->ep_shm_info[epidx].ep_stats
  893. .com_unregist_buf_exec += 1;
  894. if (ret == 0) {
  895. spin_lock_irqsave(&hw->rx_status_lock, flags);
  896. fjes_hw_setup_epbuf(
  897. &hw->ep_shm_info[epidx].tx,
  898. netdev->dev_addr, netdev->mtu);
  899. spin_unlock_irqrestore(&hw->rx_status_lock,
  900. flags);
  901. }
  902. }
  903. if (test_bit(epidx, &irq_bit)) {
  904. fjes_hw_raise_interrupt(hw, epidx,
  905. REG_ICTL_MASK_TXRX_STOP_REQ);
  906. hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
  907. set_bit(epidx, &hw->txrx_stop_req_bit);
  908. spin_lock_irqsave(&hw->rx_status_lock, flags);
  909. hw->ep_shm_info[epidx].tx.
  910. info->v1i.rx_status |=
  911. FJES_RX_STOP_REQ_REQUEST;
  912. spin_unlock_irqrestore(&hw->rx_status_lock, flags);
  913. set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
  914. }
  915. }
  916. if (irq_bit || adapter->unshare_watch_bitmask) {
  917. if (!work_pending(&adapter->unshare_watch_task))
  918. queue_work(adapter->control_wq,
  919. &adapter->unshare_watch_task);
  920. }
  921. }
  922. static void fjes_hw_epstop_task(struct work_struct *work)
  923. {
  924. struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task);
  925. struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back;
  926. unsigned long flags;
  927. ulong remain_bit;
  928. int epid_bit;
  929. while ((remain_bit = hw->epstop_req_bit)) {
  930. for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) {
  931. if (remain_bit & 1) {
  932. spin_lock_irqsave(&hw->rx_status_lock, flags);
  933. hw->ep_shm_info[epid_bit].
  934. tx.info->v1i.rx_status |=
  935. FJES_RX_STOP_REQ_DONE;
  936. spin_unlock_irqrestore(&hw->rx_status_lock,
  937. flags);
  938. clear_bit(epid_bit, &hw->epstop_req_bit);
  939. set_bit(epid_bit,
  940. &adapter->unshare_watch_bitmask);
  941. if (!work_pending(&adapter->unshare_watch_task))
  942. queue_work(
  943. adapter->control_wq,
  944. &adapter->unshare_watch_task);
  945. }
  946. }
  947. }
  948. }
  949. int fjes_hw_start_debug(struct fjes_hw *hw)
  950. {
  951. union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
  952. union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
  953. enum fjes_dev_command_response_e ret;
  954. int page_count;
  955. int result = 0;
  956. void *addr;
  957. int i;
  958. if (!hw->hw_info.trace)
  959. return -EPERM;
  960. memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE);
  961. memset(req_buf, 0, hw->hw_info.req_buf_size);
  962. memset(res_buf, 0, hw->hw_info.res_buf_size);
  963. req_buf->start_trace.length =
  964. FJES_DEV_COMMAND_START_DBG_REQ_LEN(hw->hw_info.trace_size);
  965. req_buf->start_trace.mode = hw->debug_mode;
  966. req_buf->start_trace.buffer_len = hw->hw_info.trace_size;
  967. page_count = hw->hw_info.trace_size / FJES_DEBUG_PAGE_SIZE;
  968. for (i = 0; i < page_count; i++) {
  969. addr = ((u8 *)hw->hw_info.trace) + i * FJES_DEBUG_PAGE_SIZE;
  970. req_buf->start_trace.buffer[i] =
  971. (__le64)(page_to_phys(vmalloc_to_page(addr)) +
  972. offset_in_page(addr));
  973. }
  974. res_buf->start_trace.length = 0;
  975. res_buf->start_trace.code = 0;
  976. trace_fjes_hw_start_debug_req(req_buf);
  977. ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_DEBUG);
  978. trace_fjes_hw_start_debug(res_buf);
  979. if (res_buf->start_trace.length !=
  980. FJES_DEV_COMMAND_START_DBG_RES_LEN) {
  981. result = -ENOMSG;
  982. trace_fjes_hw_start_debug_err("Invalid res_buf");
  983. } else if (ret == FJES_CMD_STATUS_NORMAL) {
  984. switch (res_buf->start_trace.code) {
  985. case FJES_CMD_REQ_RES_CODE_NORMAL:
  986. result = 0;
  987. break;
  988. default:
  989. result = -EPERM;
  990. break;
  991. }
  992. } else {
  993. switch (ret) {
  994. case FJES_CMD_STATUS_UNKNOWN:
  995. result = -EPERM;
  996. break;
  997. case FJES_CMD_STATUS_TIMEOUT:
  998. trace_fjes_hw_start_debug_err("Busy Timeout");
  999. result = -EBUSY;
  1000. break;
  1001. case FJES_CMD_STATUS_ERROR_PARAM:
  1002. case FJES_CMD_STATUS_ERROR_STATUS:
  1003. default:
  1004. result = -EPERM;
  1005. break;
  1006. }
  1007. }
  1008. return result;
  1009. }
  1010. int fjes_hw_stop_debug(struct fjes_hw *hw)
  1011. {
  1012. union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
  1013. union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
  1014. enum fjes_dev_command_response_e ret;
  1015. int result = 0;
  1016. if (!hw->hw_info.trace)
  1017. return -EPERM;
  1018. memset(req_buf, 0, hw->hw_info.req_buf_size);
  1019. memset(res_buf, 0, hw->hw_info.res_buf_size);
  1020. req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_DBG_REQ_LEN;
  1021. res_buf->stop_trace.length = 0;
  1022. res_buf->stop_trace.code = 0;
  1023. ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_DEBUG);
  1024. trace_fjes_hw_stop_debug(res_buf);
  1025. if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_DBG_RES_LEN) {
  1026. trace_fjes_hw_stop_debug_err("Invalid res_buf");
  1027. result = -ENOMSG;
  1028. } else if (ret == FJES_CMD_STATUS_NORMAL) {
  1029. switch (res_buf->stop_trace.code) {
  1030. case FJES_CMD_REQ_RES_CODE_NORMAL:
  1031. result = 0;
  1032. hw->debug_mode = 0;
  1033. break;
  1034. default:
  1035. result = -EPERM;
  1036. break;
  1037. }
  1038. } else {
  1039. switch (ret) {
  1040. case FJES_CMD_STATUS_UNKNOWN:
  1041. result = -EPERM;
  1042. break;
  1043. case FJES_CMD_STATUS_TIMEOUT:
  1044. result = -EBUSY;
  1045. trace_fjes_hw_stop_debug_err("Busy Timeout");
  1046. break;
  1047. case FJES_CMD_STATUS_ERROR_PARAM:
  1048. case FJES_CMD_STATUS_ERROR_STATUS:
  1049. default:
  1050. result = -EPERM;
  1051. break;
  1052. }
  1053. }
  1054. return result;
  1055. }