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