linux/drivers/scsi/qla2xxx/qla_bsg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * QLogic Fibre Channel HBA Driver
   4 * Copyright (c)  2003-2014 QLogic Corporation
   5 */
   6#include "qla_def.h"
   7#include "qla_gbl.h"
   8
   9#include <linux/kthread.h>
  10#include <linux/vmalloc.h>
  11#include <linux/delay.h>
  12#include <linux/bsg-lib.h>
  13
  14static void qla2xxx_free_fcport_work(struct work_struct *work)
  15{
  16        struct fc_port *fcport = container_of(work, typeof(*fcport),
  17            free_work);
  18
  19        qla2x00_free_fcport(fcport);
  20}
  21
  22/* BSG support for ELS/CT pass through */
  23void qla2x00_bsg_job_done(srb_t *sp, int res)
  24{
  25        struct bsg_job *bsg_job = sp->u.bsg_job;
  26        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
  27
  28        sp->free(sp);
  29
  30        bsg_reply->result = res;
  31        bsg_job_done(bsg_job, bsg_reply->result,
  32                       bsg_reply->reply_payload_rcv_len);
  33}
  34
  35void qla2x00_bsg_sp_free(srb_t *sp)
  36{
  37        struct qla_hw_data *ha = sp->vha->hw;
  38        struct bsg_job *bsg_job = sp->u.bsg_job;
  39        struct fc_bsg_request *bsg_request = bsg_job->request;
  40        struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
  41
  42        if (sp->type == SRB_FXIOCB_BCMD) {
  43                piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
  44                    &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
  45
  46                if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
  47                        dma_unmap_sg(&ha->pdev->dev,
  48                            bsg_job->request_payload.sg_list,
  49                            bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
  50
  51                if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
  52                        dma_unmap_sg(&ha->pdev->dev,
  53                            bsg_job->reply_payload.sg_list,
  54                            bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
  55        } else {
  56                dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
  57                    bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
  58
  59                dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
  60                    bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
  61        }
  62
  63        if (sp->type == SRB_CT_CMD ||
  64            sp->type == SRB_FXIOCB_BCMD ||
  65            sp->type == SRB_ELS_CMD_HST) {
  66                INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work);
  67                queue_work(ha->wq, &sp->fcport->free_work);
  68        }
  69
  70        qla2x00_rel_sp(sp);
  71}
  72
  73int
  74qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
  75        struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
  76{
  77        int i, ret, num_valid;
  78        uint8_t *bcode;
  79        struct qla_fcp_prio_entry *pri_entry;
  80        uint32_t *bcode_val_ptr, bcode_val;
  81
  82        ret = 1;
  83        num_valid = 0;
  84        bcode = (uint8_t *)pri_cfg;
  85        bcode_val_ptr = (uint32_t *)pri_cfg;
  86        bcode_val = (uint32_t)(*bcode_val_ptr);
  87
  88        if (bcode_val == 0xFFFFFFFF) {
  89                /* No FCP Priority config data in flash */
  90                ql_dbg(ql_dbg_user, vha, 0x7051,
  91                    "No FCP Priority config data.\n");
  92                return 0;
  93        }
  94
  95        if (memcmp(bcode, "HQOS", 4)) {
  96                /* Invalid FCP priority data header*/
  97                ql_dbg(ql_dbg_user, vha, 0x7052,
  98                    "Invalid FCP Priority data header. bcode=0x%x.\n",
  99                    bcode_val);
 100                return 0;
 101        }
 102        if (flag != 1)
 103                return ret;
 104
 105        pri_entry = &pri_cfg->entry[0];
 106        for (i = 0; i < pri_cfg->num_entries; i++) {
 107                if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
 108                        num_valid++;
 109                pri_entry++;
 110        }
 111
 112        if (num_valid == 0) {
 113                /* No valid FCP priority data entries */
 114                ql_dbg(ql_dbg_user, vha, 0x7053,
 115                    "No valid FCP Priority data entries.\n");
 116                ret = 0;
 117        } else {
 118                /* FCP priority data is valid */
 119                ql_dbg(ql_dbg_user, vha, 0x7054,
 120                    "Valid FCP priority data. num entries = %d.\n",
 121                    num_valid);
 122        }
 123
 124        return ret;
 125}
 126
 127static int
 128qla24xx_proc_fcp_prio_cfg_cmd(struct bsg_job *bsg_job)
 129{
 130        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
 131        struct fc_bsg_request *bsg_request = bsg_job->request;
 132        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 133        scsi_qla_host_t *vha = shost_priv(host);
 134        struct qla_hw_data *ha = vha->hw;
 135        int ret = 0;
 136        uint32_t len;
 137        uint32_t oper;
 138
 139        if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_P3P_TYPE(ha))) {
 140                ret = -EINVAL;
 141                goto exit_fcp_prio_cfg;
 142        }
 143
 144        /* Get the sub command */
 145        oper = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
 146
 147        /* Only set config is allowed if config memory is not allocated */
 148        if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
 149                ret = -EINVAL;
 150                goto exit_fcp_prio_cfg;
 151        }
 152        switch (oper) {
 153        case QLFC_FCP_PRIO_DISABLE:
 154                if (ha->flags.fcp_prio_enabled) {
 155                        ha->flags.fcp_prio_enabled = 0;
 156                        ha->fcp_prio_cfg->attributes &=
 157                                ~FCP_PRIO_ATTR_ENABLE;
 158                        qla24xx_update_all_fcp_prio(vha);
 159                        bsg_reply->result = DID_OK;
 160                } else {
 161                        ret = -EINVAL;
 162                        bsg_reply->result = (DID_ERROR << 16);
 163                        goto exit_fcp_prio_cfg;
 164                }
 165                break;
 166
 167        case QLFC_FCP_PRIO_ENABLE:
 168                if (!ha->flags.fcp_prio_enabled) {
 169                        if (ha->fcp_prio_cfg) {
 170                                ha->flags.fcp_prio_enabled = 1;
 171                                ha->fcp_prio_cfg->attributes |=
 172                                    FCP_PRIO_ATTR_ENABLE;
 173                                qla24xx_update_all_fcp_prio(vha);
 174                                bsg_reply->result = DID_OK;
 175                        } else {
 176                                ret = -EINVAL;
 177                                bsg_reply->result = (DID_ERROR << 16);
 178                                goto exit_fcp_prio_cfg;
 179                        }
 180                }
 181                break;
 182
 183        case QLFC_FCP_PRIO_GET_CONFIG:
 184                len = bsg_job->reply_payload.payload_len;
 185                if (!len || len > FCP_PRIO_CFG_SIZE) {
 186                        ret = -EINVAL;
 187                        bsg_reply->result = (DID_ERROR << 16);
 188                        goto exit_fcp_prio_cfg;
 189                }
 190
 191                bsg_reply->result = DID_OK;
 192                bsg_reply->reply_payload_rcv_len =
 193                        sg_copy_from_buffer(
 194                        bsg_job->reply_payload.sg_list,
 195                        bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
 196                        len);
 197
 198                break;
 199
 200        case QLFC_FCP_PRIO_SET_CONFIG:
 201                len = bsg_job->request_payload.payload_len;
 202                if (!len || len > FCP_PRIO_CFG_SIZE) {
 203                        bsg_reply->result = (DID_ERROR << 16);
 204                        ret = -EINVAL;
 205                        goto exit_fcp_prio_cfg;
 206                }
 207
 208                if (!ha->fcp_prio_cfg) {
 209                        ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
 210                        if (!ha->fcp_prio_cfg) {
 211                                ql_log(ql_log_warn, vha, 0x7050,
 212                                    "Unable to allocate memory for fcp prio "
 213                                    "config data (%x).\n", FCP_PRIO_CFG_SIZE);
 214                                bsg_reply->result = (DID_ERROR << 16);
 215                                ret = -ENOMEM;
 216                                goto exit_fcp_prio_cfg;
 217                        }
 218                }
 219
 220                memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
 221                sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 222                bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
 223                        FCP_PRIO_CFG_SIZE);
 224
 225                /* validate fcp priority data */
 226
 227                if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1)) {
 228                        bsg_reply->result = (DID_ERROR << 16);
 229                        ret = -EINVAL;
 230                        /* If buffer was invalidatic int
 231                         * fcp_prio_cfg is of no use
 232                         */
 233                        vfree(ha->fcp_prio_cfg);
 234                        ha->fcp_prio_cfg = NULL;
 235                        goto exit_fcp_prio_cfg;
 236                }
 237
 238                ha->flags.fcp_prio_enabled = 0;
 239                if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
 240                        ha->flags.fcp_prio_enabled = 1;
 241                qla24xx_update_all_fcp_prio(vha);
 242                bsg_reply->result = DID_OK;
 243                break;
 244        default:
 245                ret = -EINVAL;
 246                break;
 247        }
 248exit_fcp_prio_cfg:
 249        if (!ret)
 250                bsg_job_done(bsg_job, bsg_reply->result,
 251                               bsg_reply->reply_payload_rcv_len);
 252        return ret;
 253}
 254
 255static int
 256qla2x00_process_els(struct bsg_job *bsg_job)
 257{
 258        struct fc_bsg_request *bsg_request = bsg_job->request;
 259        struct fc_rport *rport;
 260        fc_port_t *fcport = NULL;
 261        struct Scsi_Host *host;
 262        scsi_qla_host_t *vha;
 263        struct qla_hw_data *ha;
 264        srb_t *sp;
 265        const char *type;
 266        int req_sg_cnt, rsp_sg_cnt;
 267        int rval =  (DID_ERROR << 16);
 268        uint16_t nextlid = 0;
 269
 270        if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
 271                rport = fc_bsg_to_rport(bsg_job);
 272                fcport = *(fc_port_t **) rport->dd_data;
 273                host = rport_to_shost(rport);
 274                vha = shost_priv(host);
 275                ha = vha->hw;
 276                type = "FC_BSG_RPT_ELS";
 277        } else {
 278                host = fc_bsg_to_shost(bsg_job);
 279                vha = shost_priv(host);
 280                ha = vha->hw;
 281                type = "FC_BSG_HST_ELS_NOLOGIN";
 282        }
 283
 284        if (!vha->flags.online) {
 285                ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
 286                rval = -EIO;
 287                goto done;
 288        }
 289
 290        /* pass through is supported only for ISP 4Gb or higher */
 291        if (!IS_FWI2_CAPABLE(ha)) {
 292                ql_dbg(ql_dbg_user, vha, 0x7001,
 293                    "ELS passthru not supported for ISP23xx based adapters.\n");
 294                rval = -EPERM;
 295                goto done;
 296        }
 297
 298        /*  Multiple SG's are not supported for ELS requests */
 299        if (bsg_job->request_payload.sg_cnt > 1 ||
 300                bsg_job->reply_payload.sg_cnt > 1) {
 301                ql_dbg(ql_dbg_user, vha, 0x7002,
 302                    "Multiple SG's are not supported for ELS requests, "
 303                    "request_sg_cnt=%x reply_sg_cnt=%x.\n",
 304                    bsg_job->request_payload.sg_cnt,
 305                    bsg_job->reply_payload.sg_cnt);
 306                rval = -EPERM;
 307                goto done;
 308        }
 309
 310        /* ELS request for rport */
 311        if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
 312                /* make sure the rport is logged in,
 313                 * if not perform fabric login
 314                 */
 315                if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
 316                        ql_dbg(ql_dbg_user, vha, 0x7003,
 317                            "Failed to login port %06X for ELS passthru.\n",
 318                            fcport->d_id.b24);
 319                        rval = -EIO;
 320                        goto done;
 321                }
 322        } else {
 323                /* Allocate a dummy fcport structure, since functions
 324                 * preparing the IOCB and mailbox command retrieves port
 325                 * specific information from fcport structure. For Host based
 326                 * ELS commands there will be no fcport structure allocated
 327                 */
 328                fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 329                if (!fcport) {
 330                        rval = -ENOMEM;
 331                        goto done;
 332                }
 333
 334                /* Initialize all required  fields of fcport */
 335                fcport->vha = vha;
 336                fcport->d_id.b.al_pa =
 337                        bsg_request->rqst_data.h_els.port_id[0];
 338                fcport->d_id.b.area =
 339                        bsg_request->rqst_data.h_els.port_id[1];
 340                fcport->d_id.b.domain =
 341                        bsg_request->rqst_data.h_els.port_id[2];
 342                fcport->loop_id =
 343                        (fcport->d_id.b.al_pa == 0xFD) ?
 344                        NPH_FABRIC_CONTROLLER : NPH_F_PORT;
 345        }
 346
 347        req_sg_cnt =
 348                dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 349                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 350        if (!req_sg_cnt) {
 351                dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 352                    bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 353                rval = -ENOMEM;
 354                goto done_free_fcport;
 355        }
 356
 357        rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 358                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 359        if (!rsp_sg_cnt) {
 360                dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 361                    bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 362                rval = -ENOMEM;
 363                goto done_free_fcport;
 364        }
 365
 366        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
 367                (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
 368                ql_log(ql_log_warn, vha, 0x7008,
 369                    "dma mapping resulted in different sg counts, "
 370                    "request_sg_cnt: %x dma_request_sg_cnt:%x reply_sg_cnt:%x "
 371                    "dma_reply_sg_cnt:%x.\n", bsg_job->request_payload.sg_cnt,
 372                    req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
 373                rval = -EAGAIN;
 374                goto done_unmap_sg;
 375        }
 376
 377        /* Alloc SRB structure */
 378        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 379        if (!sp) {
 380                rval = -ENOMEM;
 381                goto done_unmap_sg;
 382        }
 383
 384        sp->type =
 385                (bsg_request->msgcode == FC_BSG_RPT_ELS ?
 386                 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
 387        sp->name =
 388                (bsg_request->msgcode == FC_BSG_RPT_ELS ?
 389                 "bsg_els_rpt" : "bsg_els_hst");
 390        sp->u.bsg_job = bsg_job;
 391        sp->free = qla2x00_bsg_sp_free;
 392        sp->done = qla2x00_bsg_job_done;
 393
 394        ql_dbg(ql_dbg_user, vha, 0x700a,
 395            "bsg rqst type: %s els type: %x - loop-id=%x "
 396            "portid=%-2x%02x%02x.\n", type,
 397            bsg_request->rqst_data.h_els.command_code, fcport->loop_id,
 398            fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
 399
 400        rval = qla2x00_start_sp(sp);
 401        if (rval != QLA_SUCCESS) {
 402                ql_log(ql_log_warn, vha, 0x700e,
 403                    "qla2x00_start_sp failed = %d\n", rval);
 404                qla2x00_rel_sp(sp);
 405                rval = -EIO;
 406                goto done_unmap_sg;
 407        }
 408        return rval;
 409
 410done_unmap_sg:
 411        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 412                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 413        dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 414                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 415        goto done_free_fcport;
 416
 417done_free_fcport:
 418        if (bsg_request->msgcode == FC_BSG_RPT_ELS)
 419                qla2x00_free_fcport(fcport);
 420done:
 421        return rval;
 422}
 423
 424static inline uint16_t
 425qla24xx_calc_ct_iocbs(uint16_t dsds)
 426{
 427        uint16_t iocbs;
 428
 429        iocbs = 1;
 430        if (dsds > 2) {
 431                iocbs += (dsds - 2) / 5;
 432                if ((dsds - 2) % 5)
 433                        iocbs++;
 434        }
 435        return iocbs;
 436}
 437
 438static int
 439qla2x00_process_ct(struct bsg_job *bsg_job)
 440{
 441        srb_t *sp;
 442        struct fc_bsg_request *bsg_request = bsg_job->request;
 443        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
 444        scsi_qla_host_t *vha = shost_priv(host);
 445        struct qla_hw_data *ha = vha->hw;
 446        int rval = (DID_ERROR << 16);
 447        int req_sg_cnt, rsp_sg_cnt;
 448        uint16_t loop_id;
 449        struct fc_port *fcport;
 450        char  *type = "FC_BSG_HST_CT";
 451
 452        req_sg_cnt =
 453                dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 454                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 455        if (!req_sg_cnt) {
 456                ql_log(ql_log_warn, vha, 0x700f,
 457                    "dma_map_sg return %d for request\n", req_sg_cnt);
 458                rval = -ENOMEM;
 459                goto done;
 460        }
 461
 462        rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 463                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 464        if (!rsp_sg_cnt) {
 465                ql_log(ql_log_warn, vha, 0x7010,
 466                    "dma_map_sg return %d for reply\n", rsp_sg_cnt);
 467                rval = -ENOMEM;
 468                goto done;
 469        }
 470
 471        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
 472            (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
 473                ql_log(ql_log_warn, vha, 0x7011,
 474                    "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
 475                    "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
 476                    req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
 477                rval = -EAGAIN;
 478                goto done_unmap_sg;
 479        }
 480
 481        if (!vha->flags.online) {
 482                ql_log(ql_log_warn, vha, 0x7012,
 483                    "Host is not online.\n");
 484                rval = -EIO;
 485                goto done_unmap_sg;
 486        }
 487
 488        loop_id =
 489                (bsg_request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
 490                        >> 24;
 491        switch (loop_id) {
 492        case 0xFC:
 493                loop_id = NPH_SNS;
 494                break;
 495        case 0xFA:
 496                loop_id = vha->mgmt_svr_loop_id;
 497                break;
 498        default:
 499                ql_dbg(ql_dbg_user, vha, 0x7013,
 500                    "Unknown loop id: %x.\n", loop_id);
 501                rval = -EINVAL;
 502                goto done_unmap_sg;
 503        }
 504
 505        /* Allocate a dummy fcport structure, since functions preparing the
 506         * IOCB and mailbox command retrieves port specific information
 507         * from fcport structure. For Host based ELS commands there will be
 508         * no fcport structure allocated
 509         */
 510        fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 511        if (!fcport) {
 512                ql_log(ql_log_warn, vha, 0x7014,
 513                    "Failed to allocate fcport.\n");
 514                rval = -ENOMEM;
 515                goto done_unmap_sg;
 516        }
 517
 518        /* Initialize all required  fields of fcport */
 519        fcport->vha = vha;
 520        fcport->d_id.b.al_pa = bsg_request->rqst_data.h_ct.port_id[0];
 521        fcport->d_id.b.area = bsg_request->rqst_data.h_ct.port_id[1];
 522        fcport->d_id.b.domain = bsg_request->rqst_data.h_ct.port_id[2];
 523        fcport->loop_id = loop_id;
 524
 525        /* Alloc SRB structure */
 526        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 527        if (!sp) {
 528                ql_log(ql_log_warn, vha, 0x7015,
 529                    "qla2x00_get_sp failed.\n");
 530                rval = -ENOMEM;
 531                goto done_free_fcport;
 532        }
 533
 534        sp->type = SRB_CT_CMD;
 535        sp->name = "bsg_ct";
 536        sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
 537        sp->u.bsg_job = bsg_job;
 538        sp->free = qla2x00_bsg_sp_free;
 539        sp->done = qla2x00_bsg_job_done;
 540
 541        ql_dbg(ql_dbg_user, vha, 0x7016,
 542            "bsg rqst type: %s else type: %x - "
 543            "loop-id=%x portid=%02x%02x%02x.\n", type,
 544            (bsg_request->rqst_data.h_ct.preamble_word2 >> 16),
 545            fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
 546            fcport->d_id.b.al_pa);
 547
 548        rval = qla2x00_start_sp(sp);
 549        if (rval != QLA_SUCCESS) {
 550                ql_log(ql_log_warn, vha, 0x7017,
 551                    "qla2x00_start_sp failed=%d.\n", rval);
 552                qla2x00_rel_sp(sp);
 553                rval = -EIO;
 554                goto done_free_fcport;
 555        }
 556        return rval;
 557
 558done_free_fcport:
 559        qla2x00_free_fcport(fcport);
 560done_unmap_sg:
 561        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
 562                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 563        dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
 564                bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 565done:
 566        return rval;
 567}
 568
 569/* Disable loopback mode */
 570static inline int
 571qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
 572                            int wait, int wait2)
 573{
 574        int ret = 0;
 575        int rval = 0;
 576        uint16_t new_config[4];
 577        struct qla_hw_data *ha = vha->hw;
 578
 579        if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha))
 580                goto done_reset_internal;
 581
 582        memset(new_config, 0 , sizeof(new_config));
 583        if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
 584            ENABLE_INTERNAL_LOOPBACK ||
 585            (config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
 586            ENABLE_EXTERNAL_LOOPBACK) {
 587                new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
 588                ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
 589                    (new_config[0] & INTERNAL_LOOPBACK_MASK));
 590                memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
 591
 592                ha->notify_dcbx_comp = wait;
 593                ha->notify_lb_portup_comp = wait2;
 594
 595                ret = qla81xx_set_port_config(vha, new_config);
 596                if (ret != QLA_SUCCESS) {
 597                        ql_log(ql_log_warn, vha, 0x7025,
 598                            "Set port config failed.\n");
 599                        ha->notify_dcbx_comp = 0;
 600                        ha->notify_lb_portup_comp = 0;
 601                        rval = -EINVAL;
 602                        goto done_reset_internal;
 603                }
 604
 605                /* Wait for DCBX complete event */
 606                if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
 607                        (DCBX_COMP_TIMEOUT * HZ))) {
 608                        ql_dbg(ql_dbg_user, vha, 0x7026,
 609                            "DCBX completion not received.\n");
 610                        ha->notify_dcbx_comp = 0;
 611                        ha->notify_lb_portup_comp = 0;
 612                        rval = -EINVAL;
 613                        goto done_reset_internal;
 614                } else
 615                        ql_dbg(ql_dbg_user, vha, 0x7027,
 616                            "DCBX completion received.\n");
 617
 618                if (wait2 &&
 619                    !wait_for_completion_timeout(&ha->lb_portup_comp,
 620                    (LB_PORTUP_COMP_TIMEOUT * HZ))) {
 621                        ql_dbg(ql_dbg_user, vha, 0x70c5,
 622                            "Port up completion not received.\n");
 623                        ha->notify_lb_portup_comp = 0;
 624                        rval = -EINVAL;
 625                        goto done_reset_internal;
 626                } else
 627                        ql_dbg(ql_dbg_user, vha, 0x70c6,
 628                            "Port up completion received.\n");
 629
 630                ha->notify_dcbx_comp = 0;
 631                ha->notify_lb_portup_comp = 0;
 632        }
 633done_reset_internal:
 634        return rval;
 635}
 636
 637/*
 638 * Set the port configuration to enable the internal or external loopback
 639 * depending on the loopback mode.
 640 */
 641static inline int
 642qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
 643        uint16_t *new_config, uint16_t mode)
 644{
 645        int ret = 0;
 646        int rval = 0;
 647        unsigned long rem_tmo = 0, current_tmo = 0;
 648        struct qla_hw_data *ha = vha->hw;
 649
 650        if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha))
 651                goto done_set_internal;
 652
 653        if (mode == INTERNAL_LOOPBACK)
 654                new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
 655        else if (mode == EXTERNAL_LOOPBACK)
 656                new_config[0] = config[0] | (ENABLE_EXTERNAL_LOOPBACK << 1);
 657        ql_dbg(ql_dbg_user, vha, 0x70be,
 658             "new_config[0]=%02x\n", (new_config[0] & INTERNAL_LOOPBACK_MASK));
 659
 660        memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3);
 661
 662        ha->notify_dcbx_comp = 1;
 663        ret = qla81xx_set_port_config(vha, new_config);
 664        if (ret != QLA_SUCCESS) {
 665                ql_log(ql_log_warn, vha, 0x7021,
 666                    "set port config failed.\n");
 667                ha->notify_dcbx_comp = 0;
 668                rval = -EINVAL;
 669                goto done_set_internal;
 670        }
 671
 672        /* Wait for DCBX complete event */
 673        current_tmo = DCBX_COMP_TIMEOUT * HZ;
 674        while (1) {
 675                rem_tmo = wait_for_completion_timeout(&ha->dcbx_comp,
 676                    current_tmo);
 677                if (!ha->idc_extend_tmo || rem_tmo) {
 678                        ha->idc_extend_tmo = 0;
 679                        break;
 680                }
 681                current_tmo = ha->idc_extend_tmo * HZ;
 682                ha->idc_extend_tmo = 0;
 683        }
 684
 685        if (!rem_tmo) {
 686                ql_dbg(ql_dbg_user, vha, 0x7022,
 687                    "DCBX completion not received.\n");
 688                ret = qla81xx_reset_loopback_mode(vha, new_config, 0, 0);
 689                /*
 690                 * If the reset of the loopback mode doesn't work take a FCoE
 691                 * dump and reset the chip.
 692                 */
 693                if (ret) {
 694                        qla2xxx_dump_fw(vha);
 695                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 696                }
 697                rval = -EINVAL;
 698        } else {
 699                if (ha->flags.idc_compl_status) {
 700                        ql_dbg(ql_dbg_user, vha, 0x70c3,
 701                            "Bad status in IDC Completion AEN\n");
 702                        rval = -EINVAL;
 703                        ha->flags.idc_compl_status = 0;
 704                } else
 705                        ql_dbg(ql_dbg_user, vha, 0x7023,
 706                            "DCBX completion received.\n");
 707        }
 708
 709        ha->notify_dcbx_comp = 0;
 710        ha->idc_extend_tmo = 0;
 711
 712done_set_internal:
 713        return rval;
 714}
 715
 716static int
 717qla2x00_process_loopback(struct bsg_job *bsg_job)
 718{
 719        struct fc_bsg_request *bsg_request = bsg_job->request;
 720        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 721        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
 722        scsi_qla_host_t *vha = shost_priv(host);
 723        struct qla_hw_data *ha = vha->hw;
 724        int rval;
 725        uint8_t command_sent;
 726        char *type;
 727        struct msg_echo_lb elreq;
 728        uint16_t response[MAILBOX_REGISTER_COUNT];
 729        uint16_t config[4], new_config[4];
 730        uint8_t *fw_sts_ptr;
 731        void *req_data = NULL;
 732        dma_addr_t req_data_dma;
 733        uint32_t req_data_len;
 734        uint8_t *rsp_data = NULL;
 735        dma_addr_t rsp_data_dma;
 736        uint32_t rsp_data_len;
 737
 738        if (!vha->flags.online) {
 739                ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
 740                return -EIO;
 741        }
 742
 743        memset(&elreq, 0, sizeof(elreq));
 744
 745        elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
 746                bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
 747                DMA_TO_DEVICE);
 748
 749        if (!elreq.req_sg_cnt) {
 750                ql_log(ql_log_warn, vha, 0x701a,
 751                    "dma_map_sg returned %d for request.\n", elreq.req_sg_cnt);
 752                return -ENOMEM;
 753        }
 754
 755        elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
 756                bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
 757                DMA_FROM_DEVICE);
 758
 759        if (!elreq.rsp_sg_cnt) {
 760                ql_log(ql_log_warn, vha, 0x701b,
 761                    "dma_map_sg returned %d for reply.\n", elreq.rsp_sg_cnt);
 762                rval = -ENOMEM;
 763                goto done_unmap_req_sg;
 764        }
 765
 766        if ((elreq.req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
 767                (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
 768                ql_log(ql_log_warn, vha, 0x701c,
 769                    "dma mapping resulted in different sg counts, "
 770                    "request_sg_cnt: %x dma_request_sg_cnt: %x "
 771                    "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
 772                    bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
 773                    bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt);
 774                rval = -EAGAIN;
 775                goto done_unmap_sg;
 776        }
 777        req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
 778        req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
 779                &req_data_dma, GFP_KERNEL);
 780        if (!req_data) {
 781                ql_log(ql_log_warn, vha, 0x701d,
 782                    "dma alloc failed for req_data.\n");
 783                rval = -ENOMEM;
 784                goto done_unmap_sg;
 785        }
 786
 787        rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
 788                &rsp_data_dma, GFP_KERNEL);
 789        if (!rsp_data) {
 790                ql_log(ql_log_warn, vha, 0x7004,
 791                    "dma alloc failed for rsp_data.\n");
 792                rval = -ENOMEM;
 793                goto done_free_dma_req;
 794        }
 795
 796        /* Copy the request buffer in req_data now */
 797        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 798                bsg_job->request_payload.sg_cnt, req_data, req_data_len);
 799
 800        elreq.send_dma = req_data_dma;
 801        elreq.rcv_dma = rsp_data_dma;
 802        elreq.transfer_size = req_data_len;
 803
 804        elreq.options = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
 805        elreq.iteration_count =
 806            bsg_request->rqst_data.h_vendor.vendor_cmd[2];
 807
 808        if (atomic_read(&vha->loop_state) == LOOP_READY &&
 809            ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) ||
 810            ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
 811            get_unaligned_le32(req_data) == ELS_OPCODE_BYTE &&
 812            req_data_len == MAX_ELS_FRAME_PAYLOAD &&
 813            elreq.options == EXTERNAL_LOOPBACK))) {
 814                type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
 815                ql_dbg(ql_dbg_user, vha, 0x701e,
 816                    "BSG request type: %s.\n", type);
 817                command_sent = INT_DEF_LB_ECHO_CMD;
 818                rval = qla2x00_echo_test(vha, &elreq, response);
 819        } else {
 820                if (IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) {
 821                        memset(config, 0, sizeof(config));
 822                        memset(new_config, 0, sizeof(new_config));
 823
 824                        if (qla81xx_get_port_config(vha, config)) {
 825                                ql_log(ql_log_warn, vha, 0x701f,
 826                                    "Get port config failed.\n");
 827                                rval = -EPERM;
 828                                goto done_free_dma_rsp;
 829                        }
 830
 831                        if ((config[0] & INTERNAL_LOOPBACK_MASK) != 0) {
 832                                ql_dbg(ql_dbg_user, vha, 0x70c4,
 833                                    "Loopback operation already in "
 834                                    "progress.\n");
 835                                rval = -EAGAIN;
 836                                goto done_free_dma_rsp;
 837                        }
 838
 839                        ql_dbg(ql_dbg_user, vha, 0x70c0,
 840                            "elreq.options=%04x\n", elreq.options);
 841
 842                        if (elreq.options == EXTERNAL_LOOPBACK)
 843                                if (IS_QLA8031(ha) || IS_QLA8044(ha))
 844                                        rval = qla81xx_set_loopback_mode(vha,
 845                                            config, new_config, elreq.options);
 846                                else
 847                                        rval = qla81xx_reset_loopback_mode(vha,
 848                                            config, 1, 0);
 849                        else
 850                                rval = qla81xx_set_loopback_mode(vha, config,
 851                                    new_config, elreq.options);
 852
 853                        if (rval) {
 854                                rval = -EPERM;
 855                                goto done_free_dma_rsp;
 856                        }
 857
 858                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
 859                        ql_dbg(ql_dbg_user, vha, 0x7028,
 860                            "BSG request type: %s.\n", type);
 861
 862                        command_sent = INT_DEF_LB_LOOPBACK_CMD;
 863                        rval = qla2x00_loopback_test(vha, &elreq, response);
 864
 865                        if (response[0] == MBS_COMMAND_ERROR &&
 866                                        response[1] == MBS_LB_RESET) {
 867                                ql_log(ql_log_warn, vha, 0x7029,
 868                                    "MBX command error, Aborting ISP.\n");
 869                                set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 870                                qla2xxx_wake_dpc(vha);
 871                                qla2x00_wait_for_chip_reset(vha);
 872                                /* Also reset the MPI */
 873                                if (IS_QLA81XX(ha)) {
 874                                        if (qla81xx_restart_mpi_firmware(vha) !=
 875                                            QLA_SUCCESS) {
 876                                                ql_log(ql_log_warn, vha, 0x702a,
 877                                                    "MPI reset failed.\n");
 878                                        }
 879                                }
 880
 881                                rval = -EIO;
 882                                goto done_free_dma_rsp;
 883                        }
 884
 885                        if (new_config[0]) {
 886                                int ret;
 887
 888                                /* Revert back to original port config
 889                                 * Also clear internal loopback
 890                                 */
 891                                ret = qla81xx_reset_loopback_mode(vha,
 892                                    new_config, 0, 1);
 893                                if (ret) {
 894                                        /*
 895                                         * If the reset of the loopback mode
 896                                         * doesn't work take FCoE dump and then
 897                                         * reset the chip.
 898                                         */
 899                                        qla2xxx_dump_fw(vha);
 900                                        set_bit(ISP_ABORT_NEEDED,
 901                                            &vha->dpc_flags);
 902                                }
 903
 904                        }
 905
 906                } else {
 907                        type = "FC_BSG_HST_VENDOR_LOOPBACK";
 908                        ql_dbg(ql_dbg_user, vha, 0x702b,
 909                            "BSG request type: %s.\n", type);
 910                        command_sent = INT_DEF_LB_LOOPBACK_CMD;
 911                        rval = qla2x00_loopback_test(vha, &elreq, response);
 912                }
 913        }
 914
 915        if (rval) {
 916                ql_log(ql_log_warn, vha, 0x702c,
 917                    "Vendor request %s failed.\n", type);
 918
 919                rval = 0;
 920                bsg_reply->result = (DID_ERROR << 16);
 921                bsg_reply->reply_payload_rcv_len = 0;
 922        } else {
 923                ql_dbg(ql_dbg_user, vha, 0x702d,
 924                    "Vendor request %s completed.\n", type);
 925                bsg_reply->result = (DID_OK << 16);
 926                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
 927                        bsg_job->reply_payload.sg_cnt, rsp_data,
 928                        rsp_data_len);
 929        }
 930
 931        bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
 932            sizeof(response) + sizeof(uint8_t);
 933        fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply);
 934        memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), response,
 935                        sizeof(response));
 936        fw_sts_ptr += sizeof(response);
 937        *fw_sts_ptr = command_sent;
 938
 939done_free_dma_rsp:
 940        dma_free_coherent(&ha->pdev->dev, rsp_data_len,
 941                rsp_data, rsp_data_dma);
 942done_free_dma_req:
 943        dma_free_coherent(&ha->pdev->dev, req_data_len,
 944                req_data, req_data_dma);
 945done_unmap_sg:
 946        dma_unmap_sg(&ha->pdev->dev,
 947            bsg_job->reply_payload.sg_list,
 948            bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 949done_unmap_req_sg:
 950        dma_unmap_sg(&ha->pdev->dev,
 951            bsg_job->request_payload.sg_list,
 952            bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
 953        if (!rval)
 954                bsg_job_done(bsg_job, bsg_reply->result,
 955                               bsg_reply->reply_payload_rcv_len);
 956        return rval;
 957}
 958
 959static int
 960qla84xx_reset(struct bsg_job *bsg_job)
 961{
 962        struct fc_bsg_request *bsg_request = bsg_job->request;
 963        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
 964        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 965        scsi_qla_host_t *vha = shost_priv(host);
 966        struct qla_hw_data *ha = vha->hw;
 967        int rval = 0;
 968        uint32_t flag;
 969
 970        if (!IS_QLA84XX(ha)) {
 971                ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
 972                return -EINVAL;
 973        }
 974
 975        flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
 976
 977        rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
 978
 979        if (rval) {
 980                ql_log(ql_log_warn, vha, 0x7030,
 981                    "Vendor request 84xx reset failed.\n");
 982                rval = (DID_ERROR << 16);
 983
 984        } else {
 985                ql_dbg(ql_dbg_user, vha, 0x7031,
 986                    "Vendor request 84xx reset completed.\n");
 987                bsg_reply->result = DID_OK;
 988                bsg_job_done(bsg_job, bsg_reply->result,
 989                               bsg_reply->reply_payload_rcv_len);
 990        }
 991
 992        return rval;
 993}
 994
 995static int
 996qla84xx_updatefw(struct bsg_job *bsg_job)
 997{
 998        struct fc_bsg_request *bsg_request = bsg_job->request;
 999        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1000        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1001        scsi_qla_host_t *vha = shost_priv(host);
1002        struct qla_hw_data *ha = vha->hw;
1003        struct verify_chip_entry_84xx *mn = NULL;
1004        dma_addr_t mn_dma, fw_dma;
1005        void *fw_buf = NULL;
1006        int rval = 0;
1007        uint32_t sg_cnt;
1008        uint32_t data_len;
1009        uint16_t options;
1010        uint32_t flag;
1011        uint32_t fw_ver;
1012
1013        if (!IS_QLA84XX(ha)) {
1014                ql_dbg(ql_dbg_user, vha, 0x7032,
1015                    "Not 84xx, exiting.\n");
1016                return -EINVAL;
1017        }
1018
1019        sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1020                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1021        if (!sg_cnt) {
1022                ql_log(ql_log_warn, vha, 0x7033,
1023                    "dma_map_sg returned %d for request.\n", sg_cnt);
1024                return -ENOMEM;
1025        }
1026
1027        if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1028                ql_log(ql_log_warn, vha, 0x7034,
1029                    "DMA mapping resulted in different sg counts, "
1030                    "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1031                    bsg_job->request_payload.sg_cnt, sg_cnt);
1032                rval = -EAGAIN;
1033                goto done_unmap_sg;
1034        }
1035
1036        data_len = bsg_job->request_payload.payload_len;
1037        fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
1038                &fw_dma, GFP_KERNEL);
1039        if (!fw_buf) {
1040                ql_log(ql_log_warn, vha, 0x7035,
1041                    "DMA alloc failed for fw_buf.\n");
1042                rval = -ENOMEM;
1043                goto done_unmap_sg;
1044        }
1045
1046        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1047                bsg_job->request_payload.sg_cnt, fw_buf, data_len);
1048
1049        mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1050        if (!mn) {
1051                ql_log(ql_log_warn, vha, 0x7036,
1052                    "DMA alloc failed for fw buffer.\n");
1053                rval = -ENOMEM;
1054                goto done_free_fw_buf;
1055        }
1056
1057        flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1058        fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2);
1059
1060        mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
1061        mn->entry_count = 1;
1062
1063        options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
1064        if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD)
1065                options |= VCO_DIAG_FW;
1066
1067        mn->options = cpu_to_le16(options);
1068        mn->fw_ver =  cpu_to_le32(fw_ver);
1069        mn->fw_size =  cpu_to_le32(data_len);
1070        mn->fw_seq_size =  cpu_to_le32(data_len);
1071        put_unaligned_le64(fw_dma, &mn->dsd.address);
1072        mn->dsd.length = cpu_to_le32(data_len);
1073        mn->data_seg_cnt = cpu_to_le16(1);
1074
1075        rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
1076
1077        if (rval) {
1078                ql_log(ql_log_warn, vha, 0x7037,
1079                    "Vendor request 84xx updatefw failed.\n");
1080
1081                rval = (DID_ERROR << 16);
1082        } else {
1083                ql_dbg(ql_dbg_user, vha, 0x7038,
1084                    "Vendor request 84xx updatefw completed.\n");
1085
1086                bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1087                bsg_reply->result = DID_OK;
1088        }
1089
1090        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1091
1092done_free_fw_buf:
1093        dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma);
1094
1095done_unmap_sg:
1096        dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1097                bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1098
1099        if (!rval)
1100                bsg_job_done(bsg_job, bsg_reply->result,
1101                               bsg_reply->reply_payload_rcv_len);
1102        return rval;
1103}
1104
1105static int
1106qla84xx_mgmt_cmd(struct bsg_job *bsg_job)
1107{
1108        struct fc_bsg_request *bsg_request = bsg_job->request;
1109        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1110        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1111        scsi_qla_host_t *vha = shost_priv(host);
1112        struct qla_hw_data *ha = vha->hw;
1113        struct access_chip_84xx *mn = NULL;
1114        dma_addr_t mn_dma, mgmt_dma;
1115        void *mgmt_b = NULL;
1116        int rval = 0;
1117        struct qla_bsg_a84_mgmt *ql84_mgmt;
1118        uint32_t sg_cnt;
1119        uint32_t data_len = 0;
1120        uint32_t dma_direction = DMA_NONE;
1121
1122        if (!IS_QLA84XX(ha)) {
1123                ql_log(ql_log_warn, vha, 0x703a,
1124                    "Not 84xx, exiting.\n");
1125                return -EINVAL;
1126        }
1127
1128        mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1129        if (!mn) {
1130                ql_log(ql_log_warn, vha, 0x703c,
1131                    "DMA alloc failed for fw buffer.\n");
1132                return -ENOMEM;
1133        }
1134
1135        mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
1136        mn->entry_count = 1;
1137        ql84_mgmt = (void *)bsg_request + sizeof(struct fc_bsg_request);
1138        switch (ql84_mgmt->mgmt.cmd) {
1139        case QLA84_MGMT_READ_MEM:
1140        case QLA84_MGMT_GET_INFO:
1141                sg_cnt = dma_map_sg(&ha->pdev->dev,
1142                        bsg_job->reply_payload.sg_list,
1143                        bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1144                if (!sg_cnt) {
1145                        ql_log(ql_log_warn, vha, 0x703d,
1146                            "dma_map_sg returned %d for reply.\n", sg_cnt);
1147                        rval = -ENOMEM;
1148                        goto exit_mgmt;
1149                }
1150
1151                dma_direction = DMA_FROM_DEVICE;
1152
1153                if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
1154                        ql_log(ql_log_warn, vha, 0x703e,
1155                            "DMA mapping resulted in different sg counts, "
1156                            "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
1157                            bsg_job->reply_payload.sg_cnt, sg_cnt);
1158                        rval = -EAGAIN;
1159                        goto done_unmap_sg;
1160                }
1161
1162                data_len = bsg_job->reply_payload.payload_len;
1163
1164                mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1165                    &mgmt_dma, GFP_KERNEL);
1166                if (!mgmt_b) {
1167                        ql_log(ql_log_warn, vha, 0x703f,
1168                            "DMA alloc failed for mgmt_b.\n");
1169                        rval = -ENOMEM;
1170                        goto done_unmap_sg;
1171                }
1172
1173                if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) {
1174                        mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
1175                        mn->parameter1 =
1176                                cpu_to_le32(
1177                                ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1178
1179                } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) {
1180                        mn->options = cpu_to_le16(ACO_REQUEST_INFO);
1181                        mn->parameter1 =
1182                                cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type);
1183
1184                        mn->parameter2 =
1185                                cpu_to_le32(
1186                                ql84_mgmt->mgmt.mgmtp.u.info.context);
1187                }
1188                break;
1189
1190        case QLA84_MGMT_WRITE_MEM:
1191                sg_cnt = dma_map_sg(&ha->pdev->dev,
1192                        bsg_job->request_payload.sg_list,
1193                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1194
1195                if (!sg_cnt) {
1196                        ql_log(ql_log_warn, vha, 0x7040,
1197                            "dma_map_sg returned %d.\n", sg_cnt);
1198                        rval = -ENOMEM;
1199                        goto exit_mgmt;
1200                }
1201
1202                dma_direction = DMA_TO_DEVICE;
1203
1204                if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1205                        ql_log(ql_log_warn, vha, 0x7041,
1206                            "DMA mapping resulted in different sg counts, "
1207                            "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1208                            bsg_job->request_payload.sg_cnt, sg_cnt);
1209                        rval = -EAGAIN;
1210                        goto done_unmap_sg;
1211                }
1212
1213                data_len = bsg_job->request_payload.payload_len;
1214                mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1215                        &mgmt_dma, GFP_KERNEL);
1216                if (!mgmt_b) {
1217                        ql_log(ql_log_warn, vha, 0x7042,
1218                            "DMA alloc failed for mgmt_b.\n");
1219                        rval = -ENOMEM;
1220                        goto done_unmap_sg;
1221                }
1222
1223                sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1224                        bsg_job->request_payload.sg_cnt, mgmt_b, data_len);
1225
1226                mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
1227                mn->parameter1 =
1228                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1229                break;
1230
1231        case QLA84_MGMT_CHNG_CONFIG:
1232                mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
1233                mn->parameter1 =
1234                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id);
1235
1236                mn->parameter2 =
1237                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0);
1238
1239                mn->parameter3 =
1240                        cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1);
1241                break;
1242
1243        default:
1244                rval = -EIO;
1245                goto exit_mgmt;
1246        }
1247
1248        if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
1249                mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
1250                mn->dseg_count = cpu_to_le16(1);
1251                put_unaligned_le64(mgmt_dma, &mn->dsd.address);
1252                mn->dsd.length = cpu_to_le32(ql84_mgmt->mgmt.len);
1253        }
1254
1255        rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
1256
1257        if (rval) {
1258                ql_log(ql_log_warn, vha, 0x7043,
1259                    "Vendor request 84xx mgmt failed.\n");
1260
1261                rval = (DID_ERROR << 16);
1262
1263        } else {
1264                ql_dbg(ql_dbg_user, vha, 0x7044,
1265                    "Vendor request 84xx mgmt completed.\n");
1266
1267                bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1268                bsg_reply->result = DID_OK;
1269
1270                if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
1271                        (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
1272                        bsg_reply->reply_payload_rcv_len =
1273                                bsg_job->reply_payload.payload_len;
1274
1275                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1276                                bsg_job->reply_payload.sg_cnt, mgmt_b,
1277                                data_len);
1278                }
1279        }
1280
1281done_unmap_sg:
1282        if (mgmt_b)
1283                dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
1284
1285        if (dma_direction == DMA_TO_DEVICE)
1286                dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1287                        bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1288        else if (dma_direction == DMA_FROM_DEVICE)
1289                dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1290                        bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1291
1292exit_mgmt:
1293        dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1294
1295        if (!rval)
1296                bsg_job_done(bsg_job, bsg_reply->result,
1297                               bsg_reply->reply_payload_rcv_len);
1298        return rval;
1299}
1300
1301static int
1302qla24xx_iidma(struct bsg_job *bsg_job)
1303{
1304        struct fc_bsg_request *bsg_request = bsg_job->request;
1305        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1306        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1307        scsi_qla_host_t *vha = shost_priv(host);
1308        int rval = 0;
1309        struct qla_port_param *port_param = NULL;
1310        fc_port_t *fcport = NULL;
1311        int found = 0;
1312        uint16_t mb[MAILBOX_REGISTER_COUNT];
1313        uint8_t *rsp_ptr = NULL;
1314
1315        if (!IS_IIDMA_CAPABLE(vha->hw)) {
1316                ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
1317                return -EINVAL;
1318        }
1319
1320        port_param = (void *)bsg_request + sizeof(struct fc_bsg_request);
1321        if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
1322                ql_log(ql_log_warn, vha, 0x7048,
1323                    "Invalid destination type.\n");
1324                return -EINVAL;
1325        }
1326
1327        list_for_each_entry(fcport, &vha->vp_fcports, list) {
1328                if (fcport->port_type != FCT_TARGET)
1329                        continue;
1330
1331                if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn,
1332                        fcport->port_name, sizeof(fcport->port_name)))
1333                        continue;
1334
1335                found = 1;
1336                break;
1337        }
1338
1339        if (!found) {
1340                ql_log(ql_log_warn, vha, 0x7049,
1341                    "Failed to find port.\n");
1342                return -EINVAL;
1343        }
1344
1345        if (atomic_read(&fcport->state) != FCS_ONLINE) {
1346                ql_log(ql_log_warn, vha, 0x704a,
1347                    "Port is not online.\n");
1348                return -EINVAL;
1349        }
1350
1351        if (fcport->flags & FCF_LOGIN_NEEDED) {
1352                ql_log(ql_log_warn, vha, 0x704b,
1353                    "Remote port not logged in flags = 0x%x.\n", fcport->flags);
1354                return -EINVAL;
1355        }
1356
1357        if (port_param->mode)
1358                rval = qla2x00_set_idma_speed(vha, fcport->loop_id,
1359                        port_param->speed, mb);
1360        else
1361                rval = qla2x00_get_idma_speed(vha, fcport->loop_id,
1362                        &port_param->speed, mb);
1363
1364        if (rval) {
1365                ql_log(ql_log_warn, vha, 0x704c,
1366                    "iiDMA cmd failed for %8phN -- "
1367                    "%04x %x %04x %04x.\n", fcport->port_name,
1368                    rval, fcport->fp_speed, mb[0], mb[1]);
1369                rval = (DID_ERROR << 16);
1370        } else {
1371                if (!port_param->mode) {
1372                        bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
1373                                sizeof(struct qla_port_param);
1374
1375                        rsp_ptr = ((uint8_t *)bsg_reply) +
1376                                sizeof(struct fc_bsg_reply);
1377
1378                        memcpy(rsp_ptr, port_param,
1379                                sizeof(struct qla_port_param));
1380                }
1381
1382                bsg_reply->result = DID_OK;
1383                bsg_job_done(bsg_job, bsg_reply->result,
1384                               bsg_reply->reply_payload_rcv_len);
1385        }
1386
1387        return rval;
1388}
1389
1390static int
1391qla2x00_optrom_setup(struct bsg_job *bsg_job, scsi_qla_host_t *vha,
1392        uint8_t is_update)
1393{
1394        struct fc_bsg_request *bsg_request = bsg_job->request;
1395        uint32_t start = 0;
1396        int valid = 0;
1397        struct qla_hw_data *ha = vha->hw;
1398
1399        if (unlikely(pci_channel_offline(ha->pdev)))
1400                return -EINVAL;
1401
1402        start = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1403        if (start > ha->optrom_size) {
1404                ql_log(ql_log_warn, vha, 0x7055,
1405                    "start %d > optrom_size %d.\n", start, ha->optrom_size);
1406                return -EINVAL;
1407        }
1408
1409        if (ha->optrom_state != QLA_SWAITING) {
1410                ql_log(ql_log_info, vha, 0x7056,
1411                    "optrom_state %d.\n", ha->optrom_state);
1412                return -EBUSY;
1413        }
1414
1415        ha->optrom_region_start = start;
1416        ql_dbg(ql_dbg_user, vha, 0x7057, "is_update=%d.\n", is_update);
1417        if (is_update) {
1418                if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
1419                        valid = 1;
1420                else if (start == (ha->flt_region_boot * 4) ||
1421                    start == (ha->flt_region_fw * 4))
1422                        valid = 1;
1423                else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
1424                    IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
1425                    IS_QLA28XX(ha))
1426                        valid = 1;
1427                if (!valid) {
1428                        ql_log(ql_log_warn, vha, 0x7058,
1429                            "Invalid start region 0x%x/0x%x.\n", start,
1430                            bsg_job->request_payload.payload_len);
1431                        return -EINVAL;
1432                }
1433
1434                ha->optrom_region_size = start +
1435                    bsg_job->request_payload.payload_len > ha->optrom_size ?
1436                    ha->optrom_size - start :
1437                    bsg_job->request_payload.payload_len;
1438                ha->optrom_state = QLA_SWRITING;
1439        } else {
1440                ha->optrom_region_size = start +
1441                    bsg_job->reply_payload.payload_len > ha->optrom_size ?
1442                    ha->optrom_size - start :
1443                    bsg_job->reply_payload.payload_len;
1444                ha->optrom_state = QLA_SREADING;
1445        }
1446
1447        ha->optrom_buffer = vzalloc(ha->optrom_region_size);
1448        if (!ha->optrom_buffer) {
1449                ql_log(ql_log_warn, vha, 0x7059,
1450                    "Read: Unable to allocate memory for optrom retrieval "
1451                    "(%x)\n", ha->optrom_region_size);
1452
1453                ha->optrom_state = QLA_SWAITING;
1454                return -ENOMEM;
1455        }
1456
1457        return 0;
1458}
1459
1460static int
1461qla2x00_read_optrom(struct bsg_job *bsg_job)
1462{
1463        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1464        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1465        scsi_qla_host_t *vha = shost_priv(host);
1466        struct qla_hw_data *ha = vha->hw;
1467        int rval = 0;
1468
1469        if (ha->flags.nic_core_reset_hdlr_active)
1470                return -EBUSY;
1471
1472        mutex_lock(&ha->optrom_mutex);
1473        rval = qla2x00_optrom_setup(bsg_job, vha, 0);
1474        if (rval) {
1475                mutex_unlock(&ha->optrom_mutex);
1476                return rval;
1477        }
1478
1479        ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
1480            ha->optrom_region_start, ha->optrom_region_size);
1481
1482        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1483            bsg_job->reply_payload.sg_cnt, ha->optrom_buffer,
1484            ha->optrom_region_size);
1485
1486        bsg_reply->reply_payload_rcv_len = ha->optrom_region_size;
1487        bsg_reply->result = DID_OK;
1488        vfree(ha->optrom_buffer);
1489        ha->optrom_buffer = NULL;
1490        ha->optrom_state = QLA_SWAITING;
1491        mutex_unlock(&ha->optrom_mutex);
1492        bsg_job_done(bsg_job, bsg_reply->result,
1493                       bsg_reply->reply_payload_rcv_len);
1494        return rval;
1495}
1496
1497static int
1498qla2x00_update_optrom(struct bsg_job *bsg_job)
1499{
1500        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1501        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1502        scsi_qla_host_t *vha = shost_priv(host);
1503        struct qla_hw_data *ha = vha->hw;
1504        int rval = 0;
1505
1506        mutex_lock(&ha->optrom_mutex);
1507        rval = qla2x00_optrom_setup(bsg_job, vha, 1);
1508        if (rval) {
1509                mutex_unlock(&ha->optrom_mutex);
1510                return rval;
1511        }
1512
1513        /* Set the isp82xx_no_md_cap not to capture minidump */
1514        ha->flags.isp82xx_no_md_cap = 1;
1515
1516        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1517            bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
1518            ha->optrom_region_size);
1519
1520        rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
1521            ha->optrom_region_start, ha->optrom_region_size);
1522
1523        if (rval) {
1524                bsg_reply->result = -EINVAL;
1525                rval = -EINVAL;
1526        } else {
1527                bsg_reply->result = DID_OK;
1528        }
1529        vfree(ha->optrom_buffer);
1530        ha->optrom_buffer = NULL;
1531        ha->optrom_state = QLA_SWAITING;
1532        mutex_unlock(&ha->optrom_mutex);
1533        bsg_job_done(bsg_job, bsg_reply->result,
1534                       bsg_reply->reply_payload_rcv_len);
1535        return rval;
1536}
1537
1538static int
1539qla2x00_update_fru_versions(struct bsg_job *bsg_job)
1540{
1541        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1542        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1543        scsi_qla_host_t *vha = shost_priv(host);
1544        struct qla_hw_data *ha = vha->hw;
1545        int rval = 0;
1546        uint8_t bsg[DMA_POOL_SIZE];
1547        struct qla_image_version_list *list = (void *)bsg;
1548        struct qla_image_version *image;
1549        uint32_t count;
1550        dma_addr_t sfp_dma;
1551        void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1552
1553        if (!sfp) {
1554                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1555                    EXT_STATUS_NO_MEMORY;
1556                goto done;
1557        }
1558
1559        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1560            bsg_job->request_payload.sg_cnt, list, sizeof(bsg));
1561
1562        image = list->version;
1563        count = list->count;
1564        while (count--) {
1565                memcpy(sfp, &image->field_info, sizeof(image->field_info));
1566                rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1567                    image->field_address.device, image->field_address.offset,
1568                    sizeof(image->field_info), image->field_address.option);
1569                if (rval) {
1570                        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1571                            EXT_STATUS_MAILBOX;
1572                        goto dealloc;
1573                }
1574                image++;
1575        }
1576
1577        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1578
1579dealloc:
1580        dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1581
1582done:
1583        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1584        bsg_reply->result = DID_OK << 16;
1585        bsg_job_done(bsg_job, bsg_reply->result,
1586                       bsg_reply->reply_payload_rcv_len);
1587
1588        return 0;
1589}
1590
1591static int
1592qla2x00_read_fru_status(struct bsg_job *bsg_job)
1593{
1594        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1595        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1596        scsi_qla_host_t *vha = shost_priv(host);
1597        struct qla_hw_data *ha = vha->hw;
1598        int rval = 0;
1599        uint8_t bsg[DMA_POOL_SIZE];
1600        struct qla_status_reg *sr = (void *)bsg;
1601        dma_addr_t sfp_dma;
1602        uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1603
1604        if (!sfp) {
1605                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1606                    EXT_STATUS_NO_MEMORY;
1607                goto done;
1608        }
1609
1610        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1611            bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
1612
1613        rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1614            sr->field_address.device, sr->field_address.offset,
1615            sizeof(sr->status_reg), sr->field_address.option);
1616        sr->status_reg = *sfp;
1617
1618        if (rval) {
1619                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1620                    EXT_STATUS_MAILBOX;
1621                goto dealloc;
1622        }
1623
1624        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1625            bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr));
1626
1627        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1628
1629dealloc:
1630        dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1631
1632done:
1633        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1634        bsg_reply->reply_payload_rcv_len = sizeof(*sr);
1635        bsg_reply->result = DID_OK << 16;
1636        bsg_job_done(bsg_job, bsg_reply->result,
1637                       bsg_reply->reply_payload_rcv_len);
1638
1639        return 0;
1640}
1641
1642static int
1643qla2x00_write_fru_status(struct bsg_job *bsg_job)
1644{
1645        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1646        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1647        scsi_qla_host_t *vha = shost_priv(host);
1648        struct qla_hw_data *ha = vha->hw;
1649        int rval = 0;
1650        uint8_t bsg[DMA_POOL_SIZE];
1651        struct qla_status_reg *sr = (void *)bsg;
1652        dma_addr_t sfp_dma;
1653        uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1654
1655        if (!sfp) {
1656                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1657                    EXT_STATUS_NO_MEMORY;
1658                goto done;
1659        }
1660
1661        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1662            bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
1663
1664        *sfp = sr->status_reg;
1665        rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1666            sr->field_address.device, sr->field_address.offset,
1667            sizeof(sr->status_reg), sr->field_address.option);
1668
1669        if (rval) {
1670                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1671                    EXT_STATUS_MAILBOX;
1672                goto dealloc;
1673        }
1674
1675        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1676
1677dealloc:
1678        dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1679
1680done:
1681        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1682        bsg_reply->result = DID_OK << 16;
1683        bsg_job_done(bsg_job, bsg_reply->result,
1684                       bsg_reply->reply_payload_rcv_len);
1685
1686        return 0;
1687}
1688
1689static int
1690qla2x00_write_i2c(struct bsg_job *bsg_job)
1691{
1692        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1693        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1694        scsi_qla_host_t *vha = shost_priv(host);
1695        struct qla_hw_data *ha = vha->hw;
1696        int rval = 0;
1697        uint8_t bsg[DMA_POOL_SIZE];
1698        struct qla_i2c_access *i2c = (void *)bsg;
1699        dma_addr_t sfp_dma;
1700        uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1701
1702        if (!sfp) {
1703                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1704                    EXT_STATUS_NO_MEMORY;
1705                goto done;
1706        }
1707
1708        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1709            bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1710
1711        memcpy(sfp, i2c->buffer, i2c->length);
1712        rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1713            i2c->device, i2c->offset, i2c->length, i2c->option);
1714
1715        if (rval) {
1716                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1717                    EXT_STATUS_MAILBOX;
1718                goto dealloc;
1719        }
1720
1721        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1722
1723dealloc:
1724        dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1725
1726done:
1727        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1728        bsg_reply->result = DID_OK << 16;
1729        bsg_job_done(bsg_job, bsg_reply->result,
1730                       bsg_reply->reply_payload_rcv_len);
1731
1732        return 0;
1733}
1734
1735static int
1736qla2x00_read_i2c(struct bsg_job *bsg_job)
1737{
1738        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1739        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1740        scsi_qla_host_t *vha = shost_priv(host);
1741        struct qla_hw_data *ha = vha->hw;
1742        int rval = 0;
1743        uint8_t bsg[DMA_POOL_SIZE];
1744        struct qla_i2c_access *i2c = (void *)bsg;
1745        dma_addr_t sfp_dma;
1746        uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1747
1748        if (!sfp) {
1749                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1750                    EXT_STATUS_NO_MEMORY;
1751                goto done;
1752        }
1753
1754        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1755            bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1756
1757        rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1758                i2c->device, i2c->offset, i2c->length, i2c->option);
1759
1760        if (rval) {
1761                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1762                    EXT_STATUS_MAILBOX;
1763                goto dealloc;
1764        }
1765
1766        memcpy(i2c->buffer, sfp, i2c->length);
1767        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1768            bsg_job->reply_payload.sg_cnt, i2c, sizeof(*i2c));
1769
1770        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1771
1772dealloc:
1773        dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1774
1775done:
1776        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1777        bsg_reply->reply_payload_rcv_len = sizeof(*i2c);
1778        bsg_reply->result = DID_OK << 16;
1779        bsg_job_done(bsg_job, bsg_reply->result,
1780                       bsg_reply->reply_payload_rcv_len);
1781
1782        return 0;
1783}
1784
1785static int
1786qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
1787{
1788        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1789        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1790        scsi_qla_host_t *vha = shost_priv(host);
1791        struct qla_hw_data *ha = vha->hw;
1792        uint32_t rval = EXT_STATUS_OK;
1793        uint16_t req_sg_cnt = 0;
1794        uint16_t rsp_sg_cnt = 0;
1795        uint16_t nextlid = 0;
1796        uint32_t tot_dsds;
1797        srb_t *sp = NULL;
1798        uint32_t req_data_len;
1799        uint32_t rsp_data_len;
1800
1801        /* Check the type of the adapter */
1802        if (!IS_BIDI_CAPABLE(ha)) {
1803                ql_log(ql_log_warn, vha, 0x70a0,
1804                        "This adapter is not supported\n");
1805                rval = EXT_STATUS_NOT_SUPPORTED;
1806                goto done;
1807        }
1808
1809        if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1810                test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1811                test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
1812                rval =  EXT_STATUS_BUSY;
1813                goto done;
1814        }
1815
1816        /* Check if host is online */
1817        if (!vha->flags.online) {
1818                ql_log(ql_log_warn, vha, 0x70a1,
1819                        "Host is not online\n");
1820                rval = EXT_STATUS_DEVICE_OFFLINE;
1821                goto done;
1822        }
1823
1824        /* Check if cable is plugged in or not */
1825        if (vha->device_flags & DFLG_NO_CABLE) {
1826                ql_log(ql_log_warn, vha, 0x70a2,
1827                        "Cable is unplugged...\n");
1828                rval = EXT_STATUS_INVALID_CFG;
1829                goto done;
1830        }
1831
1832        /* Check if the switch is connected or not */
1833        if (ha->current_topology != ISP_CFG_F) {
1834                ql_log(ql_log_warn, vha, 0x70a3,
1835                        "Host is not connected to the switch\n");
1836                rval = EXT_STATUS_INVALID_CFG;
1837                goto done;
1838        }
1839
1840        /* Check if operating mode is P2P */
1841        if (ha->operating_mode != P2P) {
1842                ql_log(ql_log_warn, vha, 0x70a4,
1843                    "Host operating mode is not P2p\n");
1844                rval = EXT_STATUS_INVALID_CFG;
1845                goto done;
1846        }
1847
1848        mutex_lock(&ha->selflogin_lock);
1849        if (vha->self_login_loop_id == 0) {
1850                /* Initialize all required  fields of fcport */
1851                vha->bidir_fcport.vha = vha;
1852                vha->bidir_fcport.d_id.b.al_pa = vha->d_id.b.al_pa;
1853                vha->bidir_fcport.d_id.b.area = vha->d_id.b.area;
1854                vha->bidir_fcport.d_id.b.domain = vha->d_id.b.domain;
1855                vha->bidir_fcport.loop_id = vha->loop_id;
1856
1857                if (qla2x00_fabric_login(vha, &(vha->bidir_fcport), &nextlid)) {
1858                        ql_log(ql_log_warn, vha, 0x70a7,
1859                            "Failed to login port %06X for bidirectional IOCB\n",
1860                            vha->bidir_fcport.d_id.b24);
1861                        mutex_unlock(&ha->selflogin_lock);
1862                        rval = EXT_STATUS_MAILBOX;
1863                        goto done;
1864                }
1865                vha->self_login_loop_id = nextlid - 1;
1866
1867        }
1868        /* Assign the self login loop id to fcport */
1869        mutex_unlock(&ha->selflogin_lock);
1870
1871        vha->bidir_fcport.loop_id = vha->self_login_loop_id;
1872
1873        req_sg_cnt = dma_map_sg(&ha->pdev->dev,
1874                bsg_job->request_payload.sg_list,
1875                bsg_job->request_payload.sg_cnt,
1876                DMA_TO_DEVICE);
1877
1878        if (!req_sg_cnt) {
1879                rval = EXT_STATUS_NO_MEMORY;
1880                goto done;
1881        }
1882
1883        rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
1884                bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
1885                DMA_FROM_DEVICE);
1886
1887        if (!rsp_sg_cnt) {
1888                rval = EXT_STATUS_NO_MEMORY;
1889                goto done_unmap_req_sg;
1890        }
1891
1892        if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
1893                (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
1894                ql_dbg(ql_dbg_user, vha, 0x70a9,
1895                    "Dma mapping resulted in different sg counts "
1896                    "[request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt: "
1897                    "%x dma_reply_sg_cnt: %x]\n",
1898                    bsg_job->request_payload.sg_cnt, req_sg_cnt,
1899                    bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
1900                rval = EXT_STATUS_NO_MEMORY;
1901                goto done_unmap_sg;
1902        }
1903
1904        req_data_len = bsg_job->request_payload.payload_len;
1905        rsp_data_len = bsg_job->reply_payload.payload_len;
1906
1907        if (req_data_len != rsp_data_len) {
1908                rval = EXT_STATUS_BUSY;
1909                ql_log(ql_log_warn, vha, 0x70aa,
1910                    "req_data_len != rsp_data_len\n");
1911                goto done_unmap_sg;
1912        }
1913
1914        /* Alloc SRB structure */
1915        sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL);
1916        if (!sp) {
1917                ql_dbg(ql_dbg_user, vha, 0x70ac,
1918                    "Alloc SRB structure failed\n");
1919                rval = EXT_STATUS_NO_MEMORY;
1920                goto done_unmap_sg;
1921        }
1922
1923        /*Populate srb->ctx with bidir ctx*/
1924        sp->u.bsg_job = bsg_job;
1925        sp->free = qla2x00_bsg_sp_free;
1926        sp->type = SRB_BIDI_CMD;
1927        sp->done = qla2x00_bsg_job_done;
1928
1929        /* Add the read and write sg count */
1930        tot_dsds = rsp_sg_cnt + req_sg_cnt;
1931
1932        rval = qla2x00_start_bidir(sp, vha, tot_dsds);
1933        if (rval != EXT_STATUS_OK)
1934                goto done_free_srb;
1935        /* the bsg request  will be completed in the interrupt handler */
1936        return rval;
1937
1938done_free_srb:
1939        mempool_free(sp, ha->srb_mempool);
1940done_unmap_sg:
1941        dma_unmap_sg(&ha->pdev->dev,
1942            bsg_job->reply_payload.sg_list,
1943            bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1944done_unmap_req_sg:
1945        dma_unmap_sg(&ha->pdev->dev,
1946            bsg_job->request_payload.sg_list,
1947            bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1948done:
1949
1950        /* Return an error vendor specific response
1951         * and complete the bsg request
1952         */
1953        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
1954        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1955        bsg_reply->reply_payload_rcv_len = 0;
1956        bsg_reply->result = (DID_OK) << 16;
1957        bsg_job_done(bsg_job, bsg_reply->result,
1958                       bsg_reply->reply_payload_rcv_len);
1959        /* Always return success, vendor rsp carries correct status */
1960        return 0;
1961}
1962
1963static int
1964qlafx00_mgmt_cmd(struct bsg_job *bsg_job)
1965{
1966        struct fc_bsg_request *bsg_request = bsg_job->request;
1967        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1968        scsi_qla_host_t *vha = shost_priv(host);
1969        struct qla_hw_data *ha = vha->hw;
1970        int rval = (DID_ERROR << 16);
1971        struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
1972        srb_t *sp;
1973        int req_sg_cnt = 0, rsp_sg_cnt = 0;
1974        struct fc_port *fcport;
1975        char  *type = "FC_BSG_HST_FX_MGMT";
1976
1977        /* Copy the IOCB specific information */
1978        piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
1979            &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1980
1981        /* Dump the vendor information */
1982        ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf,
1983            piocb_rqst, sizeof(*piocb_rqst));
1984
1985        if (!vha->flags.online) {
1986                ql_log(ql_log_warn, vha, 0x70d0,
1987                    "Host is not online.\n");
1988                rval = -EIO;
1989                goto done;
1990        }
1991
1992        if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) {
1993                req_sg_cnt = dma_map_sg(&ha->pdev->dev,
1994                    bsg_job->request_payload.sg_list,
1995                    bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1996                if (!req_sg_cnt) {
1997                        ql_log(ql_log_warn, vha, 0x70c7,
1998                            "dma_map_sg return %d for request\n", req_sg_cnt);
1999                        rval = -ENOMEM;
2000                        goto done;
2001                }
2002        }
2003
2004        if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) {
2005                rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
2006                    bsg_job->reply_payload.sg_list,
2007                    bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2008                if (!rsp_sg_cnt) {
2009                        ql_log(ql_log_warn, vha, 0x70c8,
2010                            "dma_map_sg return %d for reply\n", rsp_sg_cnt);
2011                        rval = -ENOMEM;
2012                        goto done_unmap_req_sg;
2013                }
2014        }
2015
2016        ql_dbg(ql_dbg_user, vha, 0x70c9,
2017            "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
2018            "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
2019            req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
2020
2021        /* Allocate a dummy fcport structure, since functions preparing the
2022         * IOCB and mailbox command retrieves port specific information
2023         * from fcport structure. For Host based ELS commands there will be
2024         * no fcport structure allocated
2025         */
2026        fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
2027        if (!fcport) {
2028                ql_log(ql_log_warn, vha, 0x70ca,
2029                    "Failed to allocate fcport.\n");
2030                rval = -ENOMEM;
2031                goto done_unmap_rsp_sg;
2032        }
2033
2034        /* Alloc SRB structure */
2035        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
2036        if (!sp) {
2037                ql_log(ql_log_warn, vha, 0x70cb,
2038                    "qla2x00_get_sp failed.\n");
2039                rval = -ENOMEM;
2040                goto done_free_fcport;
2041        }
2042
2043        /* Initialize all required  fields of fcport */
2044        fcport->vha = vha;
2045        fcport->loop_id = le32_to_cpu(piocb_rqst->dataword);
2046
2047        sp->type = SRB_FXIOCB_BCMD;
2048        sp->name = "bsg_fx_mgmt";
2049        sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
2050        sp->u.bsg_job = bsg_job;
2051        sp->free = qla2x00_bsg_sp_free;
2052        sp->done = qla2x00_bsg_job_done;
2053
2054        ql_dbg(ql_dbg_user, vha, 0x70cc,
2055            "bsg rqst type: %s fx_mgmt_type: %x id=%x\n",
2056            type, piocb_rqst->func_type, fcport->loop_id);
2057
2058        rval = qla2x00_start_sp(sp);
2059        if (rval != QLA_SUCCESS) {
2060                ql_log(ql_log_warn, vha, 0x70cd,
2061                    "qla2x00_start_sp failed=%d.\n", rval);
2062                mempool_free(sp, ha->srb_mempool);
2063                rval = -EIO;
2064                goto done_free_fcport;
2065        }
2066        return rval;
2067
2068done_free_fcport:
2069        qla2x00_free_fcport(fcport);
2070
2071done_unmap_rsp_sg:
2072        if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
2073                dma_unmap_sg(&ha->pdev->dev,
2074                    bsg_job->reply_payload.sg_list,
2075                    bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2076done_unmap_req_sg:
2077        if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
2078                dma_unmap_sg(&ha->pdev->dev,
2079                    bsg_job->request_payload.sg_list,
2080                    bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2081
2082done:
2083        return rval;
2084}
2085
2086static int
2087qla26xx_serdes_op(struct bsg_job *bsg_job)
2088{
2089        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2090        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2091        scsi_qla_host_t *vha = shost_priv(host);
2092        int rval = 0;
2093        struct qla_serdes_reg sr;
2094
2095        memset(&sr, 0, sizeof(sr));
2096
2097        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2098            bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
2099
2100        switch (sr.cmd) {
2101        case INT_SC_SERDES_WRITE_REG:
2102                rval = qla2x00_write_serdes_word(vha, sr.addr, sr.val);
2103                bsg_reply->reply_payload_rcv_len = 0;
2104                break;
2105        case INT_SC_SERDES_READ_REG:
2106                rval = qla2x00_read_serdes_word(vha, sr.addr, &sr.val);
2107                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2108                    bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
2109                bsg_reply->reply_payload_rcv_len = sizeof(sr);
2110                break;
2111        default:
2112                ql_dbg(ql_dbg_user, vha, 0x708c,
2113                    "Unknown serdes cmd %x.\n", sr.cmd);
2114                rval = -EINVAL;
2115                break;
2116        }
2117
2118        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2119            rval ? EXT_STATUS_MAILBOX : 0;
2120
2121        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2122        bsg_reply->result = DID_OK << 16;
2123        bsg_job_done(bsg_job, bsg_reply->result,
2124                       bsg_reply->reply_payload_rcv_len);
2125        return 0;
2126}
2127
2128static int
2129qla8044_serdes_op(struct bsg_job *bsg_job)
2130{
2131        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2132        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2133        scsi_qla_host_t *vha = shost_priv(host);
2134        int rval = 0;
2135        struct qla_serdes_reg_ex sr;
2136
2137        memset(&sr, 0, sizeof(sr));
2138
2139        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2140            bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
2141
2142        switch (sr.cmd) {
2143        case INT_SC_SERDES_WRITE_REG:
2144                rval = qla8044_write_serdes_word(vha, sr.addr, sr.val);
2145                bsg_reply->reply_payload_rcv_len = 0;
2146                break;
2147        case INT_SC_SERDES_READ_REG:
2148                rval = qla8044_read_serdes_word(vha, sr.addr, &sr.val);
2149                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2150                    bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
2151                bsg_reply->reply_payload_rcv_len = sizeof(sr);
2152                break;
2153        default:
2154                ql_dbg(ql_dbg_user, vha, 0x7020,
2155                    "Unknown serdes cmd %x.\n", sr.cmd);
2156                rval = -EINVAL;
2157                break;
2158        }
2159
2160        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2161            rval ? EXT_STATUS_MAILBOX : 0;
2162
2163        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2164        bsg_reply->result = DID_OK << 16;
2165        bsg_job_done(bsg_job, bsg_reply->result,
2166                       bsg_reply->reply_payload_rcv_len);
2167        return 0;
2168}
2169
2170static int
2171qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job)
2172{
2173        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2174        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2175        scsi_qla_host_t *vha = shost_priv(host);
2176        struct qla_hw_data *ha = vha->hw;
2177        struct qla_flash_update_caps cap;
2178
2179        if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha))
2180                return -EPERM;
2181
2182        memset(&cap, 0, sizeof(cap));
2183        cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 |
2184                           (uint64_t)ha->fw_attributes_ext[0] << 32 |
2185                           (uint64_t)ha->fw_attributes_h << 16 |
2186                           (uint64_t)ha->fw_attributes;
2187
2188        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2189            bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap));
2190        bsg_reply->reply_payload_rcv_len = sizeof(cap);
2191
2192        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2193            EXT_STATUS_OK;
2194
2195        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2196        bsg_reply->result = DID_OK << 16;
2197        bsg_job_done(bsg_job, bsg_reply->result,
2198                       bsg_reply->reply_payload_rcv_len);
2199        return 0;
2200}
2201
2202static int
2203qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job)
2204{
2205        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2206        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2207        scsi_qla_host_t *vha = shost_priv(host);
2208        struct qla_hw_data *ha = vha->hw;
2209        uint64_t online_fw_attr = 0;
2210        struct qla_flash_update_caps cap;
2211
2212        if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
2213                return -EPERM;
2214
2215        memset(&cap, 0, sizeof(cap));
2216        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2217            bsg_job->request_payload.sg_cnt, &cap, sizeof(cap));
2218
2219        online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 |
2220                         (uint64_t)ha->fw_attributes_ext[0] << 32 |
2221                         (uint64_t)ha->fw_attributes_h << 16 |
2222                         (uint64_t)ha->fw_attributes;
2223
2224        if (online_fw_attr != cap.capabilities) {
2225                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2226                    EXT_STATUS_INVALID_PARAM;
2227                return -EINVAL;
2228        }
2229
2230        if (cap.outage_duration < MAX_LOOP_TIMEOUT)  {
2231                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2232                    EXT_STATUS_INVALID_PARAM;
2233                return -EINVAL;
2234        }
2235
2236        bsg_reply->reply_payload_rcv_len = 0;
2237
2238        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2239            EXT_STATUS_OK;
2240
2241        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2242        bsg_reply->result = DID_OK << 16;
2243        bsg_job_done(bsg_job, bsg_reply->result,
2244                       bsg_reply->reply_payload_rcv_len);
2245        return 0;
2246}
2247
2248static int
2249qla27xx_get_bbcr_data(struct bsg_job *bsg_job)
2250{
2251        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2252        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2253        scsi_qla_host_t *vha = shost_priv(host);
2254        struct qla_hw_data *ha = vha->hw;
2255        struct qla_bbcr_data bbcr;
2256        uint16_t loop_id, topo, sw_cap;
2257        uint8_t domain, area, al_pa, state;
2258        int rval;
2259
2260        if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
2261                return -EPERM;
2262
2263        memset(&bbcr, 0, sizeof(bbcr));
2264
2265        if (vha->flags.bbcr_enable)
2266                bbcr.status = QLA_BBCR_STATUS_ENABLED;
2267        else
2268                bbcr.status = QLA_BBCR_STATUS_DISABLED;
2269
2270        if (bbcr.status == QLA_BBCR_STATUS_ENABLED) {
2271                rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
2272                        &area, &domain, &topo, &sw_cap);
2273                if (rval != QLA_SUCCESS) {
2274                        bbcr.status = QLA_BBCR_STATUS_UNKNOWN;
2275                        bbcr.state = QLA_BBCR_STATE_OFFLINE;
2276                        bbcr.mbx1 = loop_id;
2277                        goto done;
2278                }
2279
2280                state = (vha->bbcr >> 12) & 0x1;
2281
2282                if (state) {
2283                        bbcr.state = QLA_BBCR_STATE_OFFLINE;
2284                        bbcr.offline_reason_code = QLA_BBCR_REASON_LOGIN_REJECT;
2285                } else {
2286                        bbcr.state = QLA_BBCR_STATE_ONLINE;
2287                        bbcr.negotiated_bbscn = (vha->bbcr >> 8) & 0xf;
2288                }
2289
2290                bbcr.configured_bbscn = vha->bbcr & 0xf;
2291        }
2292
2293done:
2294        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2295                bsg_job->reply_payload.sg_cnt, &bbcr, sizeof(bbcr));
2296        bsg_reply->reply_payload_rcv_len = sizeof(bbcr);
2297
2298        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2299
2300        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2301        bsg_reply->result = DID_OK << 16;
2302        bsg_job_done(bsg_job, bsg_reply->result,
2303                       bsg_reply->reply_payload_rcv_len);
2304        return 0;
2305}
2306
2307static int
2308qla2x00_get_priv_stats(struct bsg_job *bsg_job)
2309{
2310        struct fc_bsg_request *bsg_request = bsg_job->request;
2311        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2312        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2313        scsi_qla_host_t *vha = shost_priv(host);
2314        struct qla_hw_data *ha = vha->hw;
2315        struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
2316        struct link_statistics *stats = NULL;
2317        dma_addr_t stats_dma;
2318        int rval;
2319        uint32_t *cmd = bsg_request->rqst_data.h_vendor.vendor_cmd;
2320        uint options = cmd[0] == QL_VND_GET_PRIV_STATS_EX ? cmd[1] : 0;
2321
2322        if (test_bit(UNLOADING, &vha->dpc_flags))
2323                return -ENODEV;
2324
2325        if (unlikely(pci_channel_offline(ha->pdev)))
2326                return -ENODEV;
2327
2328        if (qla2x00_reset_active(vha))
2329                return -EBUSY;
2330
2331        if (!IS_FWI2_CAPABLE(ha))
2332                return -EPERM;
2333
2334        stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
2335                                   GFP_KERNEL);
2336        if (!stats) {
2337                ql_log(ql_log_warn, vha, 0x70e2,
2338                    "Failed to allocate memory for stats.\n");
2339                return -ENOMEM;
2340        }
2341
2342        rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options);
2343
2344        if (rval == QLA_SUCCESS) {
2345                ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5,
2346                        stats, sizeof(*stats));
2347                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2348                        bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats));
2349        }
2350
2351        bsg_reply->reply_payload_rcv_len = sizeof(*stats);
2352        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2353            rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
2354
2355        bsg_job->reply_len = sizeof(*bsg_reply);
2356        bsg_reply->result = DID_OK << 16;
2357        bsg_job_done(bsg_job, bsg_reply->result,
2358                       bsg_reply->reply_payload_rcv_len);
2359
2360        dma_free_coherent(&ha->pdev->dev, sizeof(*stats),
2361                stats, stats_dma);
2362
2363        return 0;
2364}
2365
2366static int
2367qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
2368{
2369        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2370        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2371        scsi_qla_host_t *vha = shost_priv(host);
2372        int rval;
2373        struct qla_dport_diag *dd;
2374
2375        if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
2376            !IS_QLA28XX(vha->hw))
2377                return -EPERM;
2378
2379        dd = kmalloc(sizeof(*dd), GFP_KERNEL);
2380        if (!dd) {
2381                ql_log(ql_log_warn, vha, 0x70db,
2382                    "Failed to allocate memory for dport.\n");
2383                return -ENOMEM;
2384        }
2385
2386        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2387            bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
2388
2389        rval = qla26xx_dport_diagnostics(
2390            vha, dd->buf, sizeof(dd->buf), dd->options);
2391        if (rval == QLA_SUCCESS) {
2392                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2393                    bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
2394        }
2395
2396        bsg_reply->reply_payload_rcv_len = sizeof(*dd);
2397        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2398            rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
2399
2400        bsg_job->reply_len = sizeof(*bsg_reply);
2401        bsg_reply->result = DID_OK << 16;
2402        bsg_job_done(bsg_job, bsg_reply->result,
2403                       bsg_reply->reply_payload_rcv_len);
2404
2405        kfree(dd);
2406
2407        return 0;
2408}
2409
2410static int
2411qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
2412{
2413        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2414        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2415        struct qla_hw_data *ha = vha->hw;
2416        struct qla_active_regions regions = { };
2417        struct active_regions active_regions = { };
2418
2419        qla27xx_get_active_image(vha, &active_regions);
2420        regions.global_image = active_regions.global;
2421
2422        if (IS_QLA28XX(ha)) {
2423                qla28xx_get_aux_images(vha, &active_regions);
2424                regions.board_config = active_regions.aux.board_config;
2425                regions.vpd_nvram = active_regions.aux.vpd_nvram;
2426                regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
2427                regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3;
2428        }
2429
2430        ql_dbg(ql_dbg_user, vha, 0x70e1,
2431            "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n",
2432            __func__, vha->host_no, regions.global_image,
2433            regions.board_config, regions.vpd_nvram,
2434            regions.npiv_config_0_1, regions.npiv_config_2_3);
2435
2436        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2437            bsg_job->reply_payload.sg_cnt, &regions, sizeof(regions));
2438
2439        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2440        bsg_reply->reply_payload_rcv_len = sizeof(regions);
2441        bsg_reply->result = DID_OK << 16;
2442        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2443        bsg_job_done(bsg_job, bsg_reply->result,
2444            bsg_reply->reply_payload_rcv_len);
2445
2446        return 0;
2447}
2448
2449static int
2450qla2x00_manage_host_stats(struct bsg_job *bsg_job)
2451{
2452        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2453        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2454        struct ql_vnd_mng_host_stats_param *req_data;
2455        struct ql_vnd_mng_host_stats_resp rsp_data;
2456        u32 req_data_len;
2457        int ret = 0;
2458
2459        if (!vha->flags.online) {
2460                ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
2461                return -EIO;
2462        }
2463
2464        req_data_len = bsg_job->request_payload.payload_len;
2465
2466        if (req_data_len != sizeof(struct ql_vnd_mng_host_stats_param)) {
2467                ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2468                return -EIO;
2469        }
2470
2471        req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2472        if (!req_data) {
2473                ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2474                return -ENOMEM;
2475        }
2476
2477        /* Copy the request buffer in req_data */
2478        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2479                          bsg_job->request_payload.sg_cnt, req_data,
2480                          req_data_len);
2481
2482        switch (req_data->action) {
2483        case QLA_STOP:
2484                ret = qla2xxx_stop_stats(vha->host, req_data->stat_type);
2485                break;
2486        case QLA_START:
2487                ret = qla2xxx_start_stats(vha->host, req_data->stat_type);
2488                break;
2489        case QLA_CLEAR:
2490                ret = qla2xxx_reset_stats(vha->host, req_data->stat_type);
2491                break;
2492        default:
2493                ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
2494                ret = -EIO;
2495                break;
2496        }
2497
2498        kfree(req_data);
2499
2500        /* Prepare response */
2501        rsp_data.status = ret;
2502        bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2503
2504        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2505        bsg_reply->reply_payload_rcv_len =
2506                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2507                                    bsg_job->reply_payload.sg_cnt,
2508                                    &rsp_data,
2509                                    sizeof(struct ql_vnd_mng_host_stats_resp));
2510
2511        bsg_reply->result = DID_OK;
2512        bsg_job_done(bsg_job, bsg_reply->result,
2513                     bsg_reply->reply_payload_rcv_len);
2514
2515        return ret;
2516}
2517
2518static int
2519qla2x00_get_host_stats(struct bsg_job *bsg_job)
2520{
2521        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2522        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2523        struct ql_vnd_stats_param *req_data;
2524        struct ql_vnd_host_stats_resp rsp_data;
2525        u32 req_data_len;
2526        int ret = 0;
2527        u64 ini_entry_count = 0;
2528        u64 entry_count = 0;
2529        u64 tgt_num = 0;
2530        u64 tmp_stat_type = 0;
2531        u64 response_len = 0;
2532        void *data;
2533
2534        req_data_len = bsg_job->request_payload.payload_len;
2535
2536        if (req_data_len != sizeof(struct ql_vnd_stats_param)) {
2537                ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2538                return -EIO;
2539        }
2540
2541        req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2542        if (!req_data) {
2543                ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2544                return -ENOMEM;
2545        }
2546
2547        /* Copy the request buffer in req_data */
2548        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2549                          bsg_job->request_payload.sg_cnt, req_data, req_data_len);
2550
2551        /* Copy stat type to work on it */
2552        tmp_stat_type = req_data->stat_type;
2553
2554        if (tmp_stat_type & QLA2XX_TGT_SHT_LNK_DOWN) {
2555                /* Num of tgts connected to this host */
2556                tgt_num = qla2x00_get_num_tgts(vha);
2557                /* unset BIT_17 */
2558                tmp_stat_type &= ~(1 << 17);
2559        }
2560
2561        /* Total ini stats */
2562        ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
2563
2564        /* Total number of entries */
2565        entry_count = ini_entry_count + tgt_num;
2566
2567        response_len = sizeof(struct ql_vnd_host_stats_resp) +
2568                (sizeof(struct ql_vnd_stat_entry) * entry_count);
2569
2570        if (response_len > bsg_job->reply_payload.payload_len) {
2571                rsp_data.status = EXT_STATUS_BUFFER_TOO_SMALL;
2572                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
2573                bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2574
2575                bsg_reply->reply_payload_rcv_len =
2576                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2577                                            bsg_job->reply_payload.sg_cnt, &rsp_data,
2578                                            sizeof(struct ql_vnd_mng_host_stats_resp));
2579
2580                bsg_reply->result = DID_OK;
2581                bsg_job_done(bsg_job, bsg_reply->result,
2582                             bsg_reply->reply_payload_rcv_len);
2583                goto host_stat_out;
2584        }
2585
2586        data = kzalloc(response_len, GFP_KERNEL);
2587        if (!data) {
2588                ret = -ENOMEM;
2589                goto host_stat_out;
2590        }
2591
2592        ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
2593                                    data, response_len);
2594
2595        rsp_data.status = EXT_STATUS_OK;
2596        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2597
2598        bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2599                                                               bsg_job->reply_payload.sg_cnt,
2600                                                               data, response_len);
2601        bsg_reply->result = DID_OK;
2602        bsg_job_done(bsg_job, bsg_reply->result,
2603                     bsg_reply->reply_payload_rcv_len);
2604
2605        kfree(data);
2606host_stat_out:
2607        kfree(req_data);
2608        return ret;
2609}
2610
2611static struct fc_rport *
2612qla2xxx_find_rport(scsi_qla_host_t *vha, uint32_t tgt_num)
2613{
2614        fc_port_t *fcport = NULL;
2615
2616        list_for_each_entry(fcport, &vha->vp_fcports, list) {
2617                if (fcport->rport->number == tgt_num)
2618                        return fcport->rport;
2619        }
2620        return NULL;
2621}
2622
2623static int
2624qla2x00_get_tgt_stats(struct bsg_job *bsg_job)
2625{
2626        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2627        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2628        struct ql_vnd_tgt_stats_param *req_data;
2629        u32 req_data_len;
2630        int ret = 0;
2631        u64 response_len = 0;
2632        struct ql_vnd_tgt_stats_resp *data = NULL;
2633        struct fc_rport *rport = NULL;
2634
2635        if (!vha->flags.online) {
2636                ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
2637                return -EIO;
2638        }
2639
2640        req_data_len = bsg_job->request_payload.payload_len;
2641
2642        if (req_data_len != sizeof(struct ql_vnd_stat_entry)) {
2643                ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2644                return -EIO;
2645        }
2646
2647        req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2648        if (!req_data) {
2649                ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2650                return -ENOMEM;
2651        }
2652
2653        /* Copy the request buffer in req_data */
2654        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2655                          bsg_job->request_payload.sg_cnt,
2656                          req_data, req_data_len);
2657
2658        response_len = sizeof(struct ql_vnd_tgt_stats_resp) +
2659                sizeof(struct ql_vnd_stat_entry);
2660
2661        /* structure + size for one entry */
2662        data = kzalloc(response_len, GFP_KERNEL);
2663        if (!data) {
2664                kfree(req_data);
2665                return -ENOMEM;
2666        }
2667
2668        if (response_len > bsg_job->reply_payload.payload_len) {
2669                data->status = EXT_STATUS_BUFFER_TOO_SMALL;
2670                bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
2671                bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2672
2673                bsg_reply->reply_payload_rcv_len =
2674                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2675                                            bsg_job->reply_payload.sg_cnt, data,
2676                                            sizeof(struct ql_vnd_tgt_stats_resp));
2677
2678                bsg_reply->result = DID_OK;
2679                bsg_job_done(bsg_job, bsg_reply->result,
2680                             bsg_reply->reply_payload_rcv_len);
2681                goto tgt_stat_out;
2682        }
2683
2684        rport = qla2xxx_find_rport(vha, req_data->tgt_id);
2685        if (!rport) {
2686                ql_log(ql_log_warn, vha, 0x0000, "target %d not found.\n", req_data->tgt_id);
2687                ret = EXT_STATUS_INVALID_PARAM;
2688                data->status = EXT_STATUS_INVALID_PARAM;
2689                goto reply;
2690        }
2691
2692        ret = qla2xxx_get_tgt_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
2693                                    rport, (void *)data, response_len);
2694
2695        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2696reply:
2697        bsg_reply->reply_payload_rcv_len =
2698                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2699                                    bsg_job->reply_payload.sg_cnt, data,
2700                                    response_len);
2701        bsg_reply->result = DID_OK;
2702        bsg_job_done(bsg_job, bsg_reply->result,
2703                     bsg_reply->reply_payload_rcv_len);
2704
2705tgt_stat_out:
2706        kfree(data);
2707        kfree(req_data);
2708
2709        return ret;
2710}
2711
2712static int
2713qla2x00_manage_host_port(struct bsg_job *bsg_job)
2714{
2715        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2716        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2717        struct ql_vnd_mng_host_port_param *req_data;
2718        struct ql_vnd_mng_host_port_resp rsp_data;
2719        u32 req_data_len;
2720        int ret = 0;
2721
2722        req_data_len = bsg_job->request_payload.payload_len;
2723
2724        if (req_data_len != sizeof(struct ql_vnd_mng_host_port_param)) {
2725                ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2726                return -EIO;
2727        }
2728
2729        req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2730        if (!req_data) {
2731                ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2732                return -ENOMEM;
2733        }
2734
2735        /* Copy the request buffer in req_data */
2736        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2737                          bsg_job->request_payload.sg_cnt, req_data, req_data_len);
2738
2739        switch (req_data->action) {
2740        case QLA_ENABLE:
2741                ret = qla2xxx_enable_port(vha->host);
2742                break;
2743        case QLA_DISABLE:
2744                ret = qla2xxx_disable_port(vha->host);
2745                break;
2746        default:
2747                ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
2748                ret = -EIO;
2749                break;
2750        }
2751
2752        kfree(req_data);
2753
2754        /* Prepare response */
2755        rsp_data.status = ret;
2756        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2757        bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_port_resp);
2758
2759        bsg_reply->reply_payload_rcv_len =
2760                sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2761                                    bsg_job->reply_payload.sg_cnt, &rsp_data,
2762                                    sizeof(struct ql_vnd_mng_host_port_resp));
2763        bsg_reply->result = DID_OK;
2764        bsg_job_done(bsg_job, bsg_reply->result,
2765                     bsg_reply->reply_payload_rcv_len);
2766
2767        return ret;
2768}
2769
2770static int
2771qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
2772{
2773        struct fc_bsg_request *bsg_request = bsg_job->request;
2774
2775        switch (bsg_request->rqst_data.h_vendor.vendor_cmd[0]) {
2776        case QL_VND_LOOPBACK:
2777                return qla2x00_process_loopback(bsg_job);
2778
2779        case QL_VND_A84_RESET:
2780                return qla84xx_reset(bsg_job);
2781
2782        case QL_VND_A84_UPDATE_FW:
2783                return qla84xx_updatefw(bsg_job);
2784
2785        case QL_VND_A84_MGMT_CMD:
2786                return qla84xx_mgmt_cmd(bsg_job);
2787
2788        case QL_VND_IIDMA:
2789                return qla24xx_iidma(bsg_job);
2790
2791        case QL_VND_FCP_PRIO_CFG_CMD:
2792                return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
2793
2794        case QL_VND_READ_FLASH:
2795                return qla2x00_read_optrom(bsg_job);
2796
2797        case QL_VND_UPDATE_FLASH:
2798                return qla2x00_update_optrom(bsg_job);
2799
2800        case QL_VND_SET_FRU_VERSION:
2801                return qla2x00_update_fru_versions(bsg_job);
2802
2803        case QL_VND_READ_FRU_STATUS:
2804                return qla2x00_read_fru_status(bsg_job);
2805
2806        case QL_VND_WRITE_FRU_STATUS:
2807                return qla2x00_write_fru_status(bsg_job);
2808
2809        case QL_VND_WRITE_I2C:
2810                return qla2x00_write_i2c(bsg_job);
2811
2812        case QL_VND_READ_I2C:
2813                return qla2x00_read_i2c(bsg_job);
2814
2815        case QL_VND_DIAG_IO_CMD:
2816                return qla24xx_process_bidir_cmd(bsg_job);
2817
2818        case QL_VND_FX00_MGMT_CMD:
2819                return qlafx00_mgmt_cmd(bsg_job);
2820
2821        case QL_VND_SERDES_OP:
2822                return qla26xx_serdes_op(bsg_job);
2823
2824        case QL_VND_SERDES_OP_EX:
2825                return qla8044_serdes_op(bsg_job);
2826
2827        case QL_VND_GET_FLASH_UPDATE_CAPS:
2828                return qla27xx_get_flash_upd_cap(bsg_job);
2829
2830        case QL_VND_SET_FLASH_UPDATE_CAPS:
2831                return qla27xx_set_flash_upd_cap(bsg_job);
2832
2833        case QL_VND_GET_BBCR_DATA:
2834                return qla27xx_get_bbcr_data(bsg_job);
2835
2836        case QL_VND_GET_PRIV_STATS:
2837        case QL_VND_GET_PRIV_STATS_EX:
2838                return qla2x00_get_priv_stats(bsg_job);
2839
2840        case QL_VND_DPORT_DIAGNOSTICS:
2841                return qla2x00_do_dport_diagnostics(bsg_job);
2842
2843        case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
2844                return qla2x00_get_flash_image_status(bsg_job);
2845
2846        case QL_VND_MANAGE_HOST_STATS:
2847                return qla2x00_manage_host_stats(bsg_job);
2848
2849        case QL_VND_GET_HOST_STATS:
2850                return qla2x00_get_host_stats(bsg_job);
2851
2852        case QL_VND_GET_TGT_STATS:
2853                return qla2x00_get_tgt_stats(bsg_job);
2854
2855        case QL_VND_MANAGE_HOST_PORT:
2856                return qla2x00_manage_host_port(bsg_job);
2857
2858        default:
2859                return -ENOSYS;
2860        }
2861}
2862
2863int
2864qla24xx_bsg_request(struct bsg_job *bsg_job)
2865{
2866        struct fc_bsg_request *bsg_request = bsg_job->request;
2867        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2868        int ret = -EINVAL;
2869        struct fc_rport *rport;
2870        struct Scsi_Host *host;
2871        scsi_qla_host_t *vha;
2872
2873        /* In case no data transferred. */
2874        bsg_reply->reply_payload_rcv_len = 0;
2875
2876        if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
2877                rport = fc_bsg_to_rport(bsg_job);
2878                host = rport_to_shost(rport);
2879                vha = shost_priv(host);
2880        } else {
2881                host = fc_bsg_to_shost(bsg_job);
2882                vha = shost_priv(host);
2883        }
2884
2885        /* Disable port will bring down the chip, allow enable command */
2886        if (bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_MANAGE_HOST_PORT ||
2887            bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_GET_HOST_STATS)
2888                goto skip_chip_chk;
2889
2890        if (vha->hw->flags.port_isolated) {
2891                bsg_reply->result = DID_ERROR;
2892                /* operation not permitted */
2893                return -EPERM;
2894        }
2895
2896        if (qla2x00_chip_is_down(vha)) {
2897                ql_dbg(ql_dbg_user, vha, 0x709f,
2898                    "BSG: ISP abort active/needed -- cmd=%d.\n",
2899                    bsg_request->msgcode);
2900                return -EBUSY;
2901        }
2902
2903skip_chip_chk:
2904        ql_dbg(ql_dbg_user, vha, 0x7000,
2905            "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode);
2906
2907        switch (bsg_request->msgcode) {
2908        case FC_BSG_RPT_ELS:
2909        case FC_BSG_HST_ELS_NOLOGIN:
2910                ret = qla2x00_process_els(bsg_job);
2911                break;
2912        case FC_BSG_HST_CT:
2913                ret = qla2x00_process_ct(bsg_job);
2914                break;
2915        case FC_BSG_HST_VENDOR:
2916                ret = qla2x00_process_vendor_specific(bsg_job);
2917                break;
2918        case FC_BSG_HST_ADD_RPORT:
2919        case FC_BSG_HST_DEL_RPORT:
2920        case FC_BSG_RPT_CT:
2921        default:
2922                ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
2923                break;
2924        }
2925        return ret;
2926}
2927
2928int
2929qla24xx_bsg_timeout(struct bsg_job *bsg_job)
2930{
2931        struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2932        scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2933        struct qla_hw_data *ha = vha->hw;
2934        srb_t *sp;
2935        int cnt, que;
2936        unsigned long flags;
2937        struct req_que *req;
2938
2939        /* find the bsg job from the active list of commands */
2940        spin_lock_irqsave(&ha->hardware_lock, flags);
2941        for (que = 0; que < ha->max_req_queues; que++) {
2942                req = ha->req_q_map[que];
2943                if (!req)
2944                        continue;
2945
2946                for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
2947                        sp = req->outstanding_cmds[cnt];
2948                        if (sp) {
2949                                if (((sp->type == SRB_CT_CMD) ||
2950                                        (sp->type == SRB_ELS_CMD_HST) ||
2951                                        (sp->type == SRB_FXIOCB_BCMD))
2952                                        && (sp->u.bsg_job == bsg_job)) {
2953                                        req->outstanding_cmds[cnt] = NULL;
2954                                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
2955                                        if (ha->isp_ops->abort_command(sp)) {
2956                                                ql_log(ql_log_warn, vha, 0x7089,
2957                                                    "mbx abort_command "
2958                                                    "failed.\n");
2959                                                bsg_reply->result = -EIO;
2960                                        } else {
2961                                                ql_dbg(ql_dbg_user, vha, 0x708a,
2962                                                    "mbx abort_command "
2963                                                    "success.\n");
2964                                                bsg_reply->result = 0;
2965                                        }
2966                                        spin_lock_irqsave(&ha->hardware_lock, flags);
2967                                        goto done;
2968                                }
2969                        }
2970                }
2971        }
2972        spin_unlock_irqrestore(&ha->hardware_lock, flags);
2973        ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
2974        bsg_reply->result = -ENXIO;
2975        return 0;
2976
2977done:
2978        spin_unlock_irqrestore(&ha->hardware_lock, flags);
2979        sp->free(sp);
2980        return 0;
2981}
2982