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,const u8 * mac_addr,u32 mtu)140 void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, const u8 *mac_addr,
141 u32 mtu)
142 {
143 union ep_buffer_info *info = epbh->info;
144 u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];
145 int i;
146
147 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
148 vlan_id[i] = info->v1i.vlan_id[i];
149
150 memset(info, 0, sizeof(union ep_buffer_info));
151
152 info->v1i.version = 0; /* version 0 */
153
154 for (i = 0; i < ETH_ALEN; i++)
155 info->v1i.mac_addr[i] = mac_addr[i];
156
157 info->v1i.head = 0;
158 info->v1i.tail = 1;
159
160 info->v1i.info_size = sizeof(union ep_buffer_info);
161 info->v1i.buffer_size = epbh->size - info->v1i.info_size;
162
163 info->v1i.frame_max = FJES_MTU_TO_FRAME_SIZE(mtu);
164 info->v1i.count_max =
165 EP_RING_NUM(info->v1i.buffer_size, info->v1i.frame_max);
166
167 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
168 info->v1i.vlan_id[i] = vlan_id[i];
169
170 info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE;
171 }
172
173 void
fjes_hw_init_command_registers(struct fjes_hw * hw,struct fjes_device_command_param * param)174 fjes_hw_init_command_registers(struct fjes_hw *hw,
175 struct fjes_device_command_param *param)
176 {
177 /* Request Buffer length */
178 wr32(XSCT_REQBL, (__le32)(param->req_len));
179 /* Response Buffer Length */
180 wr32(XSCT_RESPBL, (__le32)(param->res_len));
181
182 /* Request Buffer Address */
183 wr32(XSCT_REQBAL,
184 (__le32)(param->req_start & GENMASK_ULL(31, 0)));
185 wr32(XSCT_REQBAH,
186 (__le32)((param->req_start & GENMASK_ULL(63, 32)) >> 32));
187
188 /* Response Buffer Address */
189 wr32(XSCT_RESPBAL,
190 (__le32)(param->res_start & GENMASK_ULL(31, 0)));
191 wr32(XSCT_RESPBAH,
192 (__le32)((param->res_start & GENMASK_ULL(63, 32)) >> 32));
193
194 /* Share status address */
195 wr32(XSCT_SHSTSAL,
196 (__le32)(param->share_start & GENMASK_ULL(31, 0)));
197 wr32(XSCT_SHSTSAH,
198 (__le32)((param->share_start & GENMASK_ULL(63, 32)) >> 32));
199 }
200
fjes_hw_setup(struct fjes_hw * hw)201 static int fjes_hw_setup(struct fjes_hw *hw)
202 {
203 u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
204 struct fjes_device_command_param param;
205 struct ep_share_mem_info *buf_pair;
206 unsigned long flags;
207 size_t mem_size;
208 int result;
209 int epidx;
210 void *buf;
211
212 hw->hw_info.max_epid = &hw->max_epid;
213 hw->hw_info.my_epid = &hw->my_epid;
214
215 buf = kzalloc_objs(struct ep_share_mem_info, hw->max_epid);
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 goto err_iounmap;
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 ret = -ENXIO;
351 goto err_iounmap;
352 }
353
354 ret = fjes_hw_setup(hw);
355
356 hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE);
357 hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
358
359 return ret;
360
361 err_iounmap:
362 fjes_hw_iounmap(hw);
363 return ret;
364 }
365
fjes_hw_exit(struct fjes_hw * hw)366 void fjes_hw_exit(struct fjes_hw *hw)
367 {
368 int ret;
369
370 if (hw->base) {
371
372 if (hw->debug_mode) {
373 /* disable debug mode */
374 mutex_lock(&hw->hw_info.lock);
375 fjes_hw_stop_debug(hw);
376 mutex_unlock(&hw->hw_info.lock);
377 }
378 vfree(hw->hw_info.trace);
379 hw->hw_info.trace = NULL;
380 hw->hw_info.trace_size = 0;
381 hw->debug_mode = 0;
382
383 ret = fjes_hw_reset(hw);
384 if (ret)
385 pr_err("%s: reset error", __func__);
386
387 fjes_hw_iounmap(hw);
388 hw->base = NULL;
389 }
390
391 fjes_hw_cleanup(hw);
392
393 cancel_work_sync(&hw->update_zone_task);
394 cancel_work_sync(&hw->epstop_task);
395 }
396
397 static enum fjes_dev_command_response_e
fjes_hw_issue_request_command(struct fjes_hw * hw,enum fjes_dev_command_request_type type)398 fjes_hw_issue_request_command(struct fjes_hw *hw,
399 enum fjes_dev_command_request_type type)
400 {
401 enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
402 union REG_CR cr;
403 union REG_CS cs;
404 int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
405
406 cr.reg = 0;
407 cr.bits.req_start = 1;
408 cr.bits.req_code = type;
409 wr32(XSCT_CR, cr.reg);
410 cr.reg = rd32(XSCT_CR);
411
412 if (cr.bits.error == 0) {
413 timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
414 cs.reg = rd32(XSCT_CS);
415
416 while ((cs.bits.complete != 1) && timeout > 0) {
417 msleep(1000);
418 cs.reg = rd32(XSCT_CS);
419 timeout -= 1000;
420 }
421
422 if (cs.bits.complete == 1)
423 ret = FJES_CMD_STATUS_NORMAL;
424 else if (timeout <= 0)
425 ret = FJES_CMD_STATUS_TIMEOUT;
426
427 } else {
428 switch (cr.bits.err_info) {
429 case FJES_CMD_REQ_ERR_INFO_PARAM:
430 ret = FJES_CMD_STATUS_ERROR_PARAM;
431 break;
432 case FJES_CMD_REQ_ERR_INFO_STATUS:
433 ret = FJES_CMD_STATUS_ERROR_STATUS;
434 break;
435 default:
436 ret = FJES_CMD_STATUS_UNKNOWN;
437 break;
438 }
439 }
440
441 trace_fjes_hw_issue_request_command(&cr, &cs, timeout, ret);
442
443 return ret;
444 }
445
fjes_hw_request_info(struct fjes_hw * hw)446 int fjes_hw_request_info(struct fjes_hw *hw)
447 {
448 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
449 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
450 enum fjes_dev_command_response_e ret;
451 int result;
452
453 memset(req_buf, 0, hw->hw_info.req_buf_size);
454 memset(res_buf, 0, hw->hw_info.res_buf_size);
455
456 req_buf->info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;
457
458 res_buf->info.length = 0;
459 res_buf->info.code = 0;
460
461 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
462 trace_fjes_hw_request_info(hw, res_buf);
463
464 result = 0;
465
466 if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
467 res_buf->info.length) {
468 trace_fjes_hw_request_info_err("Invalid res_buf");
469 result = -ENOMSG;
470 } else if (ret == FJES_CMD_STATUS_NORMAL) {
471 switch (res_buf->info.code) {
472 case FJES_CMD_REQ_RES_CODE_NORMAL:
473 result = 0;
474 break;
475 default:
476 result = -EPERM;
477 break;
478 }
479 } else {
480 switch (ret) {
481 case FJES_CMD_STATUS_UNKNOWN:
482 result = -EPERM;
483 break;
484 case FJES_CMD_STATUS_TIMEOUT:
485 trace_fjes_hw_request_info_err("Timeout");
486 result = -EBUSY;
487 break;
488 case FJES_CMD_STATUS_ERROR_PARAM:
489 result = -EPERM;
490 break;
491 case FJES_CMD_STATUS_ERROR_STATUS:
492 result = -EPERM;
493 break;
494 default:
495 result = -EPERM;
496 break;
497 }
498 }
499
500 return result;
501 }
502
fjes_hw_register_buff_addr(struct fjes_hw * hw,int dest_epid,struct ep_share_mem_info * buf_pair)503 int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
504 struct ep_share_mem_info *buf_pair)
505 {
506 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
507 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
508 enum fjes_dev_command_response_e ret;
509 int page_count;
510 int timeout;
511 int i, idx;
512 void *addr;
513 int result;
514
515 if (test_bit(dest_epid, &hw->hw_info.buffer_share_bit))
516 return 0;
517
518 memset(req_buf, 0, hw->hw_info.req_buf_size);
519 memset(res_buf, 0, hw->hw_info.res_buf_size);
520
521 req_buf->share_buffer.length = FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(
522 buf_pair->tx.size,
523 buf_pair->rx.size);
524 req_buf->share_buffer.epid = dest_epid;
525
526 idx = 0;
527 req_buf->share_buffer.buffer[idx++] = buf_pair->tx.size;
528 page_count = buf_pair->tx.size / EP_BUFFER_INFO_SIZE;
529 for (i = 0; i < page_count; i++) {
530 addr = ((u8 *)(buf_pair->tx.buffer)) +
531 (i * EP_BUFFER_INFO_SIZE);
532 req_buf->share_buffer.buffer[idx++] =
533 (__le64)(page_to_phys(vmalloc_to_page(addr)) +
534 offset_in_page(addr));
535 }
536
537 req_buf->share_buffer.buffer[idx++] = buf_pair->rx.size;
538 page_count = buf_pair->rx.size / EP_BUFFER_INFO_SIZE;
539 for (i = 0; i < page_count; i++) {
540 addr = ((u8 *)(buf_pair->rx.buffer)) +
541 (i * EP_BUFFER_INFO_SIZE);
542 req_buf->share_buffer.buffer[idx++] =
543 (__le64)(page_to_phys(vmalloc_to_page(addr)) +
544 offset_in_page(addr));
545 }
546
547 res_buf->share_buffer.length = 0;
548 res_buf->share_buffer.code = 0;
549
550 trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
551
552 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
553
554 timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
555 while ((ret == FJES_CMD_STATUS_NORMAL) &&
556 (res_buf->share_buffer.length ==
557 FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) &&
558 (res_buf->share_buffer.code == FJES_CMD_REQ_RES_CODE_BUSY) &&
559 (timeout > 0)) {
560 msleep(200 + hw->my_epid * 20);
561 timeout -= (200 + hw->my_epid * 20);
562
563 res_buf->share_buffer.length = 0;
564 res_buf->share_buffer.code = 0;
565
566 ret = fjes_hw_issue_request_command(
567 hw, FJES_CMD_REQ_SHARE_BUFFER);
568 }
569
570 result = 0;
571
572 trace_fjes_hw_register_buff_addr(res_buf, timeout);
573
574 if (res_buf->share_buffer.length !=
575 FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
576 trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
577 result = -ENOMSG;
578 } else if (ret == FJES_CMD_STATUS_NORMAL) {
579 switch (res_buf->share_buffer.code) {
580 case FJES_CMD_REQ_RES_CODE_NORMAL:
581 result = 0;
582 set_bit(dest_epid, &hw->hw_info.buffer_share_bit);
583 break;
584 case FJES_CMD_REQ_RES_CODE_BUSY:
585 trace_fjes_hw_register_buff_addr_err("Busy Timeout");
586 result = -EBUSY;
587 break;
588 default:
589 result = -EPERM;
590 break;
591 }
592 } else {
593 switch (ret) {
594 case FJES_CMD_STATUS_UNKNOWN:
595 result = -EPERM;
596 break;
597 case FJES_CMD_STATUS_TIMEOUT:
598 trace_fjes_hw_register_buff_addr_err("Timeout");
599 result = -EBUSY;
600 break;
601 case FJES_CMD_STATUS_ERROR_PARAM:
602 case FJES_CMD_STATUS_ERROR_STATUS:
603 default:
604 result = -EPERM;
605 break;
606 }
607 }
608
609 return result;
610 }
611
fjes_hw_unregister_buff_addr(struct fjes_hw * hw,int dest_epid)612 int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
613 {
614 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
615 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
616 struct fjes_device_shared_info *share = hw->hw_info.share;
617 enum fjes_dev_command_response_e ret;
618 int timeout;
619 int result;
620
621 if (!hw->base)
622 return -EPERM;
623
624 if (!req_buf || !res_buf || !share)
625 return -EPERM;
626
627 if (!test_bit(dest_epid, &hw->hw_info.buffer_share_bit))
628 return 0;
629
630 memset(req_buf, 0, hw->hw_info.req_buf_size);
631 memset(res_buf, 0, hw->hw_info.res_buf_size);
632
633 req_buf->unshare_buffer.length =
634 FJES_DEV_COMMAND_UNSHARE_BUFFER_REQ_LEN;
635 req_buf->unshare_buffer.epid = dest_epid;
636
637 res_buf->unshare_buffer.length = 0;
638 res_buf->unshare_buffer.code = 0;
639
640 trace_fjes_hw_unregister_buff_addr_req(req_buf);
641 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
642
643 timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
644 while ((ret == FJES_CMD_STATUS_NORMAL) &&
645 (res_buf->unshare_buffer.length ==
646 FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) &&
647 (res_buf->unshare_buffer.code ==
648 FJES_CMD_REQ_RES_CODE_BUSY) &&
649 (timeout > 0)) {
650 msleep(200 + hw->my_epid * 20);
651 timeout -= (200 + hw->my_epid * 20);
652
653 res_buf->unshare_buffer.length = 0;
654 res_buf->unshare_buffer.code = 0;
655
656 ret =
657 fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
658 }
659
660 result = 0;
661
662 trace_fjes_hw_unregister_buff_addr(res_buf, timeout);
663
664 if (res_buf->unshare_buffer.length !=
665 FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN) {
666 trace_fjes_hw_unregister_buff_addr_err("Invalid res_buf");
667 result = -ENOMSG;
668 } else if (ret == FJES_CMD_STATUS_NORMAL) {
669 switch (res_buf->unshare_buffer.code) {
670 case FJES_CMD_REQ_RES_CODE_NORMAL:
671 result = 0;
672 clear_bit(dest_epid, &hw->hw_info.buffer_share_bit);
673 break;
674 case FJES_CMD_REQ_RES_CODE_BUSY:
675 trace_fjes_hw_unregister_buff_addr_err("Busy Timeout");
676 result = -EBUSY;
677 break;
678 default:
679 result = -EPERM;
680 break;
681 }
682 } else {
683 switch (ret) {
684 case FJES_CMD_STATUS_UNKNOWN:
685 result = -EPERM;
686 break;
687 case FJES_CMD_STATUS_TIMEOUT:
688 trace_fjes_hw_unregister_buff_addr_err("Timeout");
689 result = -EBUSY;
690 break;
691 case FJES_CMD_STATUS_ERROR_PARAM:
692 case FJES_CMD_STATUS_ERROR_STATUS:
693 default:
694 result = -EPERM;
695 break;
696 }
697 }
698
699 return result;
700 }
701
fjes_hw_raise_interrupt(struct fjes_hw * hw,int dest_epid,enum REG_ICTL_MASK mask)702 int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid,
703 enum REG_ICTL_MASK mask)
704 {
705 u32 ig = mask | dest_epid;
706
707 wr32(XSCT_IG, cpu_to_le32(ig));
708
709 return 0;
710 }
711
fjes_hw_capture_interrupt_status(struct fjes_hw * hw)712 u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw)
713 {
714 u32 cur_is;
715
716 cur_is = rd32(XSCT_IS);
717
718 return cur_is;
719 }
720
fjes_hw_set_irqmask(struct fjes_hw * hw,enum REG_ICTL_MASK intr_mask,bool mask)721 void fjes_hw_set_irqmask(struct fjes_hw *hw,
722 enum REG_ICTL_MASK intr_mask, bool mask)
723 {
724 if (mask)
725 wr32(XSCT_IMS, intr_mask);
726 else
727 wr32(XSCT_IMC, intr_mask);
728 }
729
fjes_hw_epid_is_same_zone(struct fjes_hw * hw,int epid)730 bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid)
731 {
732 if (epid >= hw->max_epid)
733 return false;
734
735 if ((hw->ep_shm_info[epid].es_status !=
736 FJES_ZONING_STATUS_ENABLE) ||
737 (hw->ep_shm_info[hw->my_epid].zone ==
738 FJES_ZONING_ZONE_TYPE_NONE))
739 return false;
740 else
741 return (hw->ep_shm_info[epid].zone ==
742 hw->ep_shm_info[hw->my_epid].zone);
743 }
744
fjes_hw_epid_is_shared(struct fjes_device_shared_info * share,int dest_epid)745 int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share,
746 int dest_epid)
747 {
748 int value = false;
749
750 if (dest_epid < share->epnum)
751 value = share->ep_status[dest_epid];
752
753 return value;
754 }
755
fjes_hw_epid_is_stop_requested(struct fjes_hw * hw,int src_epid)756 static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid)
757 {
758 return test_bit(src_epid, &hw->txrx_stop_req_bit);
759 }
760
fjes_hw_epid_is_stop_process_done(struct fjes_hw * hw,int src_epid)761 static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid)
762 {
763 return (hw->ep_shm_info[src_epid].tx.info->v1i.rx_status &
764 FJES_RX_STOP_REQ_DONE);
765 }
766
767 enum ep_partner_status
fjes_hw_get_partner_ep_status(struct fjes_hw * hw,int epid)768 fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
769 {
770 enum ep_partner_status status;
771
772 if (fjes_hw_epid_is_shared(hw->hw_info.share, epid)) {
773 if (fjes_hw_epid_is_stop_requested(hw, epid)) {
774 status = EP_PARTNER_WAITING;
775 } else {
776 if (fjes_hw_epid_is_stop_process_done(hw, epid))
777 status = EP_PARTNER_COMPLETE;
778 else
779 status = EP_PARTNER_SHARED;
780 }
781 } else {
782 status = EP_PARTNER_UNSHARE;
783 }
784
785 return status;
786 }
787
fjes_hw_raise_epstop(struct fjes_hw * hw)788 void fjes_hw_raise_epstop(struct fjes_hw *hw)
789 {
790 enum ep_partner_status status;
791 unsigned long flags;
792 int epidx;
793
794 for (epidx = 0; epidx < hw->max_epid; epidx++) {
795 if (epidx == hw->my_epid)
796 continue;
797
798 status = fjes_hw_get_partner_ep_status(hw, epidx);
799 switch (status) {
800 case EP_PARTNER_SHARED:
801 fjes_hw_raise_interrupt(hw, epidx,
802 REG_ICTL_MASK_TXRX_STOP_REQ);
803 hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
804 break;
805 default:
806 break;
807 }
808
809 set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
810 set_bit(epidx, &hw->txrx_stop_req_bit);
811
812 spin_lock_irqsave(&hw->rx_status_lock, flags);
813 hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
814 FJES_RX_STOP_REQ_REQUEST;
815 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
816 }
817 }
818
fjes_hw_wait_epstop(struct fjes_hw * hw)819 int fjes_hw_wait_epstop(struct fjes_hw *hw)
820 {
821 enum ep_partner_status status;
822 union ep_buffer_info *info;
823 int wait_time = 0;
824 int epidx;
825
826 while (hw->hw_info.buffer_unshare_reserve_bit &&
827 (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) {
828 for (epidx = 0; epidx < hw->max_epid; epidx++) {
829 if (epidx == hw->my_epid)
830 continue;
831 status = fjes_hw_epid_is_shared(hw->hw_info.share,
832 epidx);
833 info = hw->ep_shm_info[epidx].rx.info;
834 if ((!status ||
835 (info->v1i.rx_status &
836 FJES_RX_STOP_REQ_DONE)) &&
837 test_bit(epidx,
838 &hw->hw_info.buffer_unshare_reserve_bit)) {
839 clear_bit(epidx,
840 &hw->hw_info.buffer_unshare_reserve_bit);
841 }
842 }
843
844 msleep(100);
845 wait_time += 100;
846 }
847
848 for (epidx = 0; epidx < hw->max_epid; epidx++) {
849 if (epidx == hw->my_epid)
850 continue;
851 if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit))
852 clear_bit(epidx,
853 &hw->hw_info.buffer_unshare_reserve_bit);
854 }
855
856 return (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)
857 ? 0 : -EBUSY;
858 }
859
fjes_hw_check_epbuf_version(struct epbuf_handler * epbh,u32 version)860 bool fjes_hw_check_epbuf_version(struct epbuf_handler *epbh, u32 version)
861 {
862 union ep_buffer_info *info = epbh->info;
863
864 return (info->common.version == version);
865 }
866
fjes_hw_check_mtu(struct epbuf_handler * epbh,u32 mtu)867 bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu)
868 {
869 union ep_buffer_info *info = epbh->info;
870
871 return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) &&
872 info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE);
873 }
874
fjes_hw_check_vlan_id(struct epbuf_handler * epbh,u16 vlan_id)875 bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
876 {
877 union ep_buffer_info *info = epbh->info;
878 bool ret = false;
879 int i;
880
881 if (vlan_id == 0) {
882 ret = true;
883 } else {
884 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
885 if (vlan_id == info->v1i.vlan_id[i]) {
886 ret = true;
887 break;
888 }
889 }
890 }
891 return ret;
892 }
893
fjes_hw_set_vlan_id(struct epbuf_handler * epbh,u16 vlan_id)894 bool fjes_hw_set_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
895 {
896 union ep_buffer_info *info = epbh->info;
897 int i;
898
899 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
900 if (info->v1i.vlan_id[i] == 0) {
901 info->v1i.vlan_id[i] = vlan_id;
902 return true;
903 }
904 }
905 return false;
906 }
907
fjes_hw_del_vlan_id(struct epbuf_handler * epbh,u16 vlan_id)908 void fjes_hw_del_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
909 {
910 union ep_buffer_info *info = epbh->info;
911 int i;
912
913 if (0 != vlan_id) {
914 for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
915 if (vlan_id == info->v1i.vlan_id[i])
916 info->v1i.vlan_id[i] = 0;
917 }
918 }
919 }
920
fjes_hw_epbuf_rx_is_empty(struct epbuf_handler * epbh)921 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
922 {
923 union ep_buffer_info *info = epbh->info;
924
925 if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
926 return true;
927
928 if (info->v1i.count_max == 0)
929 return true;
930
931 return EP_RING_EMPTY(info->v1i.head, info->v1i.tail,
932 info->v1i.count_max);
933 }
934
fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler * epbh,size_t * psize)935 void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
936 size_t *psize)
937 {
938 union ep_buffer_info *info = epbh->info;
939 struct esmem_frame *ring_frame;
940 void *frame;
941
942 ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
943 (info->v1i.head,
944 info->v1i.count_max) *
945 info->v1i.frame_max]);
946
947 *psize = (size_t)ring_frame->frame_size;
948
949 frame = ring_frame->frame_data;
950
951 return frame;
952 }
953
fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler * epbh)954 void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
955 {
956 union ep_buffer_info *info = epbh->info;
957
958 if (fjes_hw_epbuf_rx_is_empty(epbh))
959 return;
960
961 EP_RING_INDEX_INC(epbh->info->v1i.head, info->v1i.count_max);
962 }
963
fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler * epbh,void * frame,size_t size)964 int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
965 void *frame, size_t size)
966 {
967 union ep_buffer_info *info = epbh->info;
968 struct esmem_frame *ring_frame;
969
970 if (EP_RING_FULL(info->v1i.head, info->v1i.tail, info->v1i.count_max))
971 return -ENOBUFS;
972
973 ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
974 (info->v1i.tail - 1,
975 info->v1i.count_max) *
976 info->v1i.frame_max]);
977
978 ring_frame->frame_size = size;
979 memcpy((void *)(ring_frame->frame_data), (void *)frame, size);
980
981 EP_RING_INDEX_INC(epbh->info->v1i.tail, info->v1i.count_max);
982
983 return 0;
984 }
985
fjes_hw_update_zone_task(struct work_struct * work)986 static void fjes_hw_update_zone_task(struct work_struct *work)
987 {
988 struct fjes_hw *hw = container_of(work,
989 struct fjes_hw, update_zone_task);
990
991 struct my_s {u8 es_status; u8 zone; } *info;
992 union fjes_device_command_res *res_buf;
993 enum ep_partner_status pstatus;
994
995 struct fjes_adapter *adapter;
996 struct net_device *netdev;
997 unsigned long flags;
998
999 ulong unshare_bit = 0;
1000 ulong share_bit = 0;
1001 ulong irq_bit = 0;
1002
1003 int epidx;
1004 int ret;
1005
1006 adapter = (struct fjes_adapter *)hw->back;
1007 netdev = adapter->netdev;
1008 res_buf = hw->hw_info.res_buf;
1009 info = (struct my_s *)&res_buf->info.info;
1010
1011 mutex_lock(&hw->hw_info.lock);
1012
1013 ret = fjes_hw_request_info(hw);
1014 switch (ret) {
1015 case -ENOMSG:
1016 case -EBUSY:
1017 default:
1018 if (!work_pending(&adapter->force_close_task)) {
1019 adapter->force_reset = true;
1020 schedule_work(&adapter->force_close_task);
1021 }
1022 break;
1023
1024 case 0:
1025
1026 for (epidx = 0; epidx < hw->max_epid; epidx++) {
1027 if (epidx == hw->my_epid) {
1028 hw->ep_shm_info[epidx].es_status =
1029 info[epidx].es_status;
1030 hw->ep_shm_info[epidx].zone =
1031 info[epidx].zone;
1032 continue;
1033 }
1034
1035 pstatus = fjes_hw_get_partner_ep_status(hw, epidx);
1036 switch (pstatus) {
1037 case EP_PARTNER_UNSHARE:
1038 default:
1039 if ((info[epidx].zone !=
1040 FJES_ZONING_ZONE_TYPE_NONE) &&
1041 (info[epidx].es_status ==
1042 FJES_ZONING_STATUS_ENABLE) &&
1043 (info[epidx].zone ==
1044 info[hw->my_epid].zone))
1045 set_bit(epidx, &share_bit);
1046 else
1047 set_bit(epidx, &unshare_bit);
1048 break;
1049
1050 case EP_PARTNER_COMPLETE:
1051 case EP_PARTNER_WAITING:
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,
1059 &adapter->unshare_watch_bitmask);
1060 set_bit(epidx,
1061 &hw->hw_info.buffer_unshare_reserve_bit);
1062 }
1063 break;
1064
1065 case EP_PARTNER_SHARED:
1066 if ((info[epidx].zone ==
1067 FJES_ZONING_ZONE_TYPE_NONE) ||
1068 (info[epidx].es_status !=
1069 FJES_ZONING_STATUS_ENABLE) ||
1070 (info[epidx].zone !=
1071 info[hw->my_epid].zone))
1072 set_bit(epidx, &irq_bit);
1073 break;
1074 }
1075
1076 hw->ep_shm_info[epidx].es_status =
1077 info[epidx].es_status;
1078 hw->ep_shm_info[epidx].zone = info[epidx].zone;
1079 }
1080 break;
1081 }
1082
1083 mutex_unlock(&hw->hw_info.lock);
1084
1085 for (epidx = 0; epidx < hw->max_epid; epidx++) {
1086 if (epidx == hw->my_epid)
1087 continue;
1088
1089 if (test_bit(epidx, &share_bit)) {
1090 spin_lock_irqsave(&hw->rx_status_lock, flags);
1091 fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
1092 netdev->dev_addr, netdev->mtu);
1093 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
1094
1095 mutex_lock(&hw->hw_info.lock);
1096
1097 ret = fjes_hw_register_buff_addr(
1098 hw, epidx, &hw->ep_shm_info[epidx]);
1099
1100 switch (ret) {
1101 case 0:
1102 break;
1103 case -ENOMSG:
1104 case -EBUSY:
1105 default:
1106 if (!work_pending(&adapter->force_close_task)) {
1107 adapter->force_reset = true;
1108 schedule_work(
1109 &adapter->force_close_task);
1110 }
1111 break;
1112 }
1113 mutex_unlock(&hw->hw_info.lock);
1114
1115 hw->ep_shm_info[epidx].ep_stats
1116 .com_regist_buf_exec += 1;
1117 }
1118
1119 if (test_bit(epidx, &unshare_bit)) {
1120 mutex_lock(&hw->hw_info.lock);
1121
1122 ret = fjes_hw_unregister_buff_addr(hw, epidx);
1123
1124 switch (ret) {
1125 case 0:
1126 break;
1127 case -ENOMSG:
1128 case -EBUSY:
1129 default:
1130 if (!work_pending(&adapter->force_close_task)) {
1131 adapter->force_reset = true;
1132 schedule_work(
1133 &adapter->force_close_task);
1134 }
1135 break;
1136 }
1137
1138 mutex_unlock(&hw->hw_info.lock);
1139
1140 hw->ep_shm_info[epidx].ep_stats
1141 .com_unregist_buf_exec += 1;
1142
1143 if (ret == 0) {
1144 spin_lock_irqsave(&hw->rx_status_lock, flags);
1145 fjes_hw_setup_epbuf(
1146 &hw->ep_shm_info[epidx].tx,
1147 netdev->dev_addr, netdev->mtu);
1148 spin_unlock_irqrestore(&hw->rx_status_lock,
1149 flags);
1150 }
1151 }
1152
1153 if (test_bit(epidx, &irq_bit)) {
1154 fjes_hw_raise_interrupt(hw, epidx,
1155 REG_ICTL_MASK_TXRX_STOP_REQ);
1156
1157 hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
1158
1159 set_bit(epidx, &hw->txrx_stop_req_bit);
1160 spin_lock_irqsave(&hw->rx_status_lock, flags);
1161 hw->ep_shm_info[epidx].tx.
1162 info->v1i.rx_status |=
1163 FJES_RX_STOP_REQ_REQUEST;
1164 spin_unlock_irqrestore(&hw->rx_status_lock, flags);
1165 set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
1166 }
1167 }
1168
1169 if (irq_bit || adapter->unshare_watch_bitmask) {
1170 if (!work_pending(&adapter->unshare_watch_task))
1171 queue_work(adapter->control_wq,
1172 &adapter->unshare_watch_task);
1173 }
1174 }
1175
fjes_hw_epstop_task(struct work_struct * work)1176 static void fjes_hw_epstop_task(struct work_struct *work)
1177 {
1178 struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task);
1179 struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back;
1180 unsigned long flags;
1181
1182 ulong remain_bit;
1183 int epid_bit;
1184
1185 while ((remain_bit = hw->epstop_req_bit)) {
1186 for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) {
1187 if (remain_bit & 1) {
1188 spin_lock_irqsave(&hw->rx_status_lock, flags);
1189 hw->ep_shm_info[epid_bit].
1190 tx.info->v1i.rx_status |=
1191 FJES_RX_STOP_REQ_DONE;
1192 spin_unlock_irqrestore(&hw->rx_status_lock,
1193 flags);
1194
1195 clear_bit(epid_bit, &hw->epstop_req_bit);
1196 set_bit(epid_bit,
1197 &adapter->unshare_watch_bitmask);
1198
1199 if (!work_pending(&adapter->unshare_watch_task))
1200 queue_work(
1201 adapter->control_wq,
1202 &adapter->unshare_watch_task);
1203 }
1204 }
1205 }
1206 }
1207
fjes_hw_start_debug(struct fjes_hw * hw)1208 int fjes_hw_start_debug(struct fjes_hw *hw)
1209 {
1210 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
1211 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
1212 enum fjes_dev_command_response_e ret;
1213 int page_count;
1214 int result = 0;
1215 void *addr;
1216 int i;
1217
1218 if (!hw->hw_info.trace)
1219 return -EPERM;
1220 memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE);
1221
1222 memset(req_buf, 0, hw->hw_info.req_buf_size);
1223 memset(res_buf, 0, hw->hw_info.res_buf_size);
1224
1225 req_buf->start_trace.length =
1226 FJES_DEV_COMMAND_START_DBG_REQ_LEN(hw->hw_info.trace_size);
1227 req_buf->start_trace.mode = hw->debug_mode;
1228 req_buf->start_trace.buffer_len = hw->hw_info.trace_size;
1229 page_count = hw->hw_info.trace_size / FJES_DEBUG_PAGE_SIZE;
1230 for (i = 0; i < page_count; i++) {
1231 addr = ((u8 *)hw->hw_info.trace) + i * FJES_DEBUG_PAGE_SIZE;
1232 req_buf->start_trace.buffer[i] =
1233 (__le64)(page_to_phys(vmalloc_to_page(addr)) +
1234 offset_in_page(addr));
1235 }
1236
1237 res_buf->start_trace.length = 0;
1238 res_buf->start_trace.code = 0;
1239
1240 trace_fjes_hw_start_debug_req(req_buf);
1241 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_DEBUG);
1242 trace_fjes_hw_start_debug(res_buf);
1243
1244 if (res_buf->start_trace.length !=
1245 FJES_DEV_COMMAND_START_DBG_RES_LEN) {
1246 result = -ENOMSG;
1247 trace_fjes_hw_start_debug_err("Invalid res_buf");
1248 } else if (ret == FJES_CMD_STATUS_NORMAL) {
1249 switch (res_buf->start_trace.code) {
1250 case FJES_CMD_REQ_RES_CODE_NORMAL:
1251 result = 0;
1252 break;
1253 default:
1254 result = -EPERM;
1255 break;
1256 }
1257 } else {
1258 switch (ret) {
1259 case FJES_CMD_STATUS_UNKNOWN:
1260 result = -EPERM;
1261 break;
1262 case FJES_CMD_STATUS_TIMEOUT:
1263 trace_fjes_hw_start_debug_err("Busy Timeout");
1264 result = -EBUSY;
1265 break;
1266 case FJES_CMD_STATUS_ERROR_PARAM:
1267 case FJES_CMD_STATUS_ERROR_STATUS:
1268 default:
1269 result = -EPERM;
1270 break;
1271 }
1272 }
1273
1274 return result;
1275 }
1276
fjes_hw_stop_debug(struct fjes_hw * hw)1277 int fjes_hw_stop_debug(struct fjes_hw *hw)
1278 {
1279 union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
1280 union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
1281 enum fjes_dev_command_response_e ret;
1282 int result = 0;
1283
1284 if (!hw->hw_info.trace)
1285 return -EPERM;
1286
1287 memset(req_buf, 0, hw->hw_info.req_buf_size);
1288 memset(res_buf, 0, hw->hw_info.res_buf_size);
1289 req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_DBG_REQ_LEN;
1290
1291 res_buf->stop_trace.length = 0;
1292 res_buf->stop_trace.code = 0;
1293
1294 ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_DEBUG);
1295 trace_fjes_hw_stop_debug(res_buf);
1296
1297 if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_DBG_RES_LEN) {
1298 trace_fjes_hw_stop_debug_err("Invalid res_buf");
1299 result = -ENOMSG;
1300 } else if (ret == FJES_CMD_STATUS_NORMAL) {
1301 switch (res_buf->stop_trace.code) {
1302 case FJES_CMD_REQ_RES_CODE_NORMAL:
1303 result = 0;
1304 hw->debug_mode = 0;
1305 break;
1306 default:
1307 result = -EPERM;
1308 break;
1309 }
1310 } else {
1311 switch (ret) {
1312 case FJES_CMD_STATUS_UNKNOWN:
1313 result = -EPERM;
1314 break;
1315 case FJES_CMD_STATUS_TIMEOUT:
1316 result = -EBUSY;
1317 trace_fjes_hw_stop_debug_err("Busy Timeout");
1318 break;
1319 case FJES_CMD_STATUS_ERROR_PARAM:
1320 case FJES_CMD_STATUS_ERROR_STATUS:
1321 default:
1322 result = -EPERM;
1323 break;
1324 }
1325 }
1326
1327 return result;
1328 }
1329