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