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