linux/drivers/scsi/qla2xxx/qla_bsg.c
<<
>>
Prefs
   1/*
   2 * QLogic Fibre Channel HBA Driver
   3 * Copyright (c)  2003-2011 QLogic Corporation
   4 *
   5 * See LICENSE.qla2xxx for copyright and licensing details.
   6 */
   7#include "qla_def.h"
   8
   9#include <linux/kthread.h>
  10#include <linux/vmalloc.h>
  11#include <linux/delay.h>
  12
  13/* BSG support for ELS/CT pass through */
  14inline srb_t *
  15qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
  16{
  17        srb_t *sp;
  18        struct qla_hw_data *ha = vha->hw;
  19        struct srb_ctx *ctx;
  20
  21        sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
  22        if (!sp)
  23                goto done;
  24        ctx = kzalloc(size, GFP_KERNEL);
  25        if (!ctx) {
  26                mempool_free(sp, ha->srb_mempool);
  27                sp = NULL;
  28                goto done;
  29        }
  30
  31        memset(sp, 0, sizeof(*sp));
  32        sp->fcport = fcport;
  33        sp->ctx = ctx;
  34done:
  35        return sp;
  36}
  37
  38int
  39qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
  40        struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
  41{
  42        int i, ret, num_valid;
  43        uint8_t *bcode;
  44        struct qla_fcp_prio_entry *pri_entry;
  45        uint32_t *bcode_val_ptr, bcode_val;
  46
  47        ret = 1;
  48        num_valid = 0;
  49        bcode = (uint8_t *)pri_cfg;
  50        bcode_val_ptr = (uint32_t *)pri_cfg;
  51        bcode_val = (uint32_t)(*bcode_val_ptr);
  52
  53        if (bcode_val == 0xFFFFFFFF) {
  54                /* No FCP Priority config data in flash */
  55                ql_dbg(ql_dbg_user, vha, 0x7051,
  56                    "No FCP Priority config data.\n");
  57                return 0;
  58        }
  59
  60        if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' ||
  61                        bcode[3] != 'S') {
  62                /* Invalid FCP priority data header*/
  63                ql_dbg(ql_dbg_user, vha, 0x7052,
  64                    "Invalid FCP Priority data header. bcode=0x%x.\n",
  65                    bcode_val);
  66                return 0;
  67        }
  68        if (flag != 1)
  69                return ret;
  70
  71        pri_entry = &pri_cfg->entry[0];
  72        for (i = 0; i < pri_cfg->num_entries; i++) {
  73                if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
  74                        num_valid++;
  75                pri_entry++;
  76        }
  77
  78        if (num_valid == 0) {
  79                /* No valid FCP priority data entries */
  80                ql_dbg(ql_dbg_user, vha, 0x7053,
  81                    "No valid FCP Priority data entries.\n");
  82                ret = 0;
  83        } else {
  84                /* FCP priority data is valid */
  85                ql_dbg(ql_dbg_user, vha, 0x7054,
  86                    "Valid FCP priority data. num entries = %d.\n",
  87                    num_valid);
  88        }
  89
  90        return ret;
  91}
  92
  93static int
  94qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
  95{
  96        struct Scsi_Host *host = bsg_job->shost;
  97        scsi_qla_host_t *vha = shost_priv(host);
  98        struct qla_hw_data *ha = vha->hw;
  99        int ret = 0;
 100        uint32_t len;
 101        uint32_t oper;
 102
 103        bsg_job->reply->reply_payload_rcv_len = 0;
 104
 105        if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))) {
 106                ret = -EINVAL;
 107                goto exit_fcp_prio_cfg;
 108        }
 109
 110        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
 111                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
 112                test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 113                ret = -EBUSY;
 114                goto exit_fcp_prio_cfg;
 115        }
 116
 117        /* Get the sub command */
 118        oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
 119
 120        /* Only set config is allowed if config memory is not allocated */
 121        if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
 122                ret = -EINVAL;
 123                goto exit_fcp_prio_cfg;
 124        }
 125        switch (oper) {
 126        case QLFC_FCP_PRIO_DISABLE:
 127                if (ha->flags.fcp_prio_enabled) {
 128                        ha->flags.fcp_prio_enabled = 0;
 129                        ha->fcp_prio_cfg->attributes &=
 130                                ~FCP_PRIO_ATTR_ENABLE;
 131                        qla24xx_update_all_fcp_prio(vha);
 132                        bsg_job->reply->result = DID_OK;
 133                } else {
 134                        ret = -EINVAL;
 135                        bsg_job->reply->result = (DID_ERROR << 16);
 136                        goto exit_fcp_prio_cfg;
 137                }
 138                break;
 139
 140        case QLFC_FCP_PRIO_ENABLE:
 141                if (!ha->flags.fcp_prio_enabled) {
 142                        if (ha->fcp_prio_cfg) {
 143                                ha->flags.fcp_prio_enabled = 1;
 144                                ha->fcp_prio_cfg->attributes |=
 145                                    FCP_PRIO_ATTR_ENABLE;
 146                                qla24xx_update_all_fcp_prio(vha);
 147                                bsg_job->reply->result = DID_OK;
 148                        } else {
 149                                ret = -EINVAL;
 150                                bsg_job->reply->result = (DID_ERROR << 16);
 151                                goto exit_fcp_prio_cfg;
 152                        }
 153                }
 154                break;
 155
 156        case QLFC_FCP_PRIO_GET_CONFIG:
 157                len = bsg_job->reply_payload.payload_len;
 158                if (!len || len > FCP_PRIO_CFG_SIZE) {
 159                        ret = -EINVAL;
 160                        bsg_job->reply->result = (DID_ERROR << 16);
 161                        goto exit_fcp_prio_cfg;
 162                }
 163
 164                bsg_job->reply->result = DID_OK;
 165                bsg_job->reply->reply_payload_rcv_len =
 166                        sg_copy_from_buffer(
 167                        bsg_job->reply_payload.sg_list,
 168                        bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
 169                        len);
 170
 171                break;
 172
 173        case QLFC_FCP_PRIO_SET_CONFIG:
 174                len = bsg_job->request_payload.payload_len;
 175                if (!len || len > FCP_PRIO_CFG_SIZE) {
 176                        bsg_job->reply->result = (DID_ERROR << 16);
 177                        ret = -EINVAL;
 178                        goto exit_fcp_prio_cfg;
 179                }
 180
 181                if (!ha->fcp_prio_cfg) {
 182                        ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
 183                        if (!ha->fcp_prio_cfg) {
 184                                ql_log(ql_log_warn, vha, 0x7050,
 185                                    "Unable to allocate memory for fcp prio "
 186                                    "config data (%x).\n", FCP_PRIO_CFG_SIZE);
 187                                bsg_job->reply->result = (DID_ERROR << 16);
 188                                ret = -ENOMEM;
 189                                goto exit_fcp_prio_cfg;
 190                        }
 191                }
 192
 193                memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
 194                sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 195                bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
 196                        FCP_PRIO_CFG_SIZE);
 197
 198                /* validate fcp priority data */
 199
 200                if (!qla24xx_fcp_prio_cfg_valid(vha,
 201                    (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) {
 202                        bsg_job->reply->result = (DID_ERROR << 16);
 203                        ret = -EINVAL;
 204                        /* If buffer was invalidatic int
 205                         * fcp_prio_cfg is of no use
 206                         */
 207                        vfree(ha->fcp_prio_cfg);
 208                        ha->fcp_prio_cfg = NULL;
 209                        goto exit_fcp_prio_cfg;
 210                }
 211
 212                ha->flags.fcp_prio_enabled = 0;
 213                if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
 214                        ha->flags.fcp_prio_enabled = 1;
 215                qla24xx_update_all_fcp_prio(vha);
 216                bsg_job->reply->result = DID_OK;
 217                break;
 218        default:
 219                ret = -EINVAL;
 220                break;
 221        }
 222exit_fcp_prio_cfg:
 223        bsg_job->job_done(bsg_job);
 224        return ret;
 225}
 226static int
 227qla2x00_process_els(struct fc_bsg_job *bsg_job)
 228{
 229        struct fc_rport *rport;
 230        fc_port_t *fcport = NULL;
 231        struct Scsi_Host *host;
 232        scsi_qla_host_t *vha;
 233        struct qla_hw_data *ha;
 234        srb_t *sp;
 235        const char *type;
 236        int req_sg_cnt, rsp_sg_cnt;
 237        int rval =  (DRIVER_ERROR << 16);
 238        uint16_t nextlid = 0;
 239        struct srb_ctx *els;
 240
 241        if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
 242                rport = bsg_job->rport;
 243                fcport = *(fc_port_t **) rport->dd_data;
 244                host = rport_to_shost(rport);
 245                vha = shost_priv(host);
 246                ha = vha->hw;
 247                type = "FC_BSG_RPT_ELS";
 248        } else {
 249                host = bsg_job->shost;
 250                vha = shost_priv(host);
 251                ha = vha->hw;
 252                type = "FC_BSG_HST_ELS_NOLOGIN";
 253        }
 254
 255        /* pass through is supported only for ISP 4Gb or higher */
 256        if (!IS_FWI2_CAPABLE(ha)) {
 257                ql_dbg(ql_dbg_user, vha, 0x7001,
 258                    "ELS passthru not supported for ISP23xx based adapters.\n");
 259                rval = -EPERM;
 260                goto done;
 261        }
 262
 263        /*  Multiple SG's are not supported for ELS requests */
 264        if (bsg_job->request_payload.sg_cnt > 1 ||
 265                bsg_job->reply_payload.sg_cnt > 1) {
 266                ql_dbg(ql_dbg_user, vha, 0x7002,
 267                    "Multiple SG's are not suppored for ELS requests, "
 268                    "request_sg_cnt=%x reply_sg_cnt=%x.\n",
 269                    bsg_job->request_payload.sg_cnt,
 270                    bsg_job->reply_payload.sg_cnt);
 271                rval = -EPERM;
 272                goto done;
 273        }
 274
 275        /* ELS request for rport */
 276        if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
 277                /* make sure the rport is logged in,
 278                 * if not perform fabric login
 279                 */
 280                if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
 281                        ql_dbg(ql_dbg_user, vha, 0x7003,
 282                            "Failed to login port %06X for ELS passthru.\n",
 283                            fcport->d_id.b24);
 284                        rval = -EIO;
 285                        goto done;
 286                }
 287        } else {
 288                /* Allocate a dummy fcport structure, since functions
 289                 * preparing the IOCB and mailbox command retrieves port
 290                 * specific information from fcport structure. For Host based
 291                 * ELS commands there will be no fcport structure allocated
 292                 */
 293                fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 294                if (!fcport) {
 295                        rval = -ENOMEM;
 296                        goto done;
 297                }
 298
 299                /* Initialize all required  fields of fcport */
 300                fcport->vha = vha;
 301                fcport->vp_idx = vha->vp_idx;
 302                fcport->d_id.b.al_pa =
 303                        bsg_job->request->rqst_data.h_els.port_id[0];
 304                fcport->d_id.b.area =
 305                        bsg_job->request->rqst_data.h_els.port_id[1];
 306                fcport->d_id.b.domain =
 307                        bsg_job->request->rqst_data.h_els.port_id[2];
 308                fcport->loop_id =
 309                        (fcport->d_id.b.al_pa == 0xFD) ?
 310                        NPH_FABRIC_CONTROLLER : NPH_F_PORT;
 311        }
 312
 313        if (!vha->flags.online) {
 314                ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
 315                rval = -EIO;
 316                goto done;
 317        }
 318
 319        req_sg_cnt =
 320                dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 321                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 322        if (!req_sg_cnt) {
 323                rval = -ENOMEM;
 324                goto done_free_fcport;
 325        }
 326
 327        rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 328                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 329        if (!rsp_sg_cnt) {
 330                rval = -ENOMEM;
 331                goto done_free_fcport;
 332        }
 333
 334        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
 335                (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
 336                ql_log(ql_log_warn, vha, 0x7008,
 337                    "dma mapping resulted in different sg counts, "
 338                    "request_sg_cnt: %x dma_request_sg_cnt:%x reply_sg_cnt:%x "
 339                    "dma_reply_sg_cnt:%x.\n", bsg_job->request_payload.sg_cnt,
 340                    req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
 341                rval = -EAGAIN;
 342                goto done_unmap_sg;
 343        }
 344
 345        /* Alloc SRB structure */
 346        sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
 347        if (!sp) {
 348                rval = -ENOMEM;
 349                goto done_unmap_sg;
 350        }
 351
 352        els = sp->ctx;
 353        els->type =
 354                (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
 355                SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
 356        els->name =
 357                (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
 358                "bsg_els_rpt" : "bsg_els_hst");
 359        els->u.bsg_job = bsg_job;
 360
 361        ql_dbg(ql_dbg_user, vha, 0x700a,
 362            "bsg rqst type: %s els type: %x - loop-id=%x "
 363            "portid=%-2x%02x%02x.\n", type,
 364            bsg_job->request->rqst_data.h_els.command_code, fcport->loop_id,
 365            fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
 366
 367        rval = qla2x00_start_sp(sp);
 368        if (rval != QLA_SUCCESS) {
 369                ql_log(ql_log_warn, vha, 0x700e,
 370                    "qla2x00_start_sp failed = %d\n", rval);
 371                kfree(sp->ctx);
 372                mempool_free(sp, ha->srb_mempool);
 373                rval = -EIO;
 374                goto done_unmap_sg;
 375        }
 376        return rval;
 377
 378done_unmap_sg:
 379        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 380                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 381        dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 382                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 383        goto done_free_fcport;
 384
 385done_free_fcport:
 386        if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
 387                kfree(fcport);
 388done:
 389        return rval;
 390}
 391
 392static int
 393qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 394{
 395        srb_t *sp;
 396        struct Scsi_Host *host = bsg_job->shost;
 397        scsi_qla_host_t *vha = shost_priv(host);
 398        struct qla_hw_data *ha = vha->hw;
 399        int rval = (DRIVER_ERROR << 16);
 400        int req_sg_cnt, rsp_sg_cnt;
 401        uint16_t loop_id;
 402        struct fc_port *fcport;
 403        char  *type = "FC_BSG_HST_CT";
 404        struct srb_ctx *ct;
 405
 406        req_sg_cnt =
 407                dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 408                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 409        if (!req_sg_cnt) {
 410                ql_log(ql_log_warn, vha, 0x700f,
 411                    "dma_map_sg return %d for request\n", req_sg_cnt);
 412                rval = -ENOMEM;
 413                goto done;
 414        }
 415
 416        rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 417                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 418        if (!rsp_sg_cnt) {
 419                ql_log(ql_log_warn, vha, 0x7010,
 420                    "dma_map_sg return %d for reply\n", rsp_sg_cnt);
 421                rval = -ENOMEM;
 422                goto done;
 423        }
 424
 425        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
 426            (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
 427                ql_log(ql_log_warn, vha, 0x7011,
 428                    "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
 429                    "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
 430                    req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
 431                rval = -EAGAIN;
 432                goto done_unmap_sg;
 433        }
 434
 435        if (!vha->flags.online) {
 436                ql_log(ql_log_warn, vha, 0x7012,
 437                    "Host is not online.\n");
 438                rval = -EIO;
 439                goto done_unmap_sg;
 440        }
 441
 442        loop_id =
 443                (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
 444                        >> 24;
 445        switch (loop_id) {
 446        case 0xFC:
 447                loop_id = cpu_to_le16(NPH_SNS);
 448                break;
 449        case 0xFA:
 450                loop_id = vha->mgmt_svr_loop_id;
 451                break;
 452        default:
 453                ql_dbg(ql_dbg_user, vha, 0x7013,
 454                    "Unknown loop id: %x.\n", loop_id);
 455                rval = -EINVAL;
 456                goto done_unmap_sg;
 457        }
 458
 459        /* Allocate a dummy fcport structure, since functions preparing the
 460         * IOCB and mailbox command retrieves port specific information
 461         * from fcport structure. For Host based ELS commands there will be
 462         * no fcport structure allocated
 463         */
 464        fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 465        if (!fcport) {
 466                ql_log(ql_log_warn, vha, 0x7014,
 467                    "Failed to allocate fcport.\n");
 468                rval = -ENOMEM;
 469                goto done_unmap_sg;
 470        }
 471
 472        /* Initialize all required  fields of fcport */
 473        fcport->vha = vha;
 474        fcport->vp_idx = vha->vp_idx;
 475        fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0];
 476        fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1];
 477        fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2];
 478        fcport->loop_id = loop_id;
 479
 480        /* Alloc SRB structure */
 481        sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
 482        if (!sp) {
 483                ql_log(ql_log_warn, vha, 0x7015,
 484                    "qla2x00_get_ctx_bsg_sp failed.\n");
 485                rval = -ENOMEM;
 486                goto done_free_fcport;
 487        }
 488
 489        ct = sp->ctx;
 490        ct->type = SRB_CT_CMD;
 491        ct->name = "bsg_ct";
 492        ct->u.bsg_job = bsg_job;
 493
 494        ql_dbg(ql_dbg_user, vha, 0x7016,
 495            "bsg rqst type: %s else type: %x - "
 496            "loop-id=%x portid=%02x%02x%02x.\n", type,
 497            (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
 498            fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
 499            fcport->d_id.b.al_pa);
 500
 501        rval = qla2x00_start_sp(sp);
 502        if (rval != QLA_SUCCESS) {
 503                ql_log(ql_log_warn, vha, 0x7017,
 504                    "qla2x00_start_sp failed=%d.\n", rval);
 505                kfree(sp->ctx);
 506                mempool_free(sp, ha->srb_mempool);
 507                rval = -EIO;
 508                goto done_free_fcport;
 509        }
 510        return rval;
 511
 512done_free_fcport:
 513        kfree(fcport);
 514done_unmap_sg:
 515        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 516                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 517        dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 518                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 519done:
 520        return rval;
 521}
 522
 523/* Set the port configuration to enable the
 524 * internal loopback on ISP81XX
 525 */
 526static inline int
 527qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
 528    uint16_t *new_config)
 529{
 530        int ret = 0;
 531        int rval = 0;
 532        struct qla_hw_data *ha = vha->hw;
 533
 534        if (!IS_QLA81XX(ha))
 535                goto done_set_internal;
 536
 537        new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
 538        memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
 539
 540        ha->notify_dcbx_comp = 1;
 541        ret = qla81xx_set_port_config(vha, new_config);
 542        if (ret != QLA_SUCCESS) {
 543                ql_log(ql_log_warn, vha, 0x7021,
 544                    "set port config failed.\n");
 545                ha->notify_dcbx_comp = 0;
 546                rval = -EINVAL;
 547                goto done_set_internal;
 548        }
 549
 550        /* Wait for DCBX complete event */
 551        if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
 552                ql_dbg(ql_dbg_user, vha, 0x7022,
 553                    "State change notification not received.\n");
 554        } else
 555                ql_dbg(ql_dbg_user, vha, 0x7023,
 556                    "State change received.\n");
 557
 558        ha->notify_dcbx_comp = 0;
 559
 560done_set_internal:
 561        return rval;
 562}
 563
 564/* Set the port configuration to disable the
 565 * internal loopback on ISP81XX
 566 */
 567static inline int
 568qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
 569    int wait)
 570{
 571        int ret = 0;
 572        int rval = 0;
 573        uint16_t new_config[4];
 574        struct qla_hw_data *ha = vha->hw;
 575
 576        if (!IS_QLA81XX(ha))
 577                goto done_reset_internal;
 578
 579        memset(new_config, 0 , sizeof(new_config));
 580        if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
 581                        ENABLE_INTERNAL_LOOPBACK) {
 582                new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
 583                memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
 584
 585                ha->notify_dcbx_comp = wait;
 586                ret = qla81xx_set_port_config(vha, new_config);
 587                if (ret != QLA_SUCCESS) {
 588                        ql_log(ql_log_warn, vha, 0x7025,
 589                            "Set port config failed.\n");
 590                        ha->notify_dcbx_comp = 0;
 591                        rval = -EINVAL;
 592                        goto done_reset_internal;
 593                }
 594
 595                /* Wait for DCBX complete event */
 596                if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
 597                        (20 * HZ))) {
 598                        ql_dbg(ql_dbg_user, vha, 0x7026,
 599                            "State change notification not received.\n");
 600                        ha->notify_dcbx_comp = 0;
 601                        rval = -EINVAL;
 602                        goto done_reset_internal;
 603                } else
 604                        ql_dbg(ql_dbg_user, vha, 0x7027,
 605                            "State change received.\n");
 606
 607                ha->notify_dcbx_comp = 0;
 608        }
 609done_reset_internal:
 610        return rval;
 611}
 612
 613static int
 614qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 615{
 616        struct Scsi_Host *host = bsg_job->shost;
 617        scsi_qla_host_t *vha = shost_priv(host);
 618        struct qla_hw_data *ha = vha->hw;
 619        int rval;
 620        uint8_t command_sent;
 621        char *type;
 622        struct msg_echo_lb elreq;
 623        uint16_t response[MAILBOX_REGISTER_COUNT];
 624        uint16_t config[4], new_config[4];
 625        uint8_t *fw_sts_ptr;
 626        uint8_t *req_data = NULL;
 627        dma_addr_t req_data_dma;
 628        uint32_t req_data_len;
 629        uint8_t *rsp_data = NULL;
 630        dma_addr_t rsp_data_dma;
 631        uint32_t rsp_data_len;
 632
 633        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
 634                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
 635                test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 636                ql_log(ql_log_warn, vha, 0x7018, "Abort active or needed.\n");
 637                return -EBUSY;
 638        }
 639
 640        if (!vha->flags.online) {
 641                ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
 642                return -EIO;
 643        }
 644
 645        elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
 646                bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
 647                DMA_TO_DEVICE);
 648
 649        if (!elreq.req_sg_cnt) {
 650                ql_log(ql_log_warn, vha, 0x701a,
 651                    "dma_map_sg returned %d for request.\n", elreq.req_sg_cnt);
 652                return -ENOMEM;
 653        }
 654
 655        elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
 656                bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
 657                DMA_FROM_DEVICE);
 658
 659        if (!elreq.rsp_sg_cnt) {
 660                ql_log(ql_log_warn, vha, 0x701b,
 661                    "dma_map_sg returned %d for reply.\n", elreq.rsp_sg_cnt);
 662                rval = -ENOMEM;
 663                goto done_unmap_req_sg;
 664        }
 665
 666        if ((elreq.req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
 667                (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
 668                ql_log(ql_log_warn, vha, 0x701c,
 669                    "dma mapping resulted in different sg counts, "
 670                    "request_sg_cnt: %x dma_request_sg_cnt: %x "
 671                    "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
 672                    bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
 673                    bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt);
 674                rval = -EAGAIN;
 675                goto done_unmap_sg;
 676        }
 677        req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
 678        req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
 679                &req_data_dma, GFP_KERNEL);
 680        if (!req_data) {
 681                ql_log(ql_log_warn, vha, 0x701d,
 682                    "dma alloc failed for req_data.\n");
 683                rval = -ENOMEM;
 684                goto done_unmap_sg;
 685        }
 686
 687        rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
 688                &rsp_data_dma, GFP_KERNEL);
 689        if (!rsp_data) {
 690                ql_log(ql_log_warn, vha, 0x7004,
 691                    "dma alloc failed for rsp_data.\n");
 692                rval = -ENOMEM;
 693                goto done_free_dma_req;
 694        }
 695
 696        /* Copy the request buffer in req_data now */
 697        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 698                bsg_job->request_payload.sg_cnt, req_data, req_data_len);
 699
 700        elreq.send_dma = req_data_dma;
 701        elreq.rcv_dma = rsp_data_dma;
 702        elreq.transfer_size = req_data_len;
 703
 704        elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
 705
 706        if ((ha->current_topology == ISP_CFG_F ||
 707            (IS_QLA81XX(ha) &&
 708            le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
 709            && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
 710                elreq.options == EXTERNAL_LOOPBACK) {
 711                type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
 712                ql_dbg(ql_dbg_user, vha, 0x701e,
 713                    "BSG request type: %s.\n", type);
 714                command_sent = INT_DEF_LB_ECHO_CMD;
 715                rval = qla2x00_echo_test(vha, &elreq, response);
 716        } else {
 717                if (IS_QLA81XX(ha)) {
 718                        memset(config, 0, sizeof(config));
 719                        memset(new_config, 0, sizeof(new_config));
 720                        if (qla81xx_get_port_config(vha, config)) {
 721                                ql_log(ql_log_warn, vha, 0x701f,
 722                                    "Get port config failed.\n");
 723                                bsg_job->reply->reply_payload_rcv_len = 0;
 724                                bsg_job->reply->result = (DID_ERROR << 16);
 725                                rval = -EPERM;
 726                                goto done_free_dma_req;
 727                        }
 728
 729                        if (elreq.options != EXTERNAL_LOOPBACK) {
 730                                ql_dbg(ql_dbg_user, vha, 0x7020,
 731                                    "Internal: curent port config = %x\n",
 732                                    config[0]);
 733                                if (qla81xx_set_internal_loopback(vha, config,
 734                                        new_config)) {
 735                                        ql_log(ql_log_warn, vha, 0x7024,
 736                                            "Internal loopback failed.\n");
 737                                        bsg_job->reply->reply_payload_rcv_len =
 738                                                0;
 739                                        bsg_job->reply->result =
 740                                                (DID_ERROR << 16);
 741                                        rval = -EPERM;
 742                                        goto done_free_dma_req;
 743                                }
 744                        } else {
 745                                /* For external loopback to work
 746                                 * ensure internal loopback is disabled
 747                                 */
 748                                if (qla81xx_reset_internal_loopback(vha,
 749                                        config, 1)) {
 750                                        bsg_job->reply->reply_payload_rcv_len =
 751                                                0;
 752                                        bsg_job->reply->result =
 753                                                (DID_ERROR << 16);
 754                                        rval = -EPERM;
 755                                        goto done_free_dma_req;
 756                                }
 757                        }
 758
 759                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
 760                        ql_dbg(ql_dbg_user, vha, 0x7028,
 761                            "BSG request type: %s.\n", type);
 762
 763                        command_sent = INT_DEF_LB_LOOPBACK_CMD;
 764                        rval = qla2x00_loopback_test(vha, &elreq, response);
 765
 766                        if (new_config[0]) {
 767                                /* Revert back to original port config
 768                                 * Also clear internal loopback
 769                                 */
 770                                qla81xx_reset_internal_loopback(vha,
 771                                    new_config, 0);
 772                        }
 773
 774                        if (response[0] == MBS_COMMAND_ERROR &&
 775                                        response[1] == MBS_LB_RESET) {
 776                                ql_log(ql_log_warn, vha, 0x7029,
 777                                    "MBX command error, Aborting ISP.\n");
 778                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 779                                qla2xxx_wake_dpc(vha);
 780                                qla2x00_wait_for_chip_reset(vha);
 781                                /* Also reset the MPI */
 782                                if (qla81xx_restart_mpi_firmware(vha) !=
 783                                    QLA_SUCCESS) {
 784                                        ql_log(ql_log_warn, vha, 0x702a,
 785                                            "MPI reset failed.\n");
 786                                }
 787
 788                                bsg_job->reply->reply_payload_rcv_len = 0;
 789                                bsg_job->reply->result = (DID_ERROR << 16);
 790                                rval = -EIO;
 791                                goto done_free_dma_req;
 792                        }
 793                } else {
 794                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
 795                        ql_dbg(ql_dbg_user, vha, 0x702b,
 796                            "BSG request type: %s.\n", type);
 797                        command_sent = INT_DEF_LB_LOOPBACK_CMD;
 798                        rval = qla2x00_loopback_test(vha, &elreq, response);
 799                }
 800        }
 801
 802        if (rval) {
 803                ql_log(ql_log_warn, vha, 0x702c,
 804                    "Vendor request %s failed.\n", type);
 805
 806                fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
 807                    sizeof(struct fc_bsg_reply);
 808
 809                memcpy(fw_sts_ptr, response, sizeof(response));
 810                fw_sts_ptr += sizeof(response);
 811                *fw_sts_ptr = command_sent;
 812                rval = 0;
 813                bsg_job->reply->reply_payload_rcv_len = 0;
 814                bsg_job->reply->result = (DID_ERROR << 16);
 815        } else {
 816                ql_dbg(ql_dbg_user, vha, 0x702d,
 817                    "Vendor request %s completed.\n", type);
 818
 819                bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
 820                        sizeof(response) + sizeof(uint8_t);
 821                bsg_job->reply->reply_payload_rcv_len =
 822                        bsg_job->reply_payload.payload_len;
 823                fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
 824                        sizeof(struct fc_bsg_reply);
 825                memcpy(fw_sts_ptr, response, sizeof(response));
 826                fw_sts_ptr += sizeof(response);
 827                *fw_sts_ptr = command_sent;
 828                bsg_job->reply->result = DID_OK;
 829                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
 830                        bsg_job->reply_payload.sg_cnt, rsp_data,
 831                        rsp_data_len);
 832        }
 833        bsg_job->job_done(bsg_job);
 834
 835        dma_free_coherent(&ha->pdev->dev, rsp_data_len,
 836                rsp_data, rsp_data_dma);
 837done_free_dma_req:
 838        dma_free_coherent(&ha->pdev->dev, req_data_len,
 839                req_data, req_data_dma);
 840done_unmap_sg:
 841        dma_unmap_sg(&ha->pdev->dev,
 842            bsg_job->reply_payload.sg_list,
 843            bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 844done_unmap_req_sg:
 845        dma_unmap_sg(&ha->pdev->dev,
 846            bsg_job->request_payload.sg_list,
 847            bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 848        return rval;
 849}
 850
 851static int
 852qla84xx_reset(struct fc_bsg_job *bsg_job)
 853{
 854        struct Scsi_Host *host = bsg_job->shost;
 855        scsi_qla_host_t *vha = shost_priv(host);
 856        struct qla_hw_data *ha = vha->hw;
 857        int rval = 0;
 858        uint32_t flag;
 859
 860        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
 861            test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
 862            test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 863                ql_log(ql_log_warn, vha, 0x702e, "Abort active or needed.\n");
 864                return -EBUSY;
 865        }
 866
 867        if (!IS_QLA84XX(ha)) {
 868                ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
 869                return -EINVAL;
 870        }
 871
 872        flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
 873
 874        rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
 875
 876        if (rval) {
 877                ql_log(ql_log_warn, vha, 0x7030,
 878                    "Vendor request 84xx reset failed.\n");
 879                rval = bsg_job->reply->reply_payload_rcv_len = 0;
 880                bsg_job->reply->result = (DID_ERROR << 16);
 881
 882        } else {
 883                ql_dbg(ql_dbg_user, vha, 0x7031,
 884                    "Vendor request 84xx reset completed.\n");
 885                bsg_job->reply->result = DID_OK;
 886        }
 887
 888        bsg_job->job_done(bsg_job);
 889        return rval;
 890}
 891
 892static int
 893qla84xx_updatefw(struct fc_bsg_job *bsg_job)
 894{
 895        struct Scsi_Host *host = bsg_job->shost;
 896        scsi_qla_host_t *vha = shost_priv(host);
 897        struct qla_hw_data *ha = vha->hw;
 898        struct verify_chip_entry_84xx *mn = NULL;
 899        dma_addr_t mn_dma, fw_dma;
 900        void *fw_buf = NULL;
 901        int rval = 0;
 902        uint32_t sg_cnt;
 903        uint32_t data_len;
 904        uint16_t options;
 905        uint32_t flag;
 906        uint32_t fw_ver;
 907
 908        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
 909                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
 910                test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
 911                return -EBUSY;
 912
 913        if (!IS_QLA84XX(ha)) {
 914                ql_dbg(ql_dbg_user, vha, 0x7032,
 915                    "Not 84xx, exiting.\n");
 916                return -EINVAL;
 917        }
 918
 919        sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 920                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 921        if (!sg_cnt) {
 922                ql_log(ql_log_warn, vha, 0x7033,
 923                    "dma_map_sg returned %d for request.\n", sg_cnt);
 924                return -ENOMEM;
 925        }
 926
 927        if (sg_cnt != bsg_job->request_payload.sg_cnt) {
 928                ql_log(ql_log_warn, vha, 0x7034,
 929                    "DMA mapping resulted in different sg counts, "
 930                    "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
 931                    bsg_job->request_payload.sg_cnt, sg_cnt);
 932                rval = -EAGAIN;
 933                goto done_unmap_sg;
 934        }
 935
 936        data_len = bsg_job->request_payload.payload_len;
 937        fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
 938                &fw_dma, GFP_KERNEL);
 939        if (!fw_buf) {
 940                ql_log(ql_log_warn, vha, 0x7035,
 941                    "DMA alloc failed for fw_buf.\n");
 942                rval = -ENOMEM;
 943                goto done_unmap_sg;
 944        }
 945
 946        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 947                bsg_job->request_payload.sg_cnt, fw_buf, data_len);
 948
 949        mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
 950        if (!mn) {
 951                ql_log(ql_log_warn, vha, 0x7036,
 952                    "DMA alloc failed for fw buffer.\n");
 953                rval = -ENOMEM;
 954                goto done_free_fw_buf;
 955        }
 956
 957        flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
 958        fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2)));
 959
 960        memset(mn, 0, sizeof(struct access_chip_84xx));
 961        mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
 962        mn->entry_count = 1;
 963
 964        options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
 965        if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD)
 966                options |= VCO_DIAG_FW;
 967
 968        mn->options = cpu_to_le16(options);
 969        mn->fw_ver =  cpu_to_le32(fw_ver);
 970        mn->fw_size =  cpu_to_le32(data_len);
 971        mn->fw_seq_size =  cpu_to_le32(data_len);
 972        mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma));
 973        mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma));
 974        mn->dseg_length = cpu_to_le32(data_len);
 975        mn->data_seg_cnt = cpu_to_le16(1);
 976
 977        rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
 978
 979        if (rval) {
 980                ql_log(ql_log_warn, vha, 0x7037,
 981                    "Vendor request 84xx updatefw failed.\n");
 982
 983                rval = bsg_job->reply->reply_payload_rcv_len = 0;
 984                bsg_job->reply->result = (DID_ERROR << 16);
 985
 986        } else {
 987                ql_dbg(ql_dbg_user, vha, 0x7038,
 988                    "Vendor request 84xx updatefw completed.\n");
 989
 990                bsg_job->reply_len = sizeof(struct fc_bsg_reply);
 991                bsg_job->reply->result = DID_OK;
 992        }
 993
 994        bsg_job->job_done(bsg_job);
 995        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
 996
 997done_free_fw_buf:
 998        dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma);
 999
1000done_unmap_sg:
1001        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1002                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1003
1004        return rval;
1005}
1006
1007static int
1008qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
1009{
1010        struct Scsi_Host *host = bsg_job->shost;
1011        scsi_qla_host_t *vha = shost_priv(host);
1012        struct qla_hw_data *ha = vha->hw;
1013        struct access_chip_84xx *mn = NULL;
1014        dma_addr_t mn_dma, mgmt_dma;
1015        void *mgmt_b = NULL;
1016        int rval = 0;
1017        struct qla_bsg_a84_mgmt *ql84_mgmt;
1018        uint32_t sg_cnt;
1019        uint32_t data_len = 0;
1020        uint32_t dma_direction = DMA_NONE;
1021
1022        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1023                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1024                test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
1025                ql_log(ql_log_warn, vha, 0x7039,
1026                    "Abort active or needed.\n");
1027                return -EBUSY;
1028        }
1029
1030        if (!IS_QLA84XX(ha)) {
1031                ql_log(ql_log_warn, vha, 0x703a,
1032                    "Not 84xx, exiting.\n");
1033                return -EINVAL;
1034        }
1035
1036        ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request +
1037                sizeof(struct fc_bsg_request));
1038        if (!ql84_mgmt) {
1039                ql_log(ql_log_warn, vha, 0x703b,
1040                    "MGMT header not provided, exiting.\n");
1041                return -EINVAL;
1042        }
1043
1044        mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1045        if (!mn) {
1046                ql_log(ql_log_warn, vha, 0x703c,
1047                    "DMA alloc failed for fw buffer.\n");
1048                return -ENOMEM;
1049        }
1050
1051        memset(mn, 0, sizeof(struct access_chip_84xx));
1052        mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
1053        mn->entry_count = 1;
1054
1055        switch (ql84_mgmt->mgmt.cmd) {
1056        case QLA84_MGMT_READ_MEM:
1057        case QLA84_MGMT_GET_INFO:
1058                sg_cnt = dma_map_sg(&ha->pdev->dev,
1059                        bsg_job->reply_payload.sg_list,
1060                        bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1061                if (!sg_cnt) {
1062                        ql_log(ql_log_warn, vha, 0x703d,
1063                            "dma_map_sg returned %d for reply.\n", sg_cnt);
1064                        rval = -ENOMEM;
1065                        goto exit_mgmt;
1066                }
1067
1068                dma_direction = DMA_FROM_DEVICE;
1069
1070                if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
1071                        ql_log(ql_log_warn, vha, 0x703e,
1072                            "DMA mapping resulted in different sg counts, "
1073                            "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
1074                            bsg_job->reply_payload.sg_cnt, sg_cnt);
1075                        rval = -EAGAIN;
1076                        goto done_unmap_sg;
1077                }
1078
1079                data_len = bsg_job->reply_payload.payload_len;
1080
1081                mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1082                    &mgmt_dma, GFP_KERNEL);
1083                if (!mgmt_b) {
1084                        ql_log(ql_log_warn, vha, 0x703f,
1085                            "DMA alloc failed for mgmt_b.\n");
1086                        rval = -ENOMEM;
1087                        goto done_unmap_sg;
1088                }
1089
1090                if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) {
1091                        mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
1092                        mn->parameter1 =
1093                                cpu_to_le32(
1094                                ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1095
1096                } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) {
1097                        mn->options = cpu_to_le16(ACO_REQUEST_INFO);
1098                        mn->parameter1 =
1099                                cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type);
1100
1101                        mn->parameter2 =
1102                                cpu_to_le32(
1103                                ql84_mgmt->mgmt.mgmtp.u.info.context);
1104                }
1105                break;
1106
1107        case QLA84_MGMT_WRITE_MEM:
1108                sg_cnt = dma_map_sg(&ha->pdev->dev,
1109                        bsg_job->request_payload.sg_list,
1110                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1111
1112                if (!sg_cnt) {
1113                        ql_log(ql_log_warn, vha, 0x7040,
1114                            "dma_map_sg returned %d.\n", sg_cnt);
1115                        rval = -ENOMEM;
1116                        goto exit_mgmt;
1117                }
1118
1119                dma_direction = DMA_TO_DEVICE;
1120
1121                if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1122                        ql_log(ql_log_warn, vha, 0x7041,
1123                            "DMA mapping resulted in different sg counts, "
1124                            "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1125                            bsg_job->request_payload.sg_cnt, sg_cnt);
1126                        rval = -EAGAIN;
1127                        goto done_unmap_sg;
1128                }
1129
1130                data_len = bsg_job->request_payload.payload_len;
1131                mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1132                        &mgmt_dma, GFP_KERNEL);
1133                if (!mgmt_b) {
1134                        ql_log(ql_log_warn, vha, 0x7042,
1135                            "DMA alloc failed for mgmt_b.\n");
1136                        rval = -ENOMEM;
1137                        goto done_unmap_sg;
1138                }
1139
1140                sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1141                        bsg_job->request_payload.sg_cnt, mgmt_b, data_len);
1142
1143                mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
1144                mn->parameter1 =
1145                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1146                break;
1147
1148        case QLA84_MGMT_CHNG_CONFIG:
1149                mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
1150                mn->parameter1 =
1151                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id);
1152
1153                mn->parameter2 =
1154                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0);
1155
1156                mn->parameter3 =
1157                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1);
1158                break;
1159
1160        default:
1161                rval = -EIO;
1162                goto exit_mgmt;
1163        }
1164
1165        if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
1166                mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
1167                mn->dseg_count = cpu_to_le16(1);
1168                mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma));
1169                mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma));
1170                mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len);
1171        }
1172
1173        rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
1174
1175        if (rval) {
1176                ql_log(ql_log_warn, vha, 0x7043,
1177                    "Vendor request 84xx mgmt failed.\n");
1178
1179                rval = bsg_job->reply->reply_payload_rcv_len = 0;
1180                bsg_job->reply->result = (DID_ERROR << 16);
1181
1182        } else {
1183                ql_dbg(ql_dbg_user, vha, 0x7044,
1184                    "Vendor request 84xx mgmt completed.\n");
1185
1186                bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1187                bsg_job->reply->result = DID_OK;
1188
1189                if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
1190                        (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
1191                        bsg_job->reply->reply_payload_rcv_len =
1192                                bsg_job->reply_payload.payload_len;
1193
1194                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1195                                bsg_job->reply_payload.sg_cnt, mgmt_b,
1196                                data_len);
1197                }
1198        }
1199
1200        bsg_job->job_done(bsg_job);
1201
1202done_unmap_sg:
1203        if (mgmt_b)
1204                dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
1205
1206        if (dma_direction == DMA_TO_DEVICE)
1207                dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1208                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1209        else if (dma_direction == DMA_FROM_DEVICE)
1210                dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1211                        bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1212
1213exit_mgmt:
1214        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1215
1216        return rval;
1217}
1218
1219static int
1220qla24xx_iidma(struct fc_bsg_job *bsg_job)
1221{
1222        struct Scsi_Host *host = bsg_job->shost;
1223        scsi_qla_host_t *vha = shost_priv(host);
1224        int rval = 0;
1225        struct qla_port_param *port_param = NULL;
1226        fc_port_t *fcport = NULL;
1227        uint16_t mb[MAILBOX_REGISTER_COUNT];
1228        uint8_t *rsp_ptr = NULL;
1229
1230        bsg_job->reply->reply_payload_rcv_len = 0;
1231
1232        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1233                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1234                test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
1235                ql_log(ql_log_warn, vha, 0x7045, "abort active or needed.\n");
1236                return -EBUSY;
1237        }
1238
1239        if (!IS_IIDMA_CAPABLE(vha->hw)) {
1240                ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
1241                return -EINVAL;
1242        }
1243
1244        port_param = (struct qla_port_param *)((char *)bsg_job->request +
1245                sizeof(struct fc_bsg_request));
1246        if (!port_param) {
1247                ql_log(ql_log_warn, vha, 0x7047,
1248                    "port_param header not provided.\n");
1249                return -EINVAL;
1250        }
1251
1252        if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
1253                ql_log(ql_log_warn, vha, 0x7048,
1254                    "Invalid destination type.\n");
1255                return -EINVAL;
1256        }
1257
1258        list_for_each_entry(fcport, &vha->vp_fcports, list) {
1259                if (fcport->port_type != FCT_TARGET)
1260                        continue;
1261
1262                if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn,
1263                        fcport->port_name, sizeof(fcport->port_name)))
1264                        continue;
1265                break;
1266        }
1267
1268        if (!fcport) {
1269                ql_log(ql_log_warn, vha, 0x7049,
1270                    "Failed to find port.\n");
1271                return -EINVAL;
1272        }
1273
1274        if (atomic_read(&fcport->state) != FCS_ONLINE) {
1275                ql_log(ql_log_warn, vha, 0x704a,
1276                    "Port is not online.\n");
1277                return -EINVAL;
1278        }
1279
1280        if (fcport->flags & FCF_LOGIN_NEEDED) {
1281                ql_log(ql_log_warn, vha, 0x704b,
1282                    "Remote port not logged in flags = 0x%x.\n", fcport->flags);
1283                return -EINVAL;
1284        }
1285
1286        if (port_param->mode)
1287                rval = qla2x00_set_idma_speed(vha, fcport->loop_id,
1288                        port_param->speed, mb);
1289        else
1290                rval = qla2x00_get_idma_speed(vha, fcport->loop_id,
1291                        &port_param->speed, mb);
1292
1293        if (rval) {
1294                ql_log(ql_log_warn, vha, 0x704c,
1295                    "iIDMA cmd failed for %02x%02x%02x%02x%02x%02x%02x%02x -- "
1296                    "%04x %x %04x %04x.\n", fcport->port_name[0],
1297                    fcport->port_name[1], fcport->port_name[2],
1298                    fcport->port_name[3], fcport->port_name[4],
1299                    fcport->port_name[5], fcport->port_name[6],
1300                    fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]);
1301                rval = 0;
1302                bsg_job->reply->result = (DID_ERROR << 16);
1303
1304        } else {
1305                if (!port_param->mode) {
1306                        bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
1307                                sizeof(struct qla_port_param);
1308
1309                        rsp_ptr = ((uint8_t *)bsg_job->reply) +
1310                                sizeof(struct fc_bsg_reply);
1311
1312                        memcpy(rsp_ptr, port_param,
1313                                sizeof(struct qla_port_param));
1314                }
1315
1316                bsg_job->reply->result = DID_OK;
1317        }
1318
1319        bsg_job->job_done(bsg_job);
1320        return rval;
1321}
1322
1323static int
1324qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, scsi_qla_host_t *vha,
1325        uint8_t is_update)
1326{
1327        uint32_t start = 0;
1328        int valid = 0;
1329        struct qla_hw_data *ha = vha->hw;
1330
1331        bsg_job->reply->reply_payload_rcv_len = 0;
1332
1333        if (unlikely(pci_channel_offline(ha->pdev)))
1334                return -EINVAL;
1335
1336        start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
1337        if (start > ha->optrom_size) {
1338                ql_log(ql_log_warn, vha, 0x7055,
1339                    "start %d > optrom_size %d.\n", start, ha->optrom_size);
1340                return -EINVAL;
1341        }
1342
1343        if (ha->optrom_state != QLA_SWAITING) {
1344                ql_log(ql_log_info, vha, 0x7056,
1345                    "optrom_state %d.\n", ha->optrom_state);
1346                return -EBUSY;
1347        }
1348
1349        ha->optrom_region_start = start;
1350        ql_dbg(ql_dbg_user, vha, 0x7057, "is_update=%d.\n", is_update);
1351        if (is_update) {
1352                if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
1353                        valid = 1;
1354                else if (start == (ha->flt_region_boot * 4) ||
1355                    start == (ha->flt_region_fw * 4))
1356                        valid = 1;
1357                else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
1358                    IS_QLA8XXX_TYPE(ha))
1359                        valid = 1;
1360                if (!valid) {
1361                        ql_log(ql_log_warn, vha, 0x7058,
1362                            "Invalid start region 0x%x/0x%x.\n", start,
1363                            bsg_job->request_payload.payload_len);
1364                        return -EINVAL;
1365                }
1366
1367                ha->optrom_region_size = start +
1368                    bsg_job->request_payload.payload_len > ha->optrom_size ?
1369                    ha->optrom_size - start :
1370                    bsg_job->request_payload.payload_len;
1371                ha->optrom_state = QLA_SWRITING;
1372        } else {
1373                ha->optrom_region_size = start +
1374                    bsg_job->reply_payload.payload_len > ha->optrom_size ?
1375                    ha->optrom_size - start :
1376                    bsg_job->reply_payload.payload_len;
1377                ha->optrom_state = QLA_SREADING;
1378        }
1379
1380        ha->optrom_buffer = vmalloc(ha->optrom_region_size);
1381        if (!ha->optrom_buffer) {
1382                ql_log(ql_log_warn, vha, 0x7059,
1383                    "Read: Unable to allocate memory for optrom retrieval "
1384                    "(%x)\n", ha->optrom_region_size);
1385
1386                ha->optrom_state = QLA_SWAITING;
1387                return -ENOMEM;
1388        }
1389
1390        memset(ha->optrom_buffer, 0, ha->optrom_region_size);
1391        return 0;
1392}
1393
1394static int
1395qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
1396{
1397        struct Scsi_Host *host = bsg_job->shost;
1398        scsi_qla_host_t *vha = shost_priv(host);
1399        struct qla_hw_data *ha = vha->hw;
1400        int rval = 0;
1401
1402        rval = qla2x00_optrom_setup(bsg_job, vha, 0);
1403        if (rval)
1404                return rval;
1405
1406        ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
1407            ha->optrom_region_start, ha->optrom_region_size);
1408
1409        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1410            bsg_job->reply_payload.sg_cnt, ha->optrom_buffer,
1411            ha->optrom_region_size);
1412
1413        bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size;
1414        bsg_job->reply->result = DID_OK;
1415        vfree(ha->optrom_buffer);
1416        ha->optrom_buffer = NULL;
1417        ha->optrom_state = QLA_SWAITING;
1418        bsg_job->job_done(bsg_job);
1419        return rval;
1420}
1421
1422static int
1423qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
1424{
1425        struct Scsi_Host *host = bsg_job->shost;
1426        scsi_qla_host_t *vha = shost_priv(host);
1427        struct qla_hw_data *ha = vha->hw;
1428        int rval = 0;
1429
1430        rval = qla2x00_optrom_setup(bsg_job, vha, 1);
1431        if (rval)
1432                return rval;
1433
1434        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1435            bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
1436            ha->optrom_region_size);
1437
1438        ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
1439            ha->optrom_region_start, ha->optrom_region_size);
1440
1441        bsg_job->reply->result = DID_OK;
1442        vfree(ha->optrom_buffer);
1443        ha->optrom_buffer = NULL;
1444        ha->optrom_state = QLA_SWAITING;
1445        bsg_job->job_done(bsg_job);
1446        return rval;
1447}
1448
1449static int
1450qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
1451{
1452        switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
1453        case QL_VND_LOOPBACK:
1454                return qla2x00_process_loopback(bsg_job);
1455
1456        case QL_VND_A84_RESET:
1457                return qla84xx_reset(bsg_job);
1458
1459        case QL_VND_A84_UPDATE_FW:
1460                return qla84xx_updatefw(bsg_job);
1461
1462        case QL_VND_A84_MGMT_CMD:
1463                return qla84xx_mgmt_cmd(bsg_job);
1464
1465        case QL_VND_IIDMA:
1466                return qla24xx_iidma(bsg_job);
1467
1468        case QL_VND_FCP_PRIO_CFG_CMD:
1469                return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
1470
1471        case QL_VND_READ_FLASH:
1472                return qla2x00_read_optrom(bsg_job);
1473
1474        case QL_VND_UPDATE_FLASH:
1475                return qla2x00_update_optrom(bsg_job);
1476
1477        default:
1478                bsg_job->reply->result = (DID_ERROR << 16);
1479                bsg_job->job_done(bsg_job);
1480                return -ENOSYS;
1481        }
1482}
1483
1484int
1485qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
1486{
1487        int ret = -EINVAL;
1488        struct fc_rport *rport;
1489        fc_port_t *fcport = NULL;
1490        struct Scsi_Host *host;
1491        scsi_qla_host_t *vha;
1492
1493        if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
1494                rport = bsg_job->rport;
1495                fcport = *(fc_port_t **) rport->dd_data;
1496                host = rport_to_shost(rport);
1497                vha = shost_priv(host);
1498        } else {
1499                host = bsg_job->shost;
1500                vha = shost_priv(host);
1501        }
1502
1503        ql_dbg(ql_dbg_user, vha, 0x7000,
1504            "Entered %s msgcode=%d.\n", __func__, bsg_job->request->msgcode);
1505
1506        switch (bsg_job->request->msgcode) {
1507        case FC_BSG_RPT_ELS:
1508        case FC_BSG_HST_ELS_NOLOGIN:
1509                ret = qla2x00_process_els(bsg_job);
1510                break;
1511        case FC_BSG_HST_CT:
1512                ret = qla2x00_process_ct(bsg_job);
1513                break;
1514        case FC_BSG_HST_VENDOR:
1515                ret = qla2x00_process_vendor_specific(bsg_job);
1516                break;
1517        case FC_BSG_HST_ADD_RPORT:
1518        case FC_BSG_HST_DEL_RPORT:
1519        case FC_BSG_RPT_CT:
1520        default:
1521                ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
1522                break;
1523        }
1524        return ret;
1525}
1526
1527int
1528qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
1529{
1530        scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
1531        struct qla_hw_data *ha = vha->hw;
1532        srb_t *sp;
1533        int cnt, que;
1534        unsigned long flags;
1535        struct req_que *req;
1536        struct srb_ctx *sp_bsg;
1537
1538        /* find the bsg job from the active list of commands */
1539        spin_lock_irqsave(&ha->hardware_lock, flags);
1540        for (que = 0; que < ha->max_req_queues; que++) {
1541                req = ha->req_q_map[que];
1542                if (!req)
1543                        continue;
1544
1545                for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
1546                        sp = req->outstanding_cmds[cnt];
1547                        if (sp) {
1548                                sp_bsg = sp->ctx;
1549
1550                                if (((sp_bsg->type == SRB_CT_CMD) ||
1551                                        (sp_bsg->type == SRB_ELS_CMD_HST))
1552                                        && (sp_bsg->u.bsg_job == bsg_job)) {
1553                                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
1554                                        if (ha->isp_ops->abort_command(sp)) {
1555                                                ql_log(ql_log_warn, vha, 0x7089,
1556                                                    "mbx abort_command "
1557                                                    "failed.\n");
1558                                                bsg_job->req->errors =
1559                                                bsg_job->reply->result = -EIO;
1560                                        } else {
1561                                                ql_dbg(ql_dbg_user, vha, 0x708a,
1562                                                    "mbx abort_command "
1563                                                    "success.\n");
1564                                                bsg_job->req->errors =
1565                                                bsg_job->reply->result = 0;
1566                                        }
1567                                        spin_lock_irqsave(&ha->hardware_lock, flags);
1568                                        goto done;
1569                                }
1570                        }
1571                }
1572        }
1573        spin_unlock_irqrestore(&ha->hardware_lock, flags);
1574        ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
1575        bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
1576        return 0;
1577
1578done:
1579        spin_unlock_irqrestore(&ha->hardware_lock, flags);
1580        if (bsg_job->request->msgcode == FC_BSG_HST_CT)
1581                kfree(sp->fcport);
1582        kfree(sp->ctx);
1583        mempool_free(sp, ha->srb_mempool);
1584        return 0;
1585}
1586