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