Merge tag 'mips_fixes_4.21_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips...
[linux-2.6-block.git] / drivers / net / fjes / fjes_hw.c
CommitLineData
8cdc3f6c
TI
1/*
2 * FUJITSU Extended Socket Network Device driver
3 * Copyright (c) 2015 FUJITSU LIMITED
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * The full GNU General Public License is included in this distribution in
18 * the file called "COPYING".
19 *
20 */
21
22#include "fjes_hw.h"
23#include "fjes.h"
82f6aea8 24#include "fjes_trace.h"
8cdc3f6c 25
785f28e0 26static void fjes_hw_update_zone_task(struct work_struct *);
b5a9152d 27static void fjes_hw_epstop_task(struct work_struct *);
785f28e0 28
8cdc3f6c
TI
29/* supported MTU list */
30const u32 fjes_support_mtu[] = {
31 FJES_MTU_DEFINE(8 * 1024),
32 FJES_MTU_DEFINE(16 * 1024),
33 FJES_MTU_DEFINE(32 * 1024),
34 FJES_MTU_DEFINE(64 * 1024),
35 0
36};
37
38u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg)
39{
40 u8 *base = hw->base;
41 u32 value = 0;
42
43 value = readl(&base[reg]);
44
45 return value;
46}
47
48static u8 *fjes_hw_iomap(struct fjes_hw *hw)
49{
50 u8 *base;
51
52 if (!request_mem_region(hw->hw_res.start, hw->hw_res.size,
53 fjes_driver_name)) {
54 pr_err("request_mem_region failed\n");
55 return NULL;
56 }
57
58 base = (u8 *)ioremap_nocache(hw->hw_res.start, hw->hw_res.size);
59
60 return base;
61}
62
a18aaec2
TI
63static void fjes_hw_iounmap(struct fjes_hw *hw)
64{
65 iounmap(hw->base);
66 release_mem_region(hw->hw_res.start, hw->hw_res.size);
67}
68
8cdc3f6c
TI
69int fjes_hw_reset(struct fjes_hw *hw)
70{
71 union REG_DCTL dctl;
72 int timeout;
73
74 dctl.reg = 0;
75 dctl.bits.reset = 1;
76 wr32(XSCT_DCTL, dctl.reg);
77
78 timeout = FJES_DEVICE_RESET_TIMEOUT * 1000;
79 dctl.reg = rd32(XSCT_DCTL);
80 while ((dctl.bits.reset == 1) && (timeout > 0)) {
81 msleep(1000);
82 dctl.reg = rd32(XSCT_DCTL);
83 timeout -= 1000;
84 }
85
86 return timeout > 0 ? 0 : -EIO;
87}
88
89static int fjes_hw_get_max_epid(struct fjes_hw *hw)
90{
91 union REG_MAX_EP info;
92
93 info.reg = rd32(XSCT_MAX_EP);
94
95 return info.bits.maxep;
96}
97
98static int fjes_hw_get_my_epid(struct fjes_hw *hw)
99{
100 union REG_OWNER_EPID info;
101
102 info.reg = rd32(XSCT_OWNER_EPID);
103
104 return info.bits.epid;
105}
106
107static int fjes_hw_alloc_shared_status_region(struct fjes_hw *hw)
108{
109 size_t size;
110
111 size = sizeof(struct fjes_device_shared_info) +
112 (sizeof(u8) * hw->max_epid);
113 hw->hw_info.share = kzalloc(size, GFP_KERNEL);
114 if (!hw->hw_info.share)
115 return -ENOMEM;
116
117 hw->hw_info.share->epnum = hw->max_epid;
118
119 return 0;
120}
121
a18aaec2
TI
122static void fjes_hw_free_shared_status_region(struct fjes_hw *hw)
123{
124 kfree(hw->hw_info.share);
125 hw->hw_info.share = NULL;
126}
127
8cdc3f6c
TI
128static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
129{
130 void *mem;
131
132 mem = vzalloc(EP_BUFFER_SIZE);
133 if (!mem)
134 return -ENOMEM;
135
136 epbh->buffer = mem;
137 epbh->size = EP_BUFFER_SIZE;
138
139 epbh->info = (union ep_buffer_info *)mem;
140 epbh->ring = (u8 *)(mem + sizeof(union ep_buffer_info));
141
142 return 0;
143}
144
a18aaec2
TI
145static void fjes_hw_free_epbuf(struct epbuf_handler *epbh)
146{
f7b5964d 147 vfree(epbh->buffer);
a18aaec2
TI
148 epbh->buffer = NULL;
149 epbh->size = 0;
150
151 epbh->info = NULL;
152 epbh->ring = NULL;
153}
154
8cdc3f6c
TI
155void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
156{
157 union ep_buffer_info *info = epbh->info;
158 u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];
159 int i;
160
161 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
162 vlan_id[i] = info->v1i.vlan_id[i];
163
164 memset(info, 0, sizeof(union ep_buffer_info));
165
166 info->v1i.version = 0; /* version 0 */
167
168 for (i = 0; i < ETH_ALEN; i++)
169 info->v1i.mac_addr[i] = mac_addr[i];
170
171 info->v1i.head = 0;
172 info->v1i.tail = 1;
173
174 info->v1i.info_size = sizeof(union ep_buffer_info);
175 info->v1i.buffer_size = epbh->size - info->v1i.info_size;
176
177 info->v1i.frame_max = FJES_MTU_TO_FRAME_SIZE(mtu);
178 info->v1i.count_max =
179 EP_RING_NUM(info->v1i.buffer_size, info->v1i.frame_max);
180
181 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
182 info->v1i.vlan_id[i] = vlan_id[i];
16bbec3a
TI
183
184 info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE;
8cdc3f6c
TI
185}
186
187void
188fjes_hw_init_command_registers(struct fjes_hw *hw,
189 struct fjes_device_command_param *param)
190{
191 /* Request Buffer length */
192 wr32(XSCT_REQBL, (__le32)(param->req_len));
193 /* Response Buffer Length */
194 wr32(XSCT_RESPBL, (__le32)(param->res_len));
195
196 /* Request Buffer Address */
197 wr32(XSCT_REQBAL,
198 (__le32)(param->req_start & GENMASK_ULL(31, 0)));
199 wr32(XSCT_REQBAH,
200 (__le32)((param->req_start & GENMASK_ULL(63, 32)) >> 32));
201
202 /* Response Buffer Address */
203 wr32(XSCT_RESPBAL,
204 (__le32)(param->res_start & GENMASK_ULL(31, 0)));
205 wr32(XSCT_RESPBAH,
206 (__le32)((param->res_start & GENMASK_ULL(63, 32)) >> 32));
207
208 /* Share status address */
209 wr32(XSCT_SHSTSAL,
210 (__le32)(param->share_start & GENMASK_ULL(31, 0)));
211 wr32(XSCT_SHSTSAH,
212 (__le32)((param->share_start & GENMASK_ULL(63, 32)) >> 32));
213}
214
215static int fjes_hw_setup(struct fjes_hw *hw)
216{
217 u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
218 struct fjes_device_command_param param;
219 struct ep_share_mem_info *buf_pair;
bd5a2569 220 unsigned long flags;
8cdc3f6c
TI
221 size_t mem_size;
222 int result;
223 int epidx;
224 void *buf;
225
226 hw->hw_info.max_epid = &hw->max_epid;
227 hw->hw_info.my_epid = &hw->my_epid;
228
229 buf = kcalloc(hw->max_epid, sizeof(struct ep_share_mem_info),
230 GFP_KERNEL);
231 if (!buf)
232 return -ENOMEM;
233
234 hw->ep_shm_info = (struct ep_share_mem_info *)buf;
235
236 mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid);
237 hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL);
238 if (!(hw->hw_info.req_buf))
239 return -ENOMEM;
240
241 hw->hw_info.req_buf_size = mem_size;
242
243 mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid);
244 hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL);
245 if (!(hw->hw_info.res_buf))
246 return -ENOMEM;
247
248 hw->hw_info.res_buf_size = mem_size;
249
250 result = fjes_hw_alloc_shared_status_region(hw);
251 if (result)
252 return result;
253
254 hw->hw_info.buffer_share_bit = 0;
255 hw->hw_info.buffer_unshare_reserve_bit = 0;
256
257 for (epidx = 0; epidx < hw->max_epid; epidx++) {
258 if (epidx != hw->my_epid) {
259 buf_pair = &hw->ep_shm_info[epidx];
260
261 result = fjes_hw_alloc_epbuf(&buf_pair->tx);
262 if (result)
263 return result;
264
265 result = fjes_hw_alloc_epbuf(&buf_pair->rx);
266 if (result)
267 return result;
268
bd5a2569 269 spin_lock_irqsave(&hw->rx_status_lock, flags);
8cdc3f6c
TI
270 fjes_hw_setup_epbuf(&buf_pair->tx, mac,
271 fjes_support_mtu[0]);
272 fjes_hw_setup_epbuf(&buf_pair->rx, mac,
273 fjes_support_mtu[0]);
bd5a2569 274 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
8cdc3f6c
TI
275 }
276 }
277
278 memset(&param, 0, sizeof(param));
279
280 param.req_len = hw->hw_info.req_buf_size;
281 param.req_start = __pa(hw->hw_info.req_buf);
282 param.res_len = hw->hw_info.res_buf_size;
283 param.res_start = __pa(hw->hw_info.res_buf);
284
285 param.share_start = __pa(hw->hw_info.share->ep_status);
286
287 fjes_hw_init_command_registers(hw, &param);
288
289 return 0;
290}
291
a18aaec2
TI
292static void fjes_hw_cleanup(struct fjes_hw *hw)
293{
294 int epidx;
295
296 if (!hw->ep_shm_info)
297 return;
298
299 fjes_hw_free_shared_status_region(hw);
300
301 kfree(hw->hw_info.req_buf);
302 hw->hw_info.req_buf = NULL;
303
304 kfree(hw->hw_info.res_buf);
305 hw->hw_info.res_buf = NULL;
306
307 for (epidx = 0; epidx < hw->max_epid ; epidx++) {
308 if (epidx == hw->my_epid)
309 continue;
310 fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx);
311 fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx);
312 }
313
314 kfree(hw->ep_shm_info);
315 hw->ep_shm_info = NULL;
316}
317
8cdc3f6c
TI
318int fjes_hw_init(struct fjes_hw *hw)
319{
320 int ret;
321
322 hw->base = fjes_hw_iomap(hw);
323 if (!hw->base)
324 return -EIO;
325
326 ret = fjes_hw_reset(hw);
327 if (ret)
328 return ret;
329
330 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
331
785f28e0 332 INIT_WORK(&hw->update_zone_task, fjes_hw_update_zone_task);
b5a9152d 333 INIT_WORK(&hw->epstop_task, fjes_hw_epstop_task);
785f28e0 334
8cdc3f6c 335 mutex_init(&hw->hw_info.lock);
bd5a2569 336 spin_lock_init(&hw->rx_status_lock);
8cdc3f6c
TI
337
338 hw->max_epid = fjes_hw_get_max_epid(hw);
339 hw->my_epid = fjes_hw_get_my_epid(hw);
340
341 if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid))
342 return -ENXIO;
343
344 ret = fjes_hw_setup(hw);
345
b6ba737d
TI
346 hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE);
347 hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
348
8cdc3f6c
TI
349 return ret;
350}
351
a18aaec2
TI
352void fjes_hw_exit(struct fjes_hw *hw)
353{
354 int ret;
355
356 if (hw->base) {
b6ba737d
TI
357
358 if (hw->debug_mode) {
359 /* disable debug mode */
360 mutex_lock(&hw->hw_info.lock);
361 fjes_hw_stop_debug(hw);
362 mutex_unlock(&hw->hw_info.lock);
363 }
364 vfree(hw->hw_info.trace);
365 hw->hw_info.trace = NULL;
366 hw->hw_info.trace_size = 0;
367 hw->debug_mode = 0;
368
a18aaec2
TI
369 ret = fjes_hw_reset(hw);
370 if (ret)
371 pr_err("%s: reset error", __func__);
372
373 fjes_hw_iounmap(hw);
374 hw->base = NULL;
375 }
376
377 fjes_hw_cleanup(hw);
785f28e0
TI
378
379 cancel_work_sync(&hw->update_zone_task);
b5a9152d 380 cancel_work_sync(&hw->epstop_task);
a18aaec2
TI
381}
382
3bb025d4
TI
383static enum fjes_dev_command_response_e
384fjes_hw_issue_request_command(struct fjes_hw *hw,
385 enum fjes_dev_command_request_type type)
386{
387 enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
388 union REG_CR cr;
389 union REG_CS cs;
82f6aea8 390 int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
3bb025d4
TI
391
392 cr.reg = 0;
393 cr.bits.req_start = 1;
394 cr.bits.req_code = type;
395 wr32(XSCT_CR, cr.reg);
396 cr.reg = rd32(XSCT_CR);
397
398 if (cr.bits.error == 0) {
399 timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
400 cs.reg = rd32(XSCT_CS);
401
402 while ((cs.bits.complete != 1) && timeout > 0) {
403 msleep(1000);
404 cs.reg = rd32(XSCT_CS);
405 timeout -= 1000;
406 }
407
408 if (cs.bits.complete == 1)
409 ret = FJES_CMD_STATUS_NORMAL;
410 else if (timeout <= 0)
411 ret = FJES_CMD_STATUS_TIMEOUT;
412
413 } else {
414 switch (cr.bits.err_info) {
415 case FJES_CMD_REQ_ERR_INFO_PARAM:
416 ret = FJES_CMD_STATUS_ERROR_PARAM;
417 break;
418 case FJES_CMD_REQ_ERR_INFO_STATUS:
419 ret = FJES_CMD_STATUS_ERROR_STATUS;
420 break;
421 default:
422 ret = FJES_CMD_STATUS_UNKNOWN;
423 break;
424 }
425 }
426
82f6aea8
TI
427 trace_fjes_hw_issue_request_command(&cr, &cs, timeout, ret);
428
3bb025d4
TI
429 return ret;
430}
431
432int fjes_hw_request_info(struct fjes_hw *hw)
433{
434 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
435 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
436 enum fjes_dev_command_response_e ret;
437 int result;
438
439 memset(req_buf, 0, hw->hw_info.req_buf_size);
440 memset(res_buf, 0, hw->hw_info.res_buf_size);
441
442 req_buf->info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;
443
444 res_buf->info.length = 0;
445 res_buf->info.code = 0;
446
447 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
82f6aea8 448 trace_fjes_hw_request_info(hw, res_buf);
3bb025d4
TI
449
450 result = 0;
451
452 if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
453 res_buf->info.length) {
82f6aea8 454 trace_fjes_hw_request_info_err("Invalid res_buf");
3bb025d4
TI
455 result = -ENOMSG;
456 } else if (ret == FJES_CMD_STATUS_NORMAL) {
457 switch (res_buf->info.code) {
458 case FJES_CMD_REQ_RES_CODE_NORMAL:
459 result = 0;
460 break;
461 default:
462 result = -EPERM;
463 break;
464 }
465 } else {
466 switch (ret) {
467 case FJES_CMD_STATUS_UNKNOWN:
468 result = -EPERM;
469 break;
470 case FJES_CMD_STATUS_TIMEOUT:
82f6aea8 471 trace_fjes_hw_request_info_err("Timeout");
3bb025d4
TI
472 result = -EBUSY;
473 break;
474 case FJES_CMD_STATUS_ERROR_PARAM:
475 result = -EPERM;
476 break;
477 case FJES_CMD_STATUS_ERROR_STATUS:
478 result = -EPERM;
479 break;
480 default:
481 result = -EPERM;
482 break;
483 }
484 }
485
486 return result;
487}
488
7950e6c5
TI
489int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
490 struct ep_share_mem_info *buf_pair)
491{
492 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
493 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
494 enum fjes_dev_command_response_e ret;
495 int page_count;
496 int timeout;
497 int i, idx;
498 void *addr;
499 int result;
500
501 if (test_bit(dest_epid, &hw->hw_info.buffer_share_bit))
502 return 0;
503
504 memset(req_buf, 0, hw->hw_info.req_buf_size);
505 memset(res_buf, 0, hw->hw_info.res_buf_size);
506
507 req_buf->share_buffer.length = FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(
508 buf_pair->tx.size,
509 buf_pair->rx.size);
510 req_buf->share_buffer.epid = dest_epid;
511
512 idx = 0;
513 req_buf->share_buffer.buffer[idx++] = buf_pair->tx.size;
514 page_count = buf_pair->tx.size / EP_BUFFER_INFO_SIZE;
515 for (i = 0; i < page_count; i++) {
516 addr = ((u8 *)(buf_pair->tx.buffer)) +
517 (i * EP_BUFFER_INFO_SIZE);
518 req_buf->share_buffer.buffer[idx++] =
519 (__le64)(page_to_phys(vmalloc_to_page(addr)) +
520 offset_in_page(addr));
521 }
522
523 req_buf->share_buffer.buffer[idx++] = buf_pair->rx.size;
524 page_count = buf_pair->rx.size / EP_BUFFER_INFO_SIZE;
525 for (i = 0; i < page_count; i++) {
526 addr = ((u8 *)(buf_pair->rx.buffer)) +
527 (i * EP_BUFFER_INFO_SIZE);
528 req_buf->share_buffer.buffer[idx++] =
529 (__le64)(page_to_phys(vmalloc_to_page(addr)) +
530 offset_in_page(addr));
531 }
532
533 res_buf->share_buffer.length = 0;
534 res_buf->share_buffer.code = 0;
535
82f6aea8
TI
536 trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
537
7950e6c5
TI
538 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
539
540 timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
541 while ((ret == FJES_CMD_STATUS_NORMAL) &&
542 (res_buf->share_buffer.length ==
543 FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) &&
544 (res_buf->share_buffer.code == FJES_CMD_REQ_RES_CODE_BUSY) &&
545 (timeout > 0)) {
546 msleep(200 + hw->my_epid * 20);
547 timeout -= (200 + hw->my_epid * 20);
548
549 res_buf->share_buffer.length = 0;
550 res_buf->share_buffer.code = 0;
551
552 ret = fjes_hw_issue_request_command(
553 hw, FJES_CMD_REQ_SHARE_BUFFER);
554 }
555
556 result = 0;
557
82f6aea8
TI
558 trace_fjes_hw_register_buff_addr(res_buf, timeout);
559
7950e6c5 560 if (res_buf->share_buffer.length !=
82f6aea8
TI
561 FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
562 trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
7950e6c5 563 result = -ENOMSG;
82f6aea8 564 } else if (ret == FJES_CMD_STATUS_NORMAL) {
7950e6c5
TI
565 switch (res_buf->share_buffer.code) {
566 case FJES_CMD_REQ_RES_CODE_NORMAL:
567 result = 0;
568 set_bit(dest_epid, &hw->hw_info.buffer_share_bit);
569 break;
570 case FJES_CMD_REQ_RES_CODE_BUSY:
82f6aea8 571 trace_fjes_hw_register_buff_addr_err("Busy Timeout");
7950e6c5
TI
572 result = -EBUSY;
573 break;
574 default:
575 result = -EPERM;
576 break;
577 }
578 } else {
579 switch (ret) {
580 case FJES_CMD_STATUS_UNKNOWN:
581 result = -EPERM;
582 break;
583 case FJES_CMD_STATUS_TIMEOUT:
82f6aea8 584 trace_fjes_hw_register_buff_addr_err("Timeout");
7950e6c5
TI
585 result = -EBUSY;
586 break;
587 case FJES_CMD_STATUS_ERROR_PARAM:
588 case FJES_CMD_STATUS_ERROR_STATUS:
589 default:
590 result = -EPERM;
591 break;
592 }
593 }
594
595 return result;
596}
597
598int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
599{
600 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
601 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
602 struct fjes_device_shared_info *share = hw->hw_info.share;
603 enum fjes_dev_command_response_e ret;
604 int timeout;
605 int result;
606
607 if (!hw->base)
608 return -EPERM;
609
610 if (!req_buf || !res_buf || !share)
611 return -EPERM;
612
613 if (!test_bit(dest_epid, &hw->hw_info.buffer_share_bit))
614 return 0;
615
616 memset(req_buf, 0, hw->hw_info.req_buf_size);
617 memset(res_buf, 0, hw->hw_info.res_buf_size);
618
619 req_buf->unshare_buffer.length =
620 FJES_DEV_COMMAND_UNSHARE_BUFFER_REQ_LEN;
621 req_buf->unshare_buffer.epid = dest_epid;
622
623 res_buf->unshare_buffer.length = 0;
624 res_buf->unshare_buffer.code = 0;
625
82f6aea8 626 trace_fjes_hw_unregister_buff_addr_req(req_buf);
7950e6c5
TI
627 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
628
629 timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
630 while ((ret == FJES_CMD_STATUS_NORMAL) &&
631 (res_buf->unshare_buffer.length ==
632 FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) &&
633 (res_buf->unshare_buffer.code ==
634 FJES_CMD_REQ_RES_CODE_BUSY) &&
635 (timeout > 0)) {
636 msleep(200 + hw->my_epid * 20);
9001d94d 637 timeout -= (200 + hw->my_epid * 20);
7950e6c5
TI
638
639 res_buf->unshare_buffer.length = 0;
640 res_buf->unshare_buffer.code = 0;
641
642 ret =
643 fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
644 }
645
646 result = 0;
647
82f6aea8
TI
648 trace_fjes_hw_unregister_buff_addr(res_buf, timeout);
649
7950e6c5
TI
650 if (res_buf->unshare_buffer.length !=
651 FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) {
82f6aea8 652 trace_fjes_hw_unregister_buff_addr_err("Invalid res_buf");
7950e6c5
TI
653 result = -ENOMSG;
654 } else if (ret == FJES_CMD_STATUS_NORMAL) {
655 switch (res_buf->unshare_buffer.code) {
656 case FJES_CMD_REQ_RES_CODE_NORMAL:
657 result = 0;
658 clear_bit(dest_epid, &hw->hw_info.buffer_share_bit);
659 break;
660 case FJES_CMD_REQ_RES_CODE_BUSY:
82f6aea8 661 trace_fjes_hw_unregister_buff_addr_err("Busy Timeout");
7950e6c5
TI
662 result = -EBUSY;
663 break;
664 default:
665 result = -EPERM;
666 break;
667 }
668 } else {
669 switch (ret) {
670 case FJES_CMD_STATUS_UNKNOWN:
671 result = -EPERM;
672 break;
673 case FJES_CMD_STATUS_TIMEOUT:
82f6aea8 674 trace_fjes_hw_unregister_buff_addr_err("Timeout");
7950e6c5
TI
675 result = -EBUSY;
676 break;
677 case FJES_CMD_STATUS_ERROR_PARAM:
678 case FJES_CMD_STATUS_ERROR_STATUS:
679 default:
680 result = -EPERM;
681 break;
682 }
683 }
684
685 return result;
686}
687
e5d486dc
TI
688int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid,
689 enum REG_ICTL_MASK mask)
690{
691 u32 ig = mask | dest_epid;
692
693 wr32(XSCT_IG, cpu_to_le32(ig));
694
695 return 0;
696}
697
698u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw)
699{
700 u32 cur_is;
701
702 cur_is = rd32(XSCT_IS);
703
704 return cur_is;
705}
706
8cdc3f6c
TI
707void fjes_hw_set_irqmask(struct fjes_hw *hw,
708 enum REG_ICTL_MASK intr_mask, bool mask)
709{
710 if (mask)
711 wr32(XSCT_IMS, intr_mask);
712 else
713 wr32(XSCT_IMC, intr_mask);
714}
e5d486dc
TI
715
716bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid)
717{
718 if (epid >= hw->max_epid)
719 return false;
720
721 if ((hw->ep_shm_info[epid].es_status !=
722 FJES_ZONING_STATUS_ENABLE) ||
723 (hw->ep_shm_info[hw->my_epid].zone ==
724 FJES_ZONING_ZONE_TYPE_NONE))
725 return false;
726 else
727 return (hw->ep_shm_info[epid].zone ==
728 hw->ep_shm_info[hw->my_epid].zone);
729}
730
731int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share,
732 int dest_epid)
733{
734 int value = false;
735
736 if (dest_epid < share->epnum)
737 value = share->ep_status[dest_epid];
738
739 return value;
740}
741
742static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid)
743{
744 return test_bit(src_epid, &hw->txrx_stop_req_bit);
745}
746
747static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid)
748{
749 return (hw->ep_shm_info[src_epid].tx.info->v1i.rx_status &
750 FJES_RX_STOP_REQ_DONE);
751}
752
753enum ep_partner_status
754fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
755{
756 enum ep_partner_status status;
757
758 if (fjes_hw_epid_is_shared(hw->hw_info.share, epid)) {
759 if (fjes_hw_epid_is_stop_requested(hw, epid)) {
760 status = EP_PARTNER_WAITING;
761 } else {
762 if (fjes_hw_epid_is_stop_process_done(hw, epid))
763 status = EP_PARTNER_COMPLETE;
764 else
765 status = EP_PARTNER_SHARED;
766 }
767 } else {
768 status = EP_PARTNER_UNSHARE;
769 }
770
771 return status;
772}
773
774void fjes_hw_raise_epstop(struct fjes_hw *hw)
775{
776 enum ep_partner_status status;
bd5a2569 777 unsigned long flags;
e5d486dc
TI
778 int epidx;
779
780 for (epidx = 0; epidx < hw->max_epid; epidx++) {
781 if (epidx == hw->my_epid)
782 continue;
783
784 status = fjes_hw_get_partner_ep_status(hw, epidx);
785 switch (status) {
786 case EP_PARTNER_SHARED:
787 fjes_hw_raise_interrupt(hw, epidx,
788 REG_ICTL_MASK_TXRX_STOP_REQ);
21b7efbc 789 hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
e5d486dc
TI
790 break;
791 default:
792 break;
793 }
794
795 set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
796 set_bit(epidx, &hw->txrx_stop_req_bit);
797
bd5a2569 798 spin_lock_irqsave(&hw->rx_status_lock, flags);
e5d486dc
TI
799 hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
800 FJES_RX_STOP_REQ_REQUEST;
bd5a2569 801 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
e5d486dc
TI
802 }
803}
804
805int fjes_hw_wait_epstop(struct fjes_hw *hw)
806{
807 enum ep_partner_status status;
808 union ep_buffer_info *info;
809 int wait_time = 0;
810 int epidx;
811
812 while (hw->hw_info.buffer_unshare_reserve_bit &&
813 (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) {
814 for (epidx = 0; epidx < hw->max_epid; epidx++) {
815 if (epidx == hw->my_epid)
816 continue;
817 status = fjes_hw_epid_is_shared(hw->hw_info.share,
818 epidx);
819 info = hw->ep_shm_info[epidx].rx.info;
820 if ((!status ||
821 (info->v1i.rx_status &
822 FJES_RX_STOP_REQ_DONE)) &&
823 test_bit(epidx,
824 &hw->hw_info.buffer_unshare_reserve_bit)) {
825 clear_bit(epidx,
826 &hw->hw_info.buffer_unshare_reserve_bit);
827 }
828 }
829
830 msleep(100);
831 wait_time += 100;
832 }
833
834 for (epidx = 0; epidx < hw->max_epid; epidx++) {
835 if (epidx == hw->my_epid)
836 continue;
837 if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit))
838 clear_bit(epidx,
839 &hw->hw_info.buffer_unshare_reserve_bit);
840 }
841
842 return (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)
843 ? 0 : -EBUSY;
844}
9acf51cb
TI
845
846bool fjes_hw_check_epbuf_version(struct epbuf_handler *epbh, u32 version)
847{
848 union ep_buffer_info *info = epbh->info;
849
850 return (info->common.version == version);
851}
852
853bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu)
854{
855 union ep_buffer_info *info = epbh->info;
856
16bbec3a
TI
857 return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) &&
858 info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE);
9acf51cb
TI
859}
860
861bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
862{
863 union ep_buffer_info *info = epbh->info;
864 bool ret = false;
865 int i;
866
867 if (vlan_id == 0) {
868 ret = true;
869 } else {
870 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
871 if (vlan_id == info->v1i.vlan_id[i]) {
872 ret = true;
873 break;
874 }
875 }
876 }
877 return ret;
878}
879
3e3fedda
TI
880bool fjes_hw_set_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
881{
882 union ep_buffer_info *info = epbh->info;
883 int i;
884
885 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
886 if (info->v1i.vlan_id[i] == 0) {
887 info->v1i.vlan_id[i] = vlan_id;
888 return true;
889 }
890 }
891 return false;
892}
893
894void fjes_hw_del_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
895{
896 union ep_buffer_info *info = epbh->info;
897 int i;
898
899 if (0 != vlan_id) {
900 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
901 if (vlan_id == info->v1i.vlan_id[i])
902 info->v1i.vlan_id[i] = 0;
903 }
904 }
905}
906
26585930
TI
907bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
908{
909 union ep_buffer_info *info = epbh->info;
910
16bbec3a
TI
911 if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
912 return true;
913
26585930
TI
914 if (info->v1i.count_max == 0)
915 return true;
916
917 return EP_RING_EMPTY(info->v1i.head, info->v1i.tail,
918 info->v1i.count_max);
919}
920
921void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
922 size_t *psize)
923{
924 union ep_buffer_info *info = epbh->info;
925 struct esmem_frame *ring_frame;
926 void *frame;
927
928 ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
929 (info->v1i.head,
930 info->v1i.count_max) *
931 info->v1i.frame_max]);
932
933 *psize = (size_t)ring_frame->frame_size;
934
935 frame = ring_frame->frame_data;
936
937 return frame;
938}
939
940void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
941{
942 union ep_buffer_info *info = epbh->info;
943
944 if (fjes_hw_epbuf_rx_is_empty(epbh))
945 return;
946
947 EP_RING_INDEX_INC(epbh->info->v1i.head, info->v1i.count_max);
948}
949
9acf51cb
TI
950int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
951 void *frame, size_t size)
952{
953 union ep_buffer_info *info = epbh->info;
954 struct esmem_frame *ring_frame;
955
956 if (EP_RING_FULL(info->v1i.head, info->v1i.tail, info->v1i.count_max))
957 return -ENOBUFS;
958
959 ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
960 (info->v1i.tail - 1,
961 info->v1i.count_max) *
962 info->v1i.frame_max]);
963
964 ring_frame->frame_size = size;
965 memcpy((void *)(ring_frame->frame_data), (void *)frame, size);
966
967 EP_RING_INDEX_INC(epbh->info->v1i.tail, info->v1i.count_max);
968
969 return 0;
970}
785f28e0
TI
971
972static void fjes_hw_update_zone_task(struct work_struct *work)
973{
974 struct fjes_hw *hw = container_of(work,
975 struct fjes_hw, update_zone_task);
976
977 struct my_s {u8 es_status; u8 zone; } *info;
978 union fjes_device_command_res *res_buf;
979 enum ep_partner_status pstatus;
980
981 struct fjes_adapter *adapter;
982 struct net_device *netdev;
bd5a2569 983 unsigned long flags;
785f28e0
TI
984
985 ulong unshare_bit = 0;
986 ulong share_bit = 0;
987 ulong irq_bit = 0;
988
989 int epidx;
990 int ret;
991
992 adapter = (struct fjes_adapter *)hw->back;
993 netdev = adapter->netdev;
994 res_buf = hw->hw_info.res_buf;
995 info = (struct my_s *)&res_buf->info.info;
996
997 mutex_lock(&hw->hw_info.lock);
998
999 ret = fjes_hw_request_info(hw);
1000 switch (ret) {
1001 case -ENOMSG:
1002 case -EBUSY:
1003 default:
1004 if (!work_pending(&adapter->force_close_task)) {
1005 adapter->force_reset = true;
1006 schedule_work(&adapter->force_close_task);
1007 }
1008 break;
1009
1010 case 0:
1011
1012 for (epidx = 0; epidx < hw->max_epid; epidx++) {
1013 if (epidx == hw->my_epid) {
1014 hw->ep_shm_info[epidx].es_status =
1015 info[epidx].es_status;
1016 hw->ep_shm_info[epidx].zone =
1017 info[epidx].zone;
1018 continue;
1019 }
1020
1021 pstatus = fjes_hw_get_partner_ep_status(hw, epidx);
1022 switch (pstatus) {
1023 case EP_PARTNER_UNSHARE:
1024 default:
1025 if ((info[epidx].zone !=
1026 FJES_ZONING_ZONE_TYPE_NONE) &&
1027 (info[epidx].es_status ==
1028 FJES_ZONING_STATUS_ENABLE) &&
1029 (info[epidx].zone ==
1030 info[hw->my_epid].zone))
1031 set_bit(epidx, &share_bit);
1032 else
1033 set_bit(epidx, &unshare_bit);
1034 break;
1035
1036 case EP_PARTNER_COMPLETE:
1037 case EP_PARTNER_WAITING:
1038 if ((info[epidx].zone ==
1039 FJES_ZONING_ZONE_TYPE_NONE) ||
1040 (info[epidx].es_status !=
1041 FJES_ZONING_STATUS_ENABLE) ||
1042 (info[epidx].zone !=
1043 info[hw->my_epid].zone)) {
1044 set_bit(epidx,
1045 &adapter->unshare_watch_bitmask);
1046 set_bit(epidx,
1047 &hw->hw_info.buffer_unshare_reserve_bit);
1048 }
1049 break;
1050
1051 case EP_PARTNER_SHARED:
1052 if ((info[epidx].zone ==
1053 FJES_ZONING_ZONE_TYPE_NONE) ||
1054 (info[epidx].es_status !=
1055 FJES_ZONING_STATUS_ENABLE) ||
1056 (info[epidx].zone !=
1057 info[hw->my_epid].zone))
1058 set_bit(epidx, &irq_bit);
1059 break;
1060 }
785f28e0 1061
adb094e5
TI
1062 hw->ep_shm_info[epidx].es_status =
1063 info[epidx].es_status;
1064 hw->ep_shm_info[epidx].zone = info[epidx].zone;
1065 }
785f28e0
TI
1066 break;
1067 }
1068
1069 mutex_unlock(&hw->hw_info.lock);
1070
1071 for (epidx = 0; epidx < hw->max_epid; epidx++) {
1072 if (epidx == hw->my_epid)
1073 continue;
1074
1075 if (test_bit(epidx, &share_bit)) {
bd5a2569 1076 spin_lock_irqsave(&hw->rx_status_lock, flags);
785f28e0
TI
1077 fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
1078 netdev->dev_addr, netdev->mtu);
bd5a2569 1079 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
785f28e0
TI
1080
1081 mutex_lock(&hw->hw_info.lock);
1082
1083 ret = fjes_hw_register_buff_addr(
1084 hw, epidx, &hw->ep_shm_info[epidx]);
1085
1086 switch (ret) {
1087 case 0:
1088 break;
1089 case -ENOMSG:
1090 case -EBUSY:
1091 default:
1092 if (!work_pending(&adapter->force_close_task)) {
1093 adapter->force_reset = true;
1094 schedule_work(
1095 &adapter->force_close_task);
1096 }
1097 break;
1098 }
1099 mutex_unlock(&hw->hw_info.lock);
21b7efbc
TI
1100
1101 hw->ep_shm_info[epidx].ep_stats
1102 .com_regist_buf_exec += 1;
785f28e0
TI
1103 }
1104
1105 if (test_bit(epidx, &unshare_bit)) {
1106 mutex_lock(&hw->hw_info.lock);
1107
1108 ret = fjes_hw_unregister_buff_addr(hw, epidx);
1109
1110 switch (ret) {
1111 case 0:
1112 break;
1113 case -ENOMSG:
1114 case -EBUSY:
1115 default:
1116 if (!work_pending(&adapter->force_close_task)) {
1117 adapter->force_reset = true;
1118 schedule_work(
1119 &adapter->force_close_task);
1120 }
1121 break;
1122 }
1123
1124 mutex_unlock(&hw->hw_info.lock);
1125
21b7efbc
TI
1126 hw->ep_shm_info[epidx].ep_stats
1127 .com_unregist_buf_exec += 1;
1128
bd5a2569
TI
1129 if (ret == 0) {
1130 spin_lock_irqsave(&hw->rx_status_lock, flags);
785f28e0
TI
1131 fjes_hw_setup_epbuf(
1132 &hw->ep_shm_info[epidx].tx,
1133 netdev->dev_addr, netdev->mtu);
bd5a2569
TI
1134 spin_unlock_irqrestore(&hw->rx_status_lock,
1135 flags);
1136 }
785f28e0
TI
1137 }
1138
1139 if (test_bit(epidx, &irq_bit)) {
1140 fjes_hw_raise_interrupt(hw, epidx,
1141 REG_ICTL_MASK_TXRX_STOP_REQ);
1142
21b7efbc
TI
1143 hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
1144
785f28e0 1145 set_bit(epidx, &hw->txrx_stop_req_bit);
bd5a2569 1146 spin_lock_irqsave(&hw->rx_status_lock, flags);
785f28e0
TI
1147 hw->ep_shm_info[epidx].tx.
1148 info->v1i.rx_status |=
1149 FJES_RX_STOP_REQ_REQUEST;
bd5a2569 1150 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
785f28e0
TI
1151 set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
1152 }
1153 }
1154
1155 if (irq_bit || adapter->unshare_watch_bitmask) {
1156 if (!work_pending(&adapter->unshare_watch_task))
1157 queue_work(adapter->control_wq,
1158 &adapter->unshare_watch_task);
1159 }
1160}
b5a9152d
TI
1161
1162static void fjes_hw_epstop_task(struct work_struct *work)
1163{
1164 struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task);
1165 struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back;
bd5a2569 1166 unsigned long flags;
b5a9152d
TI
1167
1168 ulong remain_bit;
1169 int epid_bit;
1170
1171 while ((remain_bit = hw->epstop_req_bit)) {
1172 for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) {
1173 if (remain_bit & 1) {
bd5a2569 1174 spin_lock_irqsave(&hw->rx_status_lock, flags);
b5a9152d
TI
1175 hw->ep_shm_info[epid_bit].
1176 tx.info->v1i.rx_status |=
1177 FJES_RX_STOP_REQ_DONE;
bd5a2569
TI
1178 spin_unlock_irqrestore(&hw->rx_status_lock,
1179 flags);
b5a9152d
TI
1180
1181 clear_bit(epid_bit, &hw->epstop_req_bit);
1182 set_bit(epid_bit,
1183 &adapter->unshare_watch_bitmask);
1184
1185 if (!work_pending(&adapter->unshare_watch_task))
1186 queue_work(
1187 adapter->control_wq,
1188 &adapter->unshare_watch_task);
1189 }
1190 }
1191 }
1192}
b6ba737d
TI
1193
1194int fjes_hw_start_debug(struct fjes_hw *hw)
1195{
1196 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
1197 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
1198 enum fjes_dev_command_response_e ret;
1199 int page_count;
1200 int result = 0;
1201 void *addr;
1202 int i;
1203
1204 if (!hw->hw_info.trace)
1205 return -EPERM;
1206 memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE);
1207
1208 memset(req_buf, 0, hw->hw_info.req_buf_size);
1209 memset(res_buf, 0, hw->hw_info.res_buf_size);
1210
1211 req_buf->start_trace.length =
1212 FJES_DEV_COMMAND_START_DBG_REQ_LEN(hw->hw_info.trace_size);
1213 req_buf->start_trace.mode = hw->debug_mode;
1214 req_buf->start_trace.buffer_len = hw->hw_info.trace_size;
1215 page_count = hw->hw_info.trace_size / FJES_DEBUG_PAGE_SIZE;
1216 for (i = 0; i < page_count; i++) {
1217 addr = ((u8 *)hw->hw_info.trace) + i * FJES_DEBUG_PAGE_SIZE;
1218 req_buf->start_trace.buffer[i] =
1219 (__le64)(page_to_phys(vmalloc_to_page(addr)) +
1220 offset_in_page(addr));
1221 }
1222
1223 res_buf->start_trace.length = 0;
1224 res_buf->start_trace.code = 0;
1225
1226 trace_fjes_hw_start_debug_req(req_buf);
1227 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_DEBUG);
1228 trace_fjes_hw_start_debug(res_buf);
1229
1230 if (res_buf->start_trace.length !=
1231 FJES_DEV_COMMAND_START_DBG_RES_LEN) {
1232 result = -ENOMSG;
1233 trace_fjes_hw_start_debug_err("Invalid res_buf");
1234 } else if (ret == FJES_CMD_STATUS_NORMAL) {
1235 switch (res_buf->start_trace.code) {
1236 case FJES_CMD_REQ_RES_CODE_NORMAL:
1237 result = 0;
1238 break;
1239 default:
1240 result = -EPERM;
1241 break;
1242 }
1243 } else {
1244 switch (ret) {
1245 case FJES_CMD_STATUS_UNKNOWN:
1246 result = -EPERM;
1247 break;
1248 case FJES_CMD_STATUS_TIMEOUT:
1249 trace_fjes_hw_start_debug_err("Busy Timeout");
1250 result = -EBUSY;
1251 break;
1252 case FJES_CMD_STATUS_ERROR_PARAM:
1253 case FJES_CMD_STATUS_ERROR_STATUS:
1254 default:
1255 result = -EPERM;
1256 break;
1257 }
1258 }
1259
1260 return result;
1261}
1262
1263int fjes_hw_stop_debug(struct fjes_hw *hw)
1264{
1265 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
1266 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
1267 enum fjes_dev_command_response_e ret;
1268 int result = 0;
1269
1270 if (!hw->hw_info.trace)
1271 return -EPERM;
1272
1273 memset(req_buf, 0, hw->hw_info.req_buf_size);
1274 memset(res_buf, 0, hw->hw_info.res_buf_size);
1275 req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_DBG_REQ_LEN;
1276
1277 res_buf->stop_trace.length = 0;
1278 res_buf->stop_trace.code = 0;
1279
1280 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_DEBUG);
1281 trace_fjes_hw_stop_debug(res_buf);
1282
1283 if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_DBG_RES_LEN) {
1284 trace_fjes_hw_stop_debug_err("Invalid res_buf");
1285 result = -ENOMSG;
1286 } else if (ret == FJES_CMD_STATUS_NORMAL) {
1287 switch (res_buf->stop_trace.code) {
1288 case FJES_CMD_REQ_RES_CODE_NORMAL:
1289 result = 0;
1290 hw->debug_mode = 0;
1291 break;
1292 default:
1293 result = -EPERM;
1294 break;
1295 }
1296 } else {
1297 switch (ret) {
1298 case FJES_CMD_STATUS_UNKNOWN:
1299 result = -EPERM;
1300 break;
1301 case FJES_CMD_STATUS_TIMEOUT:
1302 result = -EBUSY;
1303 trace_fjes_hw_stop_debug_err("Busy Timeout");
1304 break;
1305 case FJES_CMD_STATUS_ERROR_PARAM:
1306 case FJES_CMD_STATUS_ERROR_STATUS:
1307 default:
1308 result = -EPERM;
1309 break;
1310 }
1311 }
1312
1313 return result;
1314}