File Index
Files and directories
Sign in
FILE

qla_bsg.c

File preview with syntax highlighting.

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