File Index
Files and directories
Sign in
FILE

fjes_hw.c

File preview with syntax highlighting.

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