fjes_hw.c 31 KB

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