• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&param, 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, &param);
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