brintos

brintos / linux-shallow public Read only

0
0
Text · 157.5 KiB · 85059b8 Raw
5695 lines · c
1/*******************************************************************2 * This file is part of the Emulex Linux Device Driver for         *3 * Fibre Channel Host Bus Adapters.                                *4 * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *5 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *6 * Copyright (C) 2009-2015 Emulex.  All rights reserved.           *7 * EMULEX and SLI are trademarks of Emulex.                        *8 * www.broadcom.com                                                *9 *                                                                 *10 * This program is free software; you can redistribute it and/or   *11 * modify it under the terms of version 2 of the GNU General       *12 * Public License as published by the Free Software Foundation.    *13 * This program is distributed in the hope that it will be useful. *14 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *15 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *16 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *17 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *18 * TO BE LEGALLY INVALID.  See the GNU General Public License for  *19 * more details, a copy of which can be found in the file COPYING  *20 * included with this package.                                     *21 *******************************************************************/22 23#include <linux/interrupt.h>24#include <linux/mempool.h>25#include <linux/pci.h>26#include <linux/slab.h>27#include <linux/delay.h>28#include <linux/list.h>29#include <linux/bsg-lib.h>30#include <linux/vmalloc.h>31 32#include <scsi/scsi.h>33#include <scsi/scsi_host.h>34#include <scsi/scsi_transport_fc.h>35#include <scsi/scsi_bsg_fc.h>36#include <scsi/fc/fc_fs.h>37 38#include "lpfc_hw4.h"39#include "lpfc_hw.h"40#include "lpfc_sli.h"41#include "lpfc_sli4.h"42#include "lpfc_nl.h"43#include "lpfc_bsg.h"44#include "lpfc_disc.h"45#include "lpfc_scsi.h"46#include "lpfc.h"47#include "lpfc_logmsg.h"48#include "lpfc_crtn.h"49#include "lpfc_debugfs.h"50#include "lpfc_vport.h"51#include "lpfc_version.h"52 53struct lpfc_bsg_event {54	struct list_head node;55	struct kref kref;56	wait_queue_head_t wq;57 58	/* Event type and waiter identifiers */59	uint32_t type_mask;60	uint32_t req_id;61	uint32_t reg_id;62 63	/* next two flags are here for the auto-delete logic */64	unsigned long wait_time_stamp;65	int waiting;66 67	/* seen and not seen events */68	struct list_head events_to_get;69	struct list_head events_to_see;70 71	/* driver data associated with the job */72	void *dd_data;73};74 75struct lpfc_bsg_iocb {76	struct lpfc_iocbq *cmdiocbq;77	struct lpfc_dmabuf *rmp;78	struct lpfc_nodelist *ndlp;79};80 81struct lpfc_bsg_mbox {82	LPFC_MBOXQ_t *pmboxq;83	MAILBOX_t *mb;84	struct lpfc_dmabuf *dmabuffers; /* for BIU diags */85	uint8_t *ext; /* extended mailbox data */86	uint32_t mbOffset; /* from app */87	uint32_t inExtWLen; /* from app */88	uint32_t outExtWLen; /* from app */89};90 91#define TYPE_EVT 	192#define TYPE_IOCB	293#define TYPE_MBOX	394struct bsg_job_data {95	uint32_t type;96	struct bsg_job *set_job; /* job waiting for this iocb to finish */97	union {98		struct lpfc_bsg_event *evt;99		struct lpfc_bsg_iocb iocb;100		struct lpfc_bsg_mbox mbox;101	} context_un;102};103 104struct event_data {105	struct list_head node;106	uint32_t type;107	uint32_t immed_dat;108	void *data;109	uint32_t len;110};111 112#define BUF_SZ_4K 4096113#define SLI_CT_ELX_LOOPBACK 0x10114 115enum ELX_LOOPBACK_CMD {116	ELX_LOOPBACK_XRI_SETUP,117	ELX_LOOPBACK_DATA,118};119 120#define ELX_LOOPBACK_HEADER_SZ \121	(size_t)(&((struct lpfc_sli_ct_request *)NULL)->un)122 123struct lpfc_dmabufext {124	struct lpfc_dmabuf dma;125	uint32_t size;126	uint32_t flag;127};128 129static void130lpfc_free_bsg_buffers(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)131{132	struct lpfc_dmabuf *mlast, *next_mlast;133 134	if (mlist) {135		list_for_each_entry_safe(mlast, next_mlast, &mlist->list,136					 list) {137			list_del(&mlast->list);138			lpfc_mbuf_free(phba, mlast->virt, mlast->phys);139			kfree(mlast);140		}141		lpfc_mbuf_free(phba, mlist->virt, mlist->phys);142		kfree(mlist);143	}144	return;145}146 147static struct lpfc_dmabuf *148lpfc_alloc_bsg_buffers(struct lpfc_hba *phba, unsigned int size,149		       int outbound_buffers, struct ulp_bde64 *bpl,150		       int *bpl_entries)151{152	struct lpfc_dmabuf *mlist = NULL;153	struct lpfc_dmabuf *mp;154	unsigned int bytes_left = size;155 156	/* Verify we can support the size specified */157	if (!size || (size > (*bpl_entries * LPFC_BPL_SIZE)))158		return NULL;159 160	/* Determine the number of dma buffers to allocate */161	*bpl_entries = (size % LPFC_BPL_SIZE ? size/LPFC_BPL_SIZE + 1 :162			size/LPFC_BPL_SIZE);163 164	/* Allocate dma buffer and place in BPL passed */165	while (bytes_left) {166		/* Allocate dma buffer  */167		mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);168		if (!mp) {169			if (mlist)170				lpfc_free_bsg_buffers(phba, mlist);171			return NULL;172		}173 174		INIT_LIST_HEAD(&mp->list);175		mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));176 177		if (!mp->virt) {178			kfree(mp);179			if (mlist)180				lpfc_free_bsg_buffers(phba, mlist);181			return NULL;182		}183 184		/* Queue it to a linked list */185		if (!mlist)186			mlist = mp;187		else188			list_add_tail(&mp->list, &mlist->list);189 190		/* Add buffer to buffer pointer list */191		if (outbound_buffers)192			bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;193		else194			bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;195		bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));196		bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));197		bpl->tus.f.bdeSize = (uint16_t)198			(bytes_left >= LPFC_BPL_SIZE ? LPFC_BPL_SIZE :199			 bytes_left);200		bytes_left -= bpl->tus.f.bdeSize;201		bpl->tus.w = le32_to_cpu(bpl->tus.w);202		bpl++;203	}204	return mlist;205}206 207static unsigned int208lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers,209		   struct bsg_buffer *bsg_buffers,210		   unsigned int bytes_to_transfer, int to_buffers)211{212 213	struct lpfc_dmabuf *mp;214	unsigned int transfer_bytes, bytes_copied = 0;215	unsigned int sg_offset, dma_offset;216	unsigned char *dma_address, *sg_address;217	LIST_HEAD(temp_list);218	struct sg_mapping_iter miter;219	unsigned long flags;220	unsigned int sg_flags = SG_MITER_ATOMIC;221	bool sg_valid;222 223	list_splice_init(&dma_buffers->list, &temp_list);224	list_add(&dma_buffers->list, &temp_list);225	sg_offset = 0;226	if (to_buffers)227		sg_flags |= SG_MITER_FROM_SG;228	else229		sg_flags |= SG_MITER_TO_SG;230	sg_miter_start(&miter, bsg_buffers->sg_list, bsg_buffers->sg_cnt,231		       sg_flags);232	local_irq_save(flags);233	sg_valid = sg_miter_next(&miter);234	list_for_each_entry(mp, &temp_list, list) {235		dma_offset = 0;236		while (bytes_to_transfer && sg_valid &&237		       (dma_offset < LPFC_BPL_SIZE)) {238			dma_address = mp->virt + dma_offset;239			if (sg_offset) {240				/* Continue previous partial transfer of sg */241				sg_address = miter.addr + sg_offset;242				transfer_bytes = miter.length - sg_offset;243			} else {244				sg_address = miter.addr;245				transfer_bytes = miter.length;246			}247			if (bytes_to_transfer < transfer_bytes)248				transfer_bytes = bytes_to_transfer;249			if (transfer_bytes > (LPFC_BPL_SIZE - dma_offset))250				transfer_bytes = LPFC_BPL_SIZE - dma_offset;251			if (to_buffers)252				memcpy(dma_address, sg_address, transfer_bytes);253			else254				memcpy(sg_address, dma_address, transfer_bytes);255			dma_offset += transfer_bytes;256			sg_offset += transfer_bytes;257			bytes_to_transfer -= transfer_bytes;258			bytes_copied += transfer_bytes;259			if (sg_offset >= miter.length) {260				sg_offset = 0;261				sg_valid = sg_miter_next(&miter);262			}263		}264	}265	sg_miter_stop(&miter);266	local_irq_restore(flags);267	list_del_init(&dma_buffers->list);268	list_splice(&temp_list, &dma_buffers->list);269	return bytes_copied;270}271 272/**273 * lpfc_bsg_send_mgmt_cmd_cmp - lpfc_bsg_send_mgmt_cmd's completion handler274 * @phba: Pointer to HBA context object.275 * @cmdiocbq: Pointer to command iocb.276 * @rspiocbq: Pointer to response iocb.277 *278 * This function is the completion handler for iocbs issued using279 * lpfc_bsg_send_mgmt_cmd function. This function is called by the280 * ring event handler function without any lock held. This function281 * can be called from both worker thread context and interrupt282 * context. This function also can be called from another thread which283 * cleans up the SLI layer objects.284 * This function copies the contents of the response iocb to the285 * response iocb memory object provided by the caller of286 * lpfc_sli_issue_iocb_wait and then wakes up the thread which287 * sleeps for the iocb completion.288 **/289static void290lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,291			struct lpfc_iocbq *cmdiocbq,292			struct lpfc_iocbq *rspiocbq)293{294	struct bsg_job_data *dd_data;295	struct bsg_job *job;296	struct fc_bsg_reply *bsg_reply;297	struct lpfc_dmabuf *bmp, *cmp, *rmp;298	struct lpfc_nodelist *ndlp;299	struct lpfc_bsg_iocb *iocb;300	unsigned long flags;301	int rc = 0;302	u32 ulp_status, ulp_word4, total_data_placed;303 304	dd_data = cmdiocbq->context_un.dd_data;305 306	/* Determine if job has been aborted */307	spin_lock_irqsave(&phba->ct_ev_lock, flags);308	job = dd_data->set_job;309	if (job) {310		bsg_reply = job->reply;311		/* Prevent timeout handling from trying to abort job */312		job->dd_data = NULL;313	}314	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);315 316	/* Close the timeout handler abort window */317	spin_lock_irqsave(&phba->hbalock, flags);318	cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING;319	spin_unlock_irqrestore(&phba->hbalock, flags);320 321	iocb = &dd_data->context_un.iocb;322	ndlp = iocb->cmdiocbq->ndlp;323	rmp = iocb->rmp;324	cmp = cmdiocbq->cmd_dmabuf;325	bmp = cmdiocbq->bpl_dmabuf;326	ulp_status = get_job_ulpstatus(phba, rspiocbq);327	ulp_word4 = get_job_word4(phba, rspiocbq);328	total_data_placed = get_job_data_placed(phba, rspiocbq);329 330	/* Copy the completed data or set the error status */331 332	if (job) {333		if (ulp_status) {334			if (ulp_status == IOSTAT_LOCAL_REJECT) {335				switch (ulp_word4 & IOERR_PARAM_MASK) {336				case IOERR_SEQUENCE_TIMEOUT:337					rc = -ETIMEDOUT;338					break;339				case IOERR_INVALID_RPI:340					rc = -EFAULT;341					break;342				default:343					rc = -EACCES;344					break;345				}346			} else {347				rc = -EACCES;348			}349		} else {350			bsg_reply->reply_payload_rcv_len =351				lpfc_bsg_copy_data(rmp, &job->reply_payload,352						   total_data_placed, 0);353		}354	}355 356	lpfc_free_bsg_buffers(phba, cmp);357	lpfc_free_bsg_buffers(phba, rmp);358	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);359	kfree(bmp);360	lpfc_nlp_put(ndlp);361	lpfc_sli_release_iocbq(phba, cmdiocbq);362	kfree(dd_data);363 364	/* Complete the job if the job is still active */365 366	if (job) {367		bsg_reply->result = rc;368		bsg_job_done(job, bsg_reply->result,369			       bsg_reply->reply_payload_rcv_len);370	}371	return;372}373 374/**375 * lpfc_bsg_send_mgmt_cmd - send a CT command from a bsg request376 * @job: fc_bsg_job to handle377 **/378static int379lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)380{381	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));382	struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;383	struct lpfc_hba *phba = vport->phba;384	struct lpfc_nodelist *ndlp = rdata->pnode;385	struct fc_bsg_reply *bsg_reply = job->reply;386	struct ulp_bde64 *bpl = NULL;387	struct lpfc_iocbq *cmdiocbq = NULL;388	struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;389	int request_nseg, reply_nseg;390	u32 num_entry;391	struct bsg_job_data *dd_data;392	unsigned long flags;393	uint32_t creg_val;394	int rc = 0;395	int iocb_stat;396	u16 ulp_context;397 398	/* in case no data is transferred */399	bsg_reply->reply_payload_rcv_len = 0;400 401	if (ndlp->nlp_flag & NLP_ELS_SND_MASK)402		return -ENODEV;403 404	/* allocate our bsg tracking structure */405	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);406	if (!dd_data) {407		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,408				"2733 Failed allocation of dd_data\n");409		rc = -ENOMEM;410		goto no_dd_data;411	}412 413	cmdiocbq = lpfc_sli_get_iocbq(phba);414	if (!cmdiocbq) {415		rc = -ENOMEM;416		goto free_dd;417	}418 419	bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);420	if (!bmp) {421		rc = -ENOMEM;422		goto free_cmdiocbq;423	}424	bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);425	if (!bmp->virt) {426		rc = -ENOMEM;427		goto free_bmp;428	}429 430	INIT_LIST_HEAD(&bmp->list);431 432	bpl = (struct ulp_bde64 *) bmp->virt;433	request_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64);434	cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,435				     1, bpl, &request_nseg);436	if (!cmp) {437		rc = -ENOMEM;438		goto free_bmp;439	}440	lpfc_bsg_copy_data(cmp, &job->request_payload,441			   job->request_payload.payload_len, 1);442 443	bpl += request_nseg;444	reply_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64) - request_nseg;445	rmp = lpfc_alloc_bsg_buffers(phba, job->reply_payload.payload_len, 0,446				     bpl, &reply_nseg);447	if (!rmp) {448		rc = -ENOMEM;449		goto free_cmp;450	}451 452	num_entry = request_nseg + reply_nseg;453 454	if (phba->sli_rev == LPFC_SLI_REV4)455		ulp_context = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];456	else457		ulp_context = ndlp->nlp_rpi;458 459	lpfc_sli_prep_gen_req(phba, cmdiocbq, bmp, ulp_context, num_entry,460			      phba->fc_ratov * 2);461 462	cmdiocbq->num_bdes = num_entry;463	cmdiocbq->vport = phba->pport;464	cmdiocbq->cmd_dmabuf = cmp;465	cmdiocbq->bpl_dmabuf = bmp;466	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;467 468	cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;469	cmdiocbq->context_un.dd_data = dd_data;470 471	dd_data->type = TYPE_IOCB;472	dd_data->set_job = job;473	dd_data->context_un.iocb.cmdiocbq = cmdiocbq;474	dd_data->context_un.iocb.rmp = rmp;475	job->dd_data = dd_data;476 477	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {478		if (lpfc_readl(phba->HCregaddr, &creg_val)) {479			rc = -EIO ;480			goto free_rmp;481		}482		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);483		writel(creg_val, phba->HCregaddr);484		readl(phba->HCregaddr); /* flush */485	}486 487	cmdiocbq->ndlp = lpfc_nlp_get(ndlp);488	if (!cmdiocbq->ndlp) {489		rc = -ENODEV;490		goto free_rmp;491	}492 493	iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);494	if (iocb_stat == IOCB_SUCCESS) {495		spin_lock_irqsave(&phba->hbalock, flags);496		/* make sure the I/O had not been completed yet */497		if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) {498			/* open up abort window to timeout handler */499			cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING;500		}501		spin_unlock_irqrestore(&phba->hbalock, flags);502		return 0; /* done for now */503	} else if (iocb_stat == IOCB_BUSY) {504		rc = -EAGAIN;505	} else {506		rc = -EIO;507	}508 509	/* iocb failed so cleanup */510	lpfc_nlp_put(ndlp);511 512free_rmp:513	lpfc_free_bsg_buffers(phba, rmp);514free_cmp:515	lpfc_free_bsg_buffers(phba, cmp);516free_bmp:517	if (bmp->virt)518		lpfc_mbuf_free(phba, bmp->virt, bmp->phys);519	kfree(bmp);520free_cmdiocbq:521	lpfc_sli_release_iocbq(phba, cmdiocbq);522free_dd:523	kfree(dd_data);524no_dd_data:525	/* make error code available to userspace */526	bsg_reply->result = rc;527	job->dd_data = NULL;528	return rc;529}530 531/**532 * lpfc_bsg_rport_els_cmp - lpfc_bsg_rport_els's completion handler533 * @phba: Pointer to HBA context object.534 * @cmdiocbq: Pointer to command iocb.535 * @rspiocbq: Pointer to response iocb.536 *537 * This function is the completion handler for iocbs issued using538 * lpfc_bsg_rport_els_cmp function. This function is called by the539 * ring event handler function without any lock held. This function540 * can be called from both worker thread context and interrupt541 * context. This function also can be called from other thread which542 * cleans up the SLI layer objects.543 * This function copies the contents of the response iocb to the544 * response iocb memory object provided by the caller of545 * lpfc_sli_issue_iocb_wait and then wakes up the thread which546 * sleeps for the iocb completion.547 **/548static void549lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,550			struct lpfc_iocbq *cmdiocbq,551			struct lpfc_iocbq *rspiocbq)552{553	struct bsg_job_data *dd_data;554	struct bsg_job *job;555	struct fc_bsg_reply *bsg_reply;556	struct lpfc_nodelist *ndlp;557	struct lpfc_dmabuf *pcmd = NULL, *prsp = NULL;558	struct fc_bsg_ctels_reply *els_reply;559	uint8_t *rjt_data;560	unsigned long flags;561	unsigned int rsp_size;562	int rc = 0;563	u32 ulp_status, ulp_word4, total_data_placed;564 565	dd_data = cmdiocbq->context_un.dd_data;566	ndlp = dd_data->context_un.iocb.ndlp;567	cmdiocbq->ndlp = ndlp;568 569	/* Determine if job has been aborted */570	spin_lock_irqsave(&phba->ct_ev_lock, flags);571	job = dd_data->set_job;572	if (job) {573		bsg_reply = job->reply;574		/* Prevent timeout handling from trying to abort job  */575		job->dd_data = NULL;576	}577	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);578 579	/* Close the timeout handler abort window */580	spin_lock_irqsave(&phba->hbalock, flags);581	cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING;582	spin_unlock_irqrestore(&phba->hbalock, flags);583 584	ulp_status = get_job_ulpstatus(phba, rspiocbq);585	ulp_word4 = get_job_word4(phba, rspiocbq);586	total_data_placed = get_job_data_placed(phba, rspiocbq);587	pcmd = cmdiocbq->cmd_dmabuf;588	prsp = (struct lpfc_dmabuf *)pcmd->list.next;589 590	/* Copy the completed job data or determine the job status if job is591	 * still active592	 */593 594	if (job) {595		if (ulp_status == IOSTAT_SUCCESS) {596			rsp_size = total_data_placed;597			bsg_reply->reply_payload_rcv_len =598				sg_copy_from_buffer(job->reply_payload.sg_list,599						    job->reply_payload.sg_cnt,600						    prsp->virt,601						    rsp_size);602		} else if (ulp_status == IOSTAT_LS_RJT) {603			bsg_reply->reply_payload_rcv_len =604				sizeof(struct fc_bsg_ctels_reply);605			/* LS_RJT data returned in word 4 */606			rjt_data = (uint8_t *)&ulp_word4;607			els_reply = &bsg_reply->reply_data.ctels_reply;608			els_reply->status = FC_CTELS_STATUS_REJECT;609			els_reply->rjt_data.action = rjt_data[3];610			els_reply->rjt_data.reason_code = rjt_data[2];611			els_reply->rjt_data.reason_explanation = rjt_data[1];612			els_reply->rjt_data.vendor_unique = rjt_data[0];613		} else if (ulp_status == IOSTAT_LOCAL_REJECT &&614			   (ulp_word4 & IOERR_PARAM_MASK) ==615			   IOERR_SEQUENCE_TIMEOUT) {616			rc = -ETIMEDOUT;617		} else {618			rc = -EIO;619		}620	}621 622	lpfc_els_free_iocb(phba, cmdiocbq);623 624	lpfc_nlp_put(ndlp);625	kfree(dd_data);626 627	/* Complete the job if the job is still active */628 629	if (job) {630		bsg_reply->result = rc;631		bsg_job_done(job, bsg_reply->result,632			       bsg_reply->reply_payload_rcv_len);633	}634	return;635}636 637/**638 * lpfc_bsg_rport_els - send an ELS command from a bsg request639 * @job: fc_bsg_job to handle640 **/641static int642lpfc_bsg_rport_els(struct bsg_job *job)643{644	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));645	struct lpfc_hba *phba = vport->phba;646	struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;647	struct lpfc_nodelist *ndlp = rdata->pnode;648	struct fc_bsg_request *bsg_request = job->request;649	struct fc_bsg_reply *bsg_reply = job->reply;650	uint32_t elscmd;651	uint32_t cmdsize;652	struct lpfc_iocbq *cmdiocbq;653	uint16_t rpi = 0;654	struct bsg_job_data *dd_data;655	unsigned long flags;656	uint32_t creg_val;657	int rc = 0;658 659	/* in case no data is transferred */660	bsg_reply->reply_payload_rcv_len = 0;661 662	/* verify the els command is not greater than the663	 * maximum ELS transfer size.664	 */665 666	if (job->request_payload.payload_len > FCELSSIZE) {667		rc = -EINVAL;668		goto no_dd_data;669	}670 671	/* allocate our bsg tracking structure */672	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);673	if (!dd_data) {674		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,675				"2735 Failed allocation of dd_data\n");676		rc = -ENOMEM;677		goto no_dd_data;678	}679 680	elscmd = bsg_request->rqst_data.r_els.els_code;681	cmdsize = job->request_payload.payload_len;682 683	if (!lpfc_nlp_get(ndlp)) {684		rc = -ENODEV;685		goto free_dd_data;686	}687 688	/* We will use the allocated dma buffers by prep els iocb for command689	 * and response to ensure if the job times out and the request is freed,690	 * we won't be dma into memory that is no longer allocated to for the691	 * request.692	 */693	cmdiocbq = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp,694				      ndlp->nlp_DID, elscmd);695	if (!cmdiocbq) {696		rc = -EIO;697		goto release_ndlp;698	}699 700	/* Transfer the request payload to allocated command dma buffer */701	sg_copy_to_buffer(job->request_payload.sg_list,702			  job->request_payload.sg_cnt,703			  cmdiocbq->cmd_dmabuf->virt,704			  cmdsize);705 706	rpi = ndlp->nlp_rpi;707 708	if (phba->sli_rev == LPFC_SLI_REV4)709		bf_set(wqe_ctxt_tag, &cmdiocbq->wqe.generic.wqe_com,710		       phba->sli4_hba.rpi_ids[rpi]);711	else712		cmdiocbq->iocb.ulpContext = rpi;713	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;714	cmdiocbq->context_un.dd_data = dd_data;715	cmdiocbq->ndlp = ndlp;716	cmdiocbq->cmd_cmpl = lpfc_bsg_rport_els_cmp;717	dd_data->type = TYPE_IOCB;718	dd_data->set_job = job;719	dd_data->context_un.iocb.cmdiocbq = cmdiocbq;720	dd_data->context_un.iocb.ndlp = ndlp;721	dd_data->context_un.iocb.rmp = NULL;722	job->dd_data = dd_data;723 724	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {725		if (lpfc_readl(phba->HCregaddr, &creg_val)) {726			rc = -EIO;727			goto linkdown_err;728		}729		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);730		writel(creg_val, phba->HCregaddr);731		readl(phba->HCregaddr); /* flush */732	}733 734	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);735	if (rc == IOCB_SUCCESS) {736		spin_lock_irqsave(&phba->hbalock, flags);737		/* make sure the I/O had not been completed/released */738		if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) {739			/* open up abort window to timeout handler */740			cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING;741		}742		spin_unlock_irqrestore(&phba->hbalock, flags);743		return 0; /* done for now */744	} else if (rc == IOCB_BUSY) {745		rc = -EAGAIN;746	} else {747		rc = -EIO;748	}749 750	/* I/O issue failed.  Cleanup resources. */751 752linkdown_err:753	lpfc_els_free_iocb(phba, cmdiocbq);754 755release_ndlp:756	lpfc_nlp_put(ndlp);757 758free_dd_data:759	kfree(dd_data);760 761no_dd_data:762	/* make error code available to userspace */763	bsg_reply->result = rc;764	job->dd_data = NULL;765	return rc;766}767 768/**769 * lpfc_bsg_event_free - frees an allocated event structure770 * @kref: Pointer to a kref.771 *772 * Called from kref_put. Back cast the kref into an event structure address.773 * Free any events to get, delete associated nodes, free any events to see,774 * free any data then free the event itself.775 **/776static void777lpfc_bsg_event_free(struct kref *kref)778{779	struct lpfc_bsg_event *evt = container_of(kref, struct lpfc_bsg_event,780						  kref);781	struct event_data *ed;782 783	list_del(&evt->node);784 785	while (!list_empty(&evt->events_to_get)) {786		ed = list_entry(evt->events_to_get.next, typeof(*ed), node);787		list_del(&ed->node);788		kfree(ed->data);789		kfree(ed);790	}791 792	while (!list_empty(&evt->events_to_see)) {793		ed = list_entry(evt->events_to_see.next, typeof(*ed), node);794		list_del(&ed->node);795		kfree(ed->data);796		kfree(ed);797	}798 799	kfree(evt->dd_data);800	kfree(evt);801}802 803/**804 * lpfc_bsg_event_ref - increments the kref for an event805 * @evt: Pointer to an event structure.806 **/807static inline void808lpfc_bsg_event_ref(struct lpfc_bsg_event *evt)809{810	kref_get(&evt->kref);811}812 813/**814 * lpfc_bsg_event_unref - Uses kref_put to free an event structure815 * @evt: Pointer to an event structure.816 **/817static inline void818lpfc_bsg_event_unref(struct lpfc_bsg_event *evt)819{820	kref_put(&evt->kref, lpfc_bsg_event_free);821}822 823/**824 * lpfc_bsg_event_new - allocate and initialize a event structure825 * @ev_mask: Mask of events.826 * @ev_reg_id: Event reg id.827 * @ev_req_id: Event request id.828 **/829static struct lpfc_bsg_event *830lpfc_bsg_event_new(uint32_t ev_mask, int ev_reg_id, uint32_t ev_req_id)831{832	struct lpfc_bsg_event *evt = kzalloc(sizeof(*evt), GFP_KERNEL);833 834	if (!evt)835		return NULL;836 837	INIT_LIST_HEAD(&evt->events_to_get);838	INIT_LIST_HEAD(&evt->events_to_see);839	evt->type_mask = ev_mask;840	evt->req_id = ev_req_id;841	evt->reg_id = ev_reg_id;842	evt->wait_time_stamp = jiffies;843	evt->dd_data = NULL;844	init_waitqueue_head(&evt->wq);845	kref_init(&evt->kref);846	return evt;847}848 849/**850 * diag_cmd_data_free - Frees an lpfc dma buffer extension851 * @phba: Pointer to HBA context object.852 * @mlist: Pointer to an lpfc dma buffer extension.853 **/854static int855diag_cmd_data_free(struct lpfc_hba *phba, struct lpfc_dmabufext *mlist)856{857	struct lpfc_dmabufext *mlast;858	struct pci_dev *pcidev;859	struct list_head head, *curr, *next;860 861	if ((!mlist) || (!lpfc_is_link_up(phba) &&862		(phba->link_flag & LS_LOOPBACK_MODE))) {863		return 0;864	}865 866	pcidev = phba->pcidev;867	list_add_tail(&head, &mlist->dma.list);868 869	list_for_each_safe(curr, next, &head) {870		mlast = list_entry(curr, struct lpfc_dmabufext , dma.list);871		if (mlast->dma.virt)872			dma_free_coherent(&pcidev->dev,873					  mlast->size,874					  mlast->dma.virt,875					  mlast->dma.phys);876		kfree(mlast);877	}878	return 0;879}880 881/*882 * lpfc_bsg_ct_unsol_event - process an unsolicited CT command883 *884 * This function is called when an unsolicited CT command is received.  It885 * forwards the event to any processes registered to receive CT events.886 **/887int888lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,889			struct lpfc_iocbq *piocbq)890{891	uint32_t evt_req_id = 0;892	u16 cmd;893	struct lpfc_dmabuf *dmabuf = NULL;894	struct lpfc_bsg_event *evt;895	struct event_data *evt_dat = NULL;896	struct lpfc_iocbq *iocbq;897	IOCB_t *iocb = NULL;898	size_t offset = 0;899	struct list_head head;900	struct ulp_bde64 *bde;901	dma_addr_t dma_addr;902	int i;903	struct lpfc_dmabuf *bdeBuf1 = piocbq->cmd_dmabuf;904	struct lpfc_dmabuf *bdeBuf2 = piocbq->bpl_dmabuf;905	struct lpfc_sli_ct_request *ct_req;906	struct bsg_job *job = NULL;907	struct fc_bsg_reply *bsg_reply;908	struct bsg_job_data *dd_data = NULL;909	unsigned long flags;910	int size = 0;911	u32 bde_count = 0;912 913	INIT_LIST_HEAD(&head);914	list_add_tail(&head, &piocbq->list);915 916	ct_req = (struct lpfc_sli_ct_request *)bdeBuf1->virt;917	evt_req_id = ct_req->FsType;918	cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp);919 920	spin_lock_irqsave(&phba->ct_ev_lock, flags);921	list_for_each_entry(evt, &phba->ct_ev_waiters, node) {922		if (!(evt->type_mask & FC_REG_CT_EVENT) ||923			evt->req_id != evt_req_id)924			continue;925 926		lpfc_bsg_event_ref(evt);927		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);928		evt_dat = kzalloc(sizeof(*evt_dat), GFP_KERNEL);929		if (evt_dat == NULL) {930			spin_lock_irqsave(&phba->ct_ev_lock, flags);931			lpfc_bsg_event_unref(evt);932			lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,933					"2614 Memory allocation failed for "934					"CT event\n");935			break;936		}937 938		if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {939			/* take accumulated byte count from the last iocbq */940			iocbq = list_entry(head.prev, typeof(*iocbq), list);941			if (phba->sli_rev == LPFC_SLI_REV4)942				evt_dat->len = iocbq->wcqe_cmpl.total_data_placed;943			else944				evt_dat->len = iocbq->iocb.unsli3.rcvsli3.acc_len;945		} else {946			list_for_each_entry(iocbq, &head, list) {947				iocb = &iocbq->iocb;948				for (i = 0; i < iocb->ulpBdeCount;949				     i++)950					evt_dat->len +=951					iocb->un.cont64[i].tus.f.bdeSize;952			}953		}954 955		evt_dat->data = kzalloc(evt_dat->len, GFP_KERNEL);956		if (evt_dat->data == NULL) {957			lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,958					"2615 Memory allocation failed for "959					"CT event data, size %d\n",960					evt_dat->len);961			kfree(evt_dat);962			spin_lock_irqsave(&phba->ct_ev_lock, flags);963			lpfc_bsg_event_unref(evt);964			spin_unlock_irqrestore(&phba->ct_ev_lock, flags);965			goto error_ct_unsol_exit;966		}967 968		list_for_each_entry(iocbq, &head, list) {969			size = 0;970			if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {971				bdeBuf1 = iocbq->cmd_dmabuf;972				bdeBuf2 = iocbq->bpl_dmabuf;973			}974			if (phba->sli_rev == LPFC_SLI_REV4)975				bde_count = iocbq->wcqe_cmpl.word3;976			else977				bde_count = iocbq->iocb.ulpBdeCount;978			for (i = 0; i < bde_count; i++) {979				if (phba->sli3_options &980				    LPFC_SLI3_HBQ_ENABLED) {981					if (i == 0) {982						size = iocbq->wqe.gen_req.bde.tus.f.bdeSize;983						dmabuf = bdeBuf1;984					} else if (i == 1) {985						size = iocbq->unsol_rcv_len;986						dmabuf = bdeBuf2;987					}988					if ((offset + size) > evt_dat->len)989						size = evt_dat->len - offset;990				} else {991					size = iocbq->iocb.un.cont64[i].992						tus.f.bdeSize;993					bde = &iocbq->iocb.un.cont64[i];994					dma_addr = getPaddr(bde->addrHigh,995							    bde->addrLow);996					dmabuf = lpfc_sli_ringpostbuf_get(phba,997							pring, dma_addr);998				}999				if (!dmabuf) {1000					lpfc_printf_log(phba, KERN_ERR,1001						LOG_LIBDFC, "2616 No dmabuf "1002						"found for iocbq x%px\n",1003						iocbq);1004					kfree(evt_dat->data);1005					kfree(evt_dat);1006					spin_lock_irqsave(&phba->ct_ev_lock,1007						flags);1008					lpfc_bsg_event_unref(evt);1009					spin_unlock_irqrestore(1010						&phba->ct_ev_lock, flags);1011					goto error_ct_unsol_exit;1012				}1013				memcpy((char *)(evt_dat->data) + offset,1014				       dmabuf->virt, size);1015				offset += size;1016				if (evt_req_id != SLI_CT_ELX_LOOPBACK &&1017				    !(phba->sli3_options &1018				      LPFC_SLI3_HBQ_ENABLED)) {1019					lpfc_sli_ringpostbuf_put(phba, pring,1020								 dmabuf);1021				} else {1022					switch (cmd) {1023					case ELX_LOOPBACK_DATA:1024						if (phba->sli_rev <1025						    LPFC_SLI_REV4)1026							diag_cmd_data_free(phba,1027							(struct lpfc_dmabufext1028							 *)dmabuf);1029						break;1030					case ELX_LOOPBACK_XRI_SETUP:1031						if ((phba->sli_rev ==1032							LPFC_SLI_REV2) ||1033							(phba->sli3_options &1034							LPFC_SLI3_HBQ_ENABLED1035							)) {1036							lpfc_in_buf_free(phba,1037									dmabuf);1038						} else {1039							lpfc_sli3_post_buffer(phba,1040									      pring,1041									      1);1042						}1043						break;1044					default:1045						if (!(phba->sli3_options &1046						      LPFC_SLI3_HBQ_ENABLED))1047							lpfc_sli3_post_buffer(phba,1048									      pring,1049									      1);1050						break;1051					}1052				}1053			}1054		}1055 1056		spin_lock_irqsave(&phba->ct_ev_lock, flags);1057		if (phba->sli_rev == LPFC_SLI_REV4) {1058			evt_dat->immed_dat = phba->ctx_idx;1059			phba->ctx_idx = (phba->ctx_idx + 1) % LPFC_CT_CTX_MAX;1060			/* Provide warning for over-run of the ct_ctx array */1061			if (phba->ct_ctx[evt_dat->immed_dat].valid ==1062			    UNSOL_VALID)1063				lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,1064						"2717 CT context array entry "1065						"[%d] over-run: oxid:x%x, "1066						"sid:x%x\n", phba->ctx_idx,1067						phba->ct_ctx[1068						    evt_dat->immed_dat].oxid,1069						phba->ct_ctx[1070						    evt_dat->immed_dat].SID);1071			phba->ct_ctx[evt_dat->immed_dat].rxid =1072				get_job_ulpcontext(phba, piocbq);1073			phba->ct_ctx[evt_dat->immed_dat].oxid =1074				get_job_rcvoxid(phba, piocbq);1075			phba->ct_ctx[evt_dat->immed_dat].SID =1076				bf_get(wqe_els_did,1077				       &piocbq->wqe.xmit_els_rsp.wqe_dest);1078			phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID;1079		} else1080			evt_dat->immed_dat = get_job_ulpcontext(phba, piocbq);1081 1082		evt_dat->type = FC_REG_CT_EVENT;1083		list_add(&evt_dat->node, &evt->events_to_see);1084		if (evt_req_id == SLI_CT_ELX_LOOPBACK) {1085			wake_up_interruptible(&evt->wq);1086			lpfc_bsg_event_unref(evt);1087			break;1088		}1089 1090		list_move(evt->events_to_see.prev, &evt->events_to_get);1091 1092		dd_data = (struct bsg_job_data *)evt->dd_data;1093		job = dd_data->set_job;1094		dd_data->set_job = NULL;1095		lpfc_bsg_event_unref(evt);1096		if (job) {1097			bsg_reply = job->reply;1098			bsg_reply->reply_payload_rcv_len = size;1099			/* make error code available to userspace */1100			bsg_reply->result = 0;1101			job->dd_data = NULL;1102			/* complete the job back to userspace */1103			spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1104			bsg_job_done(job, bsg_reply->result,1105				       bsg_reply->reply_payload_rcv_len);1106			spin_lock_irqsave(&phba->ct_ev_lock, flags);1107		}1108	}1109	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1110 1111error_ct_unsol_exit:1112	if (!list_empty(&head))1113		list_del(&head);1114	if ((phba->sli_rev < LPFC_SLI_REV4) &&1115	    (evt_req_id == SLI_CT_ELX_LOOPBACK))1116		return 0;1117	return 1;1118}1119 1120/**1121 * lpfc_bsg_ct_unsol_abort - handler ct abort to management plane1122 * @phba: Pointer to HBA context object.1123 * @dmabuf: pointer to a dmabuf that describes the FC sequence1124 *1125 * This function handles abort to the CT command toward management plane1126 * for SLI4 port.1127 *1128 * If the pending context of a CT command to management plane present, clears1129 * such context and returns 1 for handled; otherwise, it returns 0 indicating1130 * no context exists.1131 **/1132int1133lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)1134{1135	struct fc_frame_header fc_hdr;1136	struct fc_frame_header *fc_hdr_ptr = &fc_hdr;1137	int ctx_idx, handled = 0;1138	uint16_t oxid, rxid;1139	uint32_t sid;1140 1141	memcpy(fc_hdr_ptr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header));1142	sid = sli4_sid_from_fc_hdr(fc_hdr_ptr);1143	oxid = be16_to_cpu(fc_hdr_ptr->fh_ox_id);1144	rxid = be16_to_cpu(fc_hdr_ptr->fh_rx_id);1145 1146	for (ctx_idx = 0; ctx_idx < LPFC_CT_CTX_MAX; ctx_idx++) {1147		if (phba->ct_ctx[ctx_idx].valid != UNSOL_VALID)1148			continue;1149		if (phba->ct_ctx[ctx_idx].rxid != rxid)1150			continue;1151		if (phba->ct_ctx[ctx_idx].oxid != oxid)1152			continue;1153		if (phba->ct_ctx[ctx_idx].SID != sid)1154			continue;1155		phba->ct_ctx[ctx_idx].valid = UNSOL_INVALID;1156		handled = 1;1157	}1158	return handled;1159}1160 1161/**1162 * lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command1163 * @job: SET_EVENT fc_bsg_job1164 **/1165static int1166lpfc_bsg_hba_set_event(struct bsg_job *job)1167{1168	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));1169	struct lpfc_hba *phba = vport->phba;1170	struct fc_bsg_request *bsg_request = job->request;1171	struct set_ct_event *event_req;1172	struct lpfc_bsg_event *evt;1173	int rc = 0;1174	struct bsg_job_data *dd_data = NULL;1175	uint32_t ev_mask;1176	unsigned long flags;1177 1178	if (job->request_len <1179	    sizeof(struct fc_bsg_request) + sizeof(struct set_ct_event)) {1180		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1181				"2612 Received SET_CT_EVENT below minimum "1182				"size\n");1183		rc = -EINVAL;1184		goto job_error;1185	}1186 1187	event_req = (struct set_ct_event *)1188		bsg_request->rqst_data.h_vendor.vendor_cmd;1189	ev_mask = ((uint32_t)(unsigned long)event_req->type_mask &1190				FC_REG_EVENT_MASK);1191	spin_lock_irqsave(&phba->ct_ev_lock, flags);1192	list_for_each_entry(evt, &phba->ct_ev_waiters, node) {1193		if (evt->reg_id == event_req->ev_reg_id) {1194			lpfc_bsg_event_ref(evt);1195			evt->wait_time_stamp = jiffies;1196			dd_data = (struct bsg_job_data *)evt->dd_data;1197			break;1198		}1199	}1200	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1201 1202	if (&evt->node == &phba->ct_ev_waiters) {1203		/* no event waiting struct yet - first call */1204		dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);1205		if (dd_data == NULL) {1206			lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1207					"2734 Failed allocation of dd_data\n");1208			rc = -ENOMEM;1209			goto job_error;1210		}1211		evt = lpfc_bsg_event_new(ev_mask, event_req->ev_reg_id,1212					event_req->ev_req_id);1213		if (!evt) {1214			lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1215					"2617 Failed allocation of event "1216					"waiter\n");1217			rc = -ENOMEM;1218			goto job_error;1219		}1220		dd_data->type = TYPE_EVT;1221		dd_data->set_job = NULL;1222		dd_data->context_un.evt = evt;1223		evt->dd_data = (void *)dd_data;1224		spin_lock_irqsave(&phba->ct_ev_lock, flags);1225		list_add(&evt->node, &phba->ct_ev_waiters);1226		lpfc_bsg_event_ref(evt);1227		evt->wait_time_stamp = jiffies;1228		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1229	}1230 1231	spin_lock_irqsave(&phba->ct_ev_lock, flags);1232	evt->waiting = 1;1233	dd_data->set_job = job; /* for unsolicited command */1234	job->dd_data = dd_data; /* for fc transport timeout callback*/1235	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1236	return 0; /* call job done later */1237 1238job_error:1239	kfree(dd_data);1240	job->dd_data = NULL;1241	return rc;1242}1243 1244/**1245 * lpfc_bsg_hba_get_event - process a GET_EVENT bsg vendor command1246 * @job: GET_EVENT fc_bsg_job1247 **/1248static int1249lpfc_bsg_hba_get_event(struct bsg_job *job)1250{1251	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));1252	struct lpfc_hba *phba = vport->phba;1253	struct fc_bsg_request *bsg_request = job->request;1254	struct fc_bsg_reply *bsg_reply = job->reply;1255	struct get_ct_event *event_req;1256	struct get_ct_event_reply *event_reply;1257	struct lpfc_bsg_event *evt, *evt_next;1258	struct event_data *evt_dat = NULL;1259	unsigned long flags;1260	uint32_t rc = 0;1261 1262	if (job->request_len <1263	    sizeof(struct fc_bsg_request) + sizeof(struct get_ct_event)) {1264		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1265				"2613 Received GET_CT_EVENT request below "1266				"minimum size\n");1267		rc = -EINVAL;1268		goto job_error;1269	}1270 1271	event_req = (struct get_ct_event *)1272		bsg_request->rqst_data.h_vendor.vendor_cmd;1273 1274	event_reply = (struct get_ct_event_reply *)1275		bsg_reply->reply_data.vendor_reply.vendor_rsp;1276	spin_lock_irqsave(&phba->ct_ev_lock, flags);1277	list_for_each_entry_safe(evt, evt_next, &phba->ct_ev_waiters, node) {1278		if (evt->reg_id == event_req->ev_reg_id) {1279			if (list_empty(&evt->events_to_get))1280				break;1281			lpfc_bsg_event_ref(evt);1282			evt->wait_time_stamp = jiffies;1283			evt_dat = list_entry(evt->events_to_get.prev,1284					     struct event_data, node);1285			list_del(&evt_dat->node);1286			break;1287		}1288	}1289	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1290 1291	/* The app may continue to ask for event data until it gets1292	 * an error indicating that there isn't anymore1293	 */1294	if (evt_dat == NULL) {1295		bsg_reply->reply_payload_rcv_len = 0;1296		rc = -ENOENT;1297		goto job_error;1298	}1299 1300	if (evt_dat->len > job->request_payload.payload_len) {1301		evt_dat->len = job->request_payload.payload_len;1302		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1303				"2618 Truncated event data at %d "1304				"bytes\n",1305				job->request_payload.payload_len);1306	}1307 1308	event_reply->type = evt_dat->type;1309	event_reply->immed_data = evt_dat->immed_dat;1310	if (evt_dat->len > 0)1311		bsg_reply->reply_payload_rcv_len =1312			sg_copy_from_buffer(job->request_payload.sg_list,1313					    job->request_payload.sg_cnt,1314					    evt_dat->data, evt_dat->len);1315	else1316		bsg_reply->reply_payload_rcv_len = 0;1317 1318	if (evt_dat) {1319		kfree(evt_dat->data);1320		kfree(evt_dat);1321	}1322 1323	spin_lock_irqsave(&phba->ct_ev_lock, flags);1324	lpfc_bsg_event_unref(evt);1325	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1326	job->dd_data = NULL;1327	bsg_reply->result = 0;1328	bsg_job_done(job, bsg_reply->result,1329		       bsg_reply->reply_payload_rcv_len);1330	return 0;1331 1332job_error:1333	job->dd_data = NULL;1334	bsg_reply->result = rc;1335	return rc;1336}1337 1338/**1339 * lpfc_issue_ct_rsp_cmp - lpfc_issue_ct_rsp's completion handler1340 * @phba: Pointer to HBA context object.1341 * @cmdiocbq: Pointer to command iocb.1342 * @rspiocbq: Pointer to response iocb.1343 *1344 * This function is the completion handler for iocbs issued using1345 * lpfc_issue_ct_rsp_cmp function. This function is called by the1346 * ring event handler function without any lock held. This function1347 * can be called from both worker thread context and interrupt1348 * context. This function also can be called from other thread which1349 * cleans up the SLI layer objects.1350 * This function copy the contents of the response iocb to the1351 * response iocb memory object provided by the caller of1352 * lpfc_sli_issue_iocb_wait and then wakes up the thread which1353 * sleeps for the iocb completion.1354 **/1355static void1356lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,1357			struct lpfc_iocbq *cmdiocbq,1358			struct lpfc_iocbq *rspiocbq)1359{1360	struct bsg_job_data *dd_data;1361	struct bsg_job *job;1362	struct fc_bsg_reply *bsg_reply;1363	struct lpfc_dmabuf *bmp, *cmp;1364	struct lpfc_nodelist *ndlp;1365	unsigned long flags;1366	int rc = 0;1367	u32 ulp_status, ulp_word4;1368 1369	dd_data = cmdiocbq->context_un.dd_data;1370 1371	/* Determine if job has been aborted */1372	spin_lock_irqsave(&phba->ct_ev_lock, flags);1373	job = dd_data->set_job;1374	if (job) {1375		/* Prevent timeout handling from trying to abort job  */1376		job->dd_data = NULL;1377	}1378	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);1379 1380	/* Close the timeout handler abort window */1381	spin_lock_irqsave(&phba->hbalock, flags);1382	cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING;1383	spin_unlock_irqrestore(&phba->hbalock, flags);1384 1385	ndlp = dd_data->context_un.iocb.ndlp;1386	cmp = cmdiocbq->cmd_dmabuf;1387	bmp = cmdiocbq->bpl_dmabuf;1388 1389	ulp_status = get_job_ulpstatus(phba, rspiocbq);1390	ulp_word4 = get_job_word4(phba, rspiocbq);1391 1392	/* Copy the completed job data or set the error status */1393 1394	if (job) {1395		bsg_reply = job->reply;1396		if (ulp_status) {1397			if (ulp_status == IOSTAT_LOCAL_REJECT) {1398				switch (ulp_word4 & IOERR_PARAM_MASK) {1399				case IOERR_SEQUENCE_TIMEOUT:1400					rc = -ETIMEDOUT;1401					break;1402				case IOERR_INVALID_RPI:1403					rc = -EFAULT;1404					break;1405				default:1406					rc = -EACCES;1407					break;1408				}1409			} else {1410				rc = -EACCES;1411			}1412		} else {1413			bsg_reply->reply_payload_rcv_len = 0;1414		}1415	}1416 1417	lpfc_free_bsg_buffers(phba, cmp);1418	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);1419	kfree(bmp);1420	lpfc_sli_release_iocbq(phba, cmdiocbq);1421	lpfc_nlp_put(ndlp);1422	kfree(dd_data);1423 1424	/* Complete the job if the job is still active */1425 1426	if (job) {1427		bsg_reply->result = rc;1428		bsg_job_done(job, bsg_reply->result,1429			       bsg_reply->reply_payload_rcv_len);1430	}1431	return;1432}1433 1434/**1435 * lpfc_issue_ct_rsp - issue a ct response1436 * @phba: Pointer to HBA context object.1437 * @job: Pointer to the job object.1438 * @tag: tag index value into the ports context exchange array.1439 * @cmp: Pointer to a cmp dma buffer descriptor.1440 * @bmp: Pointer to a bmp dma buffer descriptor.1441 * @num_entry: Number of enties in the bde.1442 **/1443static int1444lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,1445		  struct lpfc_dmabuf *cmp, struct lpfc_dmabuf *bmp,1446		  int num_entry)1447{1448	struct lpfc_iocbq *ctiocb = NULL;1449	int rc = 0;1450	struct lpfc_nodelist *ndlp = NULL;1451	struct bsg_job_data *dd_data;1452	unsigned long flags;1453	uint32_t creg_val;1454	u16 ulp_context, iotag;1455 1456	ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID);1457	if (!ndlp) {1458		lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,1459				"2721 ndlp null for oxid %x SID %x\n",1460				phba->ct_ctx[tag].rxid,1461				phba->ct_ctx[tag].SID);1462		return IOCB_ERROR;1463	}1464 1465	/* allocate our bsg tracking structure */1466	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);1467	if (!dd_data) {1468		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1469				"2736 Failed allocation of dd_data\n");1470		rc = -ENOMEM;1471		goto no_dd_data;1472	}1473 1474	/* Allocate buffer for  command iocb */1475	ctiocb = lpfc_sli_get_iocbq(phba);1476	if (!ctiocb) {1477		rc = -ENOMEM;1478		goto no_ctiocb;1479	}1480 1481	if (phba->sli_rev == LPFC_SLI_REV4) {1482		/* Do not issue unsol response if oxid not marked as valid */1483		if (phba->ct_ctx[tag].valid != UNSOL_VALID) {1484			rc = IOCB_ERROR;1485			goto issue_ct_rsp_exit;1486		}1487 1488		lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp,1489					 phba->sli4_hba.rpi_ids[ndlp->nlp_rpi],1490					 phba->ct_ctx[tag].oxid, num_entry,1491					 FC_RCTL_DD_SOL_CTL, 1,1492					 CMD_XMIT_SEQUENCE64_WQE);1493 1494		/* The exchange is done, mark the entry as invalid */1495		phba->ct_ctx[tag].valid = UNSOL_INVALID;1496		iotag = get_wqe_reqtag(ctiocb);1497	} else {1498		lpfc_sli_prep_xmit_seq64(phba, ctiocb, bmp, 0, tag, num_entry,1499					 FC_RCTL_DD_SOL_CTL, 1,1500					 CMD_XMIT_SEQUENCE64_CX);1501		ctiocb->num_bdes = num_entry;1502		iotag = ctiocb->iocb.ulpIoTag;1503	}1504 1505	ulp_context = get_job_ulpcontext(phba, ctiocb);1506 1507	/* Xmit CT response on exchange <xid> */1508	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,1509			"2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",1510			ulp_context, iotag, tag, phba->link_state);1511 1512	ctiocb->cmd_flag |= LPFC_IO_LIBDFC;1513	ctiocb->vport = phba->pport;1514	ctiocb->context_un.dd_data = dd_data;1515	ctiocb->cmd_dmabuf = cmp;1516	ctiocb->bpl_dmabuf = bmp;1517	ctiocb->ndlp = ndlp;1518	ctiocb->cmd_cmpl = lpfc_issue_ct_rsp_cmp;1519 1520	dd_data->type = TYPE_IOCB;1521	dd_data->set_job = job;1522	dd_data->context_un.iocb.cmdiocbq = ctiocb;1523	dd_data->context_un.iocb.ndlp = lpfc_nlp_get(ndlp);1524	if (!dd_data->context_un.iocb.ndlp) {1525		rc = -IOCB_ERROR;1526		goto issue_ct_rsp_exit;1527	}1528	dd_data->context_un.iocb.rmp = NULL;1529	job->dd_data = dd_data;1530 1531	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {1532		if (lpfc_readl(phba->HCregaddr, &creg_val)) {1533			rc = -IOCB_ERROR;1534			goto issue_ct_rsp_exit;1535		}1536		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);1537		writel(creg_val, phba->HCregaddr);1538		readl(phba->HCregaddr); /* flush */1539	}1540 1541	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);1542	if (rc == IOCB_SUCCESS) {1543		spin_lock_irqsave(&phba->hbalock, flags);1544		/* make sure the I/O had not been completed/released */1545		if (ctiocb->cmd_flag & LPFC_IO_LIBDFC) {1546			/* open up abort window to timeout handler */1547			ctiocb->cmd_flag |= LPFC_IO_CMD_OUTSTANDING;1548		}1549		spin_unlock_irqrestore(&phba->hbalock, flags);1550		return 0; /* done for now */1551	}1552 1553	/* iocb failed so cleanup */1554	job->dd_data = NULL;1555	lpfc_nlp_put(ndlp);1556 1557issue_ct_rsp_exit:1558	lpfc_sli_release_iocbq(phba, ctiocb);1559no_ctiocb:1560	kfree(dd_data);1561no_dd_data:1562	return rc;1563}1564 1565/**1566 * lpfc_bsg_send_mgmt_rsp - process a SEND_MGMT_RESP bsg vendor command1567 * @job: SEND_MGMT_RESP fc_bsg_job1568 **/1569static int1570lpfc_bsg_send_mgmt_rsp(struct bsg_job *job)1571{1572	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));1573	struct lpfc_hba *phba = vport->phba;1574	struct fc_bsg_request *bsg_request = job->request;1575	struct fc_bsg_reply *bsg_reply = job->reply;1576	struct send_mgmt_resp *mgmt_resp = (struct send_mgmt_resp *)1577		bsg_request->rqst_data.h_vendor.vendor_cmd;1578	struct ulp_bde64 *bpl;1579	struct lpfc_dmabuf *bmp = NULL, *cmp = NULL;1580	int bpl_entries;1581	uint32_t tag = mgmt_resp->tag;1582	unsigned long reqbfrcnt =1583			(unsigned long)job->request_payload.payload_len;1584	int rc = 0;1585 1586	/* in case no data is transferred */1587	bsg_reply->reply_payload_rcv_len = 0;1588 1589	if (!reqbfrcnt || (reqbfrcnt > (80 * BUF_SZ_4K))) {1590		rc = -ERANGE;1591		goto send_mgmt_rsp_exit;1592	}1593 1594	bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);1595	if (!bmp) {1596		rc = -ENOMEM;1597		goto send_mgmt_rsp_exit;1598	}1599 1600	bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);1601	if (!bmp->virt) {1602		rc = -ENOMEM;1603		goto send_mgmt_rsp_free_bmp;1604	}1605 1606	INIT_LIST_HEAD(&bmp->list);1607	bpl = (struct ulp_bde64 *) bmp->virt;1608	bpl_entries = (LPFC_BPL_SIZE/sizeof(struct ulp_bde64));1609	cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,1610				     1, bpl, &bpl_entries);1611	if (!cmp) {1612		rc = -ENOMEM;1613		goto send_mgmt_rsp_free_bmp;1614	}1615	lpfc_bsg_copy_data(cmp, &job->request_payload,1616			   job->request_payload.payload_len, 1);1617 1618	rc = lpfc_issue_ct_rsp(phba, job, tag, cmp, bmp, bpl_entries);1619 1620	if (rc == IOCB_SUCCESS)1621		return 0; /* done for now */1622 1623	rc = -EACCES;1624 1625	lpfc_free_bsg_buffers(phba, cmp);1626 1627send_mgmt_rsp_free_bmp:1628	if (bmp->virt)1629		lpfc_mbuf_free(phba, bmp->virt, bmp->phys);1630	kfree(bmp);1631send_mgmt_rsp_exit:1632	/* make error code available to userspace */1633	bsg_reply->result = rc;1634	job->dd_data = NULL;1635	return rc;1636}1637 1638/**1639 * lpfc_bsg_diag_mode_enter - process preparing into device diag loopback mode1640 * @phba: Pointer to HBA context object.1641 *1642 * This function is responsible for preparing driver for diag loopback1643 * on device.1644 */1645static int1646lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)1647{1648	struct lpfc_vport **vports;1649	struct Scsi_Host *shost;1650	struct lpfc_sli *psli;1651	struct lpfc_queue *qp = NULL;1652	struct lpfc_sli_ring *pring;1653	int i = 0;1654 1655	psli = &phba->sli;1656	if (!psli)1657		return -ENODEV;1658 1659 1660	if ((phba->link_state == LPFC_HBA_ERROR) ||1661	    (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||1662	    (!(psli->sli_flag & LPFC_SLI_ACTIVE)))1663		return -EACCES;1664 1665	vports = lpfc_create_vport_work_array(phba);1666	if (vports) {1667		for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {1668			shost = lpfc_shost_from_vport(vports[i]);1669			scsi_block_requests(shost);1670		}1671		lpfc_destroy_vport_work_array(phba, vports);1672	} else {1673		shost = lpfc_shost_from_vport(phba->pport);1674		scsi_block_requests(shost);1675	}1676 1677	if (phba->sli_rev != LPFC_SLI_REV4) {1678		pring = &psli->sli3_ring[LPFC_FCP_RING];1679		lpfc_emptyq_wait(phba, &pring->txcmplq, &phba->hbalock);1680		return 0;1681	}1682	list_for_each_entry(qp, &phba->sli4_hba.lpfc_wq_list, wq_list) {1683		pring = qp->pring;1684		if (!pring || (pring->ringno != LPFC_FCP_RING))1685			continue;1686		if (!lpfc_emptyq_wait(phba, &pring->txcmplq,1687				      &pring->ring_lock))1688			break;1689	}1690	return 0;1691}1692 1693/**1694 * lpfc_bsg_diag_mode_exit - exit process from device diag loopback mode1695 * @phba: Pointer to HBA context object.1696 *1697 * This function is responsible for driver exit processing of setting up1698 * diag loopback mode on device.1699 */1700static void1701lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba)1702{1703	struct Scsi_Host *shost;1704	struct lpfc_vport **vports;1705	int i;1706 1707	vports = lpfc_create_vport_work_array(phba);1708	if (vports) {1709		for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {1710			shost = lpfc_shost_from_vport(vports[i]);1711			scsi_unblock_requests(shost);1712		}1713		lpfc_destroy_vport_work_array(phba, vports);1714	} else {1715		shost = lpfc_shost_from_vport(phba->pport);1716		scsi_unblock_requests(shost);1717	}1718	return;1719}1720 1721/**1722 * lpfc_sli3_bsg_diag_loopback_mode - process an sli3 bsg vendor command1723 * @phba: Pointer to HBA context object.1724 * @job: LPFC_BSG_VENDOR_DIAG_MODE1725 *1726 * This function is responsible for placing an sli3  port into diagnostic1727 * loopback mode in order to perform a diagnostic loopback test.1728 * All new scsi requests are blocked, a small delay is used to allow the1729 * scsi requests to complete then the link is brought down. If the link is1730 * is placed in loopback mode then scsi requests are again allowed1731 * so the scsi mid-layer doesn't give up on the port.1732 * All of this is done in-line.1733 */1734static int1735lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct bsg_job *job)1736{1737	struct fc_bsg_request *bsg_request = job->request;1738	struct fc_bsg_reply *bsg_reply = job->reply;1739	struct diag_mode_set *loopback_mode;1740	uint32_t link_flags;1741	uint32_t timeout;1742	LPFC_MBOXQ_t *pmboxq  = NULL;1743	int mbxstatus = MBX_SUCCESS;1744	int i = 0;1745	int rc = 0;1746 1747	/* no data to return just the return code */1748	bsg_reply->reply_payload_rcv_len = 0;1749 1750	if (job->request_len < sizeof(struct fc_bsg_request) +1751	    sizeof(struct diag_mode_set)) {1752		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1753				"2738 Received DIAG MODE request size:%d "1754				"below the minimum size:%d\n",1755				job->request_len,1756				(int)(sizeof(struct fc_bsg_request) +1757				sizeof(struct diag_mode_set)));1758		rc = -EINVAL;1759		goto job_error;1760	}1761 1762	rc = lpfc_bsg_diag_mode_enter(phba);1763	if (rc)1764		goto job_error;1765 1766	/* bring the link to diagnostic mode */1767	loopback_mode = (struct diag_mode_set *)1768		bsg_request->rqst_data.h_vendor.vendor_cmd;1769	link_flags = loopback_mode->type;1770	timeout = loopback_mode->timeout * 100;1771 1772	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);1773	if (!pmboxq) {1774		rc = -ENOMEM;1775		goto loopback_mode_exit;1776	}1777	memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t));1778	pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK;1779	pmboxq->u.mb.mbxOwner = OWN_HOST;1780 1781	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);1782 1783	if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0)) {1784		/* wait for link down before proceeding */1785		i = 0;1786		while (phba->link_state != LPFC_LINK_DOWN) {1787			if (i++ > timeout) {1788				rc = -ETIMEDOUT;1789				goto loopback_mode_exit;1790			}1791			msleep(10);1792		}1793 1794		memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t));1795		if (link_flags == INTERNAL_LOOP_BACK)1796			pmboxq->u.mb.un.varInitLnk.link_flags = FLAGS_LOCAL_LB;1797		else1798			pmboxq->u.mb.un.varInitLnk.link_flags =1799				FLAGS_TOPOLOGY_MODE_LOOP;1800 1801		pmboxq->u.mb.mbxCommand = MBX_INIT_LINK;1802		pmboxq->u.mb.mbxOwner = OWN_HOST;1803 1804		mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,1805						     LPFC_MBOX_TMO);1806 1807		if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus))1808			rc = -ENODEV;1809		else {1810			spin_lock_irq(&phba->hbalock);1811			phba->link_flag |= LS_LOOPBACK_MODE;1812			spin_unlock_irq(&phba->hbalock);1813			/* wait for the link attention interrupt */1814			msleep(100);1815 1816			i = 0;1817			while (phba->link_state != LPFC_HBA_READY) {1818				if (i++ > timeout) {1819					rc = -ETIMEDOUT;1820					break;1821				}1822 1823				msleep(10);1824			}1825		}1826 1827	} else1828		rc = -ENODEV;1829 1830loopback_mode_exit:1831	lpfc_bsg_diag_mode_exit(phba);1832 1833	/*1834	 * Let SLI layer release mboxq if mbox command completed after timeout.1835	 */1836	if (pmboxq && mbxstatus != MBX_TIMEOUT)1837		mempool_free(pmboxq, phba->mbox_mem_pool);1838 1839job_error:1840	/* make error code available to userspace */1841	bsg_reply->result = rc;1842	/* complete the job back to userspace if no error */1843	if (rc == 0)1844		bsg_job_done(job, bsg_reply->result,1845			       bsg_reply->reply_payload_rcv_len);1846	return rc;1847}1848 1849/**1850 * lpfc_sli4_bsg_set_link_diag_state - set sli4 link diag state1851 * @phba: Pointer to HBA context object.1852 * @diag: Flag for set link to diag or nomral operation state.1853 *1854 * This function is responsible for issuing a sli4 mailbox command for setting1855 * link to either diag state or normal operation state.1856 */1857static int1858lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag)1859{1860	LPFC_MBOXQ_t *pmboxq;1861	struct lpfc_mbx_set_link_diag_state *link_diag_state;1862	uint32_t req_len, alloc_len;1863	int mbxstatus = MBX_SUCCESS, rc;1864 1865	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);1866	if (!pmboxq)1867		return -ENOMEM;1868 1869	req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) -1870		   sizeof(struct lpfc_sli4_cfg_mhdr));1871	alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,1872				LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,1873				req_len, LPFC_SLI4_MBX_EMBED);1874	if (alloc_len != req_len) {1875		rc = -ENOMEM;1876		goto link_diag_state_set_out;1877	}1878	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,1879			"3128 Set link to diagnostic state:x%x (x%x/x%x)\n",1880			diag, phba->sli4_hba.lnk_info.lnk_tp,1881			phba->sli4_hba.lnk_info.lnk_no);1882 1883	link_diag_state = &pmboxq->u.mqe.un.link_diag_state;1884	bf_set(lpfc_mbx_set_diag_state_diag_bit_valid, &link_diag_state->u.req,1885	       LPFC_DIAG_STATE_DIAG_BIT_VALID_CHANGE);1886	bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req,1887	       phba->sli4_hba.lnk_info.lnk_no);1888	bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req,1889	       phba->sli4_hba.lnk_info.lnk_tp);1890	if (diag)1891		bf_set(lpfc_mbx_set_diag_state_diag,1892		       &link_diag_state->u.req, 1);1893	else1894		bf_set(lpfc_mbx_set_diag_state_diag,1895		       &link_diag_state->u.req, 0);1896 1897	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);1898 1899	if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0))1900		rc = 0;1901	else1902		rc = -ENODEV;1903 1904link_diag_state_set_out:1905	if (pmboxq && (mbxstatus != MBX_TIMEOUT))1906		mempool_free(pmboxq, phba->mbox_mem_pool);1907 1908	return rc;1909}1910 1911/**1912 * lpfc_sli4_bsg_set_loopback_mode - set sli4 internal loopback diagnostic1913 * @phba: Pointer to HBA context object.1914 * @mode: loopback mode to set1915 * @link_no: link number for loopback mode to set1916 *1917 * This function is responsible for issuing a sli4 mailbox command for setting1918 * up loopback diagnostic for a link.1919 */1920static int1921lpfc_sli4_bsg_set_loopback_mode(struct lpfc_hba *phba, int mode,1922				uint32_t link_no)1923{1924	LPFC_MBOXQ_t *pmboxq;1925	uint32_t req_len, alloc_len;1926	struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;1927	int mbxstatus = MBX_SUCCESS, rc = 0;1928 1929	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);1930	if (!pmboxq)1931		return -ENOMEM;1932	req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) -1933		   sizeof(struct lpfc_sli4_cfg_mhdr));1934	alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,1935				LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK,1936				req_len, LPFC_SLI4_MBX_EMBED);1937	if (alloc_len != req_len) {1938		mempool_free(pmboxq, phba->mbox_mem_pool);1939		return -ENOMEM;1940	}1941	link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback;1942	bf_set(lpfc_mbx_set_diag_state_link_num,1943	       &link_diag_loopback->u.req, link_no);1944 1945	if (phba->sli4_hba.conf_trunk & (1 << link_no)) {1946		bf_set(lpfc_mbx_set_diag_state_link_type,1947		       &link_diag_loopback->u.req, LPFC_LNK_FC_TRUNKED);1948	} else {1949		bf_set(lpfc_mbx_set_diag_state_link_type,1950		       &link_diag_loopback->u.req,1951		       phba->sli4_hba.lnk_info.lnk_tp);1952	}1953 1954	bf_set(lpfc_mbx_set_diag_lpbk_type, &link_diag_loopback->u.req,1955	       mode);1956 1957	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);1958	if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) {1959		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1960				"3127 Failed setup loopback mode mailbox "1961				"command, rc:x%x, status:x%x\n", mbxstatus,1962				pmboxq->u.mb.mbxStatus);1963		rc = -ENODEV;1964	}1965	if (pmboxq && (mbxstatus != MBX_TIMEOUT))1966		mempool_free(pmboxq, phba->mbox_mem_pool);1967	return rc;1968}1969 1970/**1971 * lpfc_sli4_diag_fcport_reg_setup - setup port registrations for diagnostic1972 * @phba: Pointer to HBA context object.1973 *1974 * This function set up SLI4 FC port registrations for diagnostic run, which1975 * includes all the rpis, vfi, and also vpi.1976 */1977static int1978lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba)1979{1980	if (test_bit(FC_VFI_REGISTERED, &phba->pport->fc_flag)) {1981		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,1982				"3136 Port still had vfi registered: "1983				"mydid:x%x, fcfi:%d, vfi:%d, vpi:%d\n",1984				phba->pport->fc_myDID, phba->fcf.fcfi,1985				phba->sli4_hba.vfi_ids[phba->pport->vfi],1986				phba->vpi_ids[phba->pport->vpi]);1987		return -EINVAL;1988	}1989	return lpfc_issue_reg_vfi(phba->pport);1990}1991 1992/**1993 * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command1994 * @phba: Pointer to HBA context object.1995 * @job: LPFC_BSG_VENDOR_DIAG_MODE1996 *1997 * This function is responsible for placing an sli4 port into diagnostic1998 * loopback mode in order to perform a diagnostic loopback test.1999 */2000static int2001lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct bsg_job *job)2002{2003	struct fc_bsg_request *bsg_request = job->request;2004	struct fc_bsg_reply *bsg_reply = job->reply;2005	struct diag_mode_set *loopback_mode;2006	uint32_t link_flags, timeout, link_no;2007	int i, rc = 0;2008 2009	/* no data to return just the return code */2010	bsg_reply->reply_payload_rcv_len = 0;2011 2012	if (job->request_len < sizeof(struct fc_bsg_request) +2013	    sizeof(struct diag_mode_set)) {2014		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,2015				"3011 Received DIAG MODE request size:%d "2016				"below the minimum size:%d\n",2017				job->request_len,2018				(int)(sizeof(struct fc_bsg_request) +2019				sizeof(struct diag_mode_set)));2020		rc = -EINVAL;2021		goto job_done;2022	}2023 2024	loopback_mode = (struct diag_mode_set *)2025		bsg_request->rqst_data.h_vendor.vendor_cmd;2026	link_flags = loopback_mode->type;2027	timeout = loopback_mode->timeout * 100;2028 2029	if (loopback_mode->physical_link == -1)2030		link_no = phba->sli4_hba.lnk_info.lnk_no;2031	else2032		link_no = loopback_mode->physical_link;2033 2034	if (link_flags == DISABLE_LOOP_BACK) {2035		rc = lpfc_sli4_bsg_set_loopback_mode(phba,2036					LPFC_DIAG_LOOPBACK_TYPE_DISABLE,2037					link_no);2038		if (!rc) {2039			/* Unset the need disable bit */2040			phba->sli4_hba.conf_trunk &= ~((1 << link_no) << 4);2041		}2042		goto job_done;2043	} else {2044		/* Check if we need to disable the loopback state */2045		if (phba->sli4_hba.conf_trunk & ((1 << link_no) << 4)) {2046			rc = -EPERM;2047			goto job_done;2048		}2049	}2050 2051	rc = lpfc_bsg_diag_mode_enter(phba);2052	if (rc)2053		goto job_done;2054 2055	/* indicate we are in loobpack diagnostic mode */2056	spin_lock_irq(&phba->hbalock);2057	phba->link_flag |= LS_LOOPBACK_MODE;2058	spin_unlock_irq(&phba->hbalock);2059 2060	/* reset port to start frome scratch */2061	rc = lpfc_selective_reset(phba);2062	if (rc)2063		goto job_done;2064 2065	/* bring the link to diagnostic mode */2066	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,2067			"3129 Bring link to diagnostic state.\n");2068 2069	rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);2070	if (rc) {2071		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,2072				"3130 Failed to bring link to diagnostic "2073				"state, rc:x%x\n", rc);2074		goto loopback_mode_exit;2075	}2076 2077	/* wait for link down before proceeding */2078	i = 0;2079	while (phba->link_state != LPFC_LINK_DOWN) {2080		if (i++ > timeout) {2081			rc = -ETIMEDOUT;2082			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,2083					"3131 Timeout waiting for link to "2084					"diagnostic mode, timeout:%d ms\n",2085					timeout * 10);2086			goto loopback_mode_exit;2087		}2088		msleep(10);2089	}2090 2091	/* set up loopback mode */2092	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,2093			"3132 Set up loopback mode:x%x\n", link_flags);2094 2095	switch (link_flags) {2096	case INTERNAL_LOOP_BACK:2097		if (phba->sli4_hba.conf_trunk & (1 << link_no)) {2098			rc = lpfc_sli4_bsg_set_loopback_mode(phba,2099					LPFC_DIAG_LOOPBACK_TYPE_INTERNAL,2100					link_no);2101		} else {2102			/* Trunk is configured, but link is not in this trunk */2103			if (phba->sli4_hba.conf_trunk) {2104				rc = -ELNRNG;2105				goto loopback_mode_exit;2106			}2107 2108			rc = lpfc_sli4_bsg_set_loopback_mode(phba,2109					LPFC_DIAG_LOOPBACK_TYPE_INTERNAL,2110					link_no);2111		}2112 2113		if (!rc) {2114			/* Set the need disable bit */2115			phba->sli4_hba.conf_trunk |= (1 << link_no) << 4;2116		}2117 2118		break;2119	case EXTERNAL_LOOP_BACK:2120		if (phba->sli4_hba.conf_trunk & (1 << link_no)) {2121			rc = lpfc_sli4_bsg_set_loopback_mode(phba,2122				LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL_TRUNKED,2123				link_no);2124		} else {2125			/* Trunk is configured, but link is not in this trunk */2126			if (phba->sli4_hba.conf_trunk) {2127				rc = -ELNRNG;2128				goto loopback_mode_exit;2129			}2130 2131			rc = lpfc_sli4_bsg_set_loopback_mode(phba,2132						LPFC_DIAG_LOOPBACK_TYPE_SERDES,2133						link_no);2134		}2135 2136		if (!rc) {2137			/* Set the need disable bit */2138			phba->sli4_hba.conf_trunk |= (1 << link_no) << 4;2139		}2140 2141		break;2142	default:2143		rc = -EINVAL;2144		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,2145				"3141 Loopback mode:x%x not supported\n",2146				link_flags);2147		goto loopback_mode_exit;2148	}2149 2150	if (!rc) {2151		/* wait for the link attention interrupt */2152		msleep(100);2153		i = 0;2154		while (phba->link_state < LPFC_LINK_UP) {2155			if (i++ > timeout) {2156				rc = -ETIMEDOUT;2157				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,2158					"3137 Timeout waiting for link up "2159					"in loopback mode, timeout:%d ms\n",2160					timeout * 10);2161				break;2162			}2163			msleep(10);2164		}2165	}2166 2167	/* port resource registration setup for loopback diagnostic */2168	if (!rc) {2169		/* set up a none zero myDID for loopback test */2170		phba->pport->fc_myDID = 1;2171		rc = lpfc_sli4_diag_fcport_reg_setup(phba);2172	} else2173		goto loopback_mode_exit;2174 2175	if (!rc) {2176		/* wait for the port ready */2177		msleep(100);2178		i = 0;2179		while (phba->link_state != LPFC_HBA_READY) {2180			if (i++ > timeout) {2181				rc = -ETIMEDOUT;2182				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,2183					"3133 Timeout waiting for port "2184					"loopback mode ready, timeout:%d ms\n",2185					timeout * 10);2186				break;2187			}2188			msleep(10);2189		}2190	}2191 2192loopback_mode_exit:2193	/* clear loopback diagnostic mode */2194	if (rc) {2195		spin_lock_irq(&phba->hbalock);2196		phba->link_flag &= ~LS_LOOPBACK_MODE;2197		spin_unlock_irq(&phba->hbalock);2198	}2199	lpfc_bsg_diag_mode_exit(phba);2200 2201job_done:2202	/* make error code available to userspace */2203	bsg_reply->result = rc;2204	/* complete the job back to userspace if no error */2205	if (rc == 0)2206		bsg_job_done(job, bsg_reply->result,2207			       bsg_reply->reply_payload_rcv_len);2208	return rc;2209}2210 2211/**2212 * lpfc_bsg_diag_loopback_mode - bsg vendor command for diag loopback mode2213 * @job: LPFC_BSG_VENDOR_DIAG_MODE2214 *2215 * This function is responsible for responding to check and dispatch bsg diag2216 * command from the user to proper driver action routines.2217 */2218static int2219lpfc_bsg_diag_loopback_mode(struct bsg_job *job)2220{2221	struct Scsi_Host *shost;2222	struct lpfc_vport *vport;2223	struct lpfc_hba *phba;2224	int rc;2225 2226	shost = fc_bsg_to_shost(job);2227	if (!shost)2228		return -ENODEV;2229	vport = shost_priv(shost);2230	if (!vport)2231		return -ENODEV;2232	phba = vport->phba;2233	if (!phba)2234		return -ENODEV;2235 2236	if (phba->sli_rev < LPFC_SLI_REV4)2237		rc = lpfc_sli3_bsg_diag_loopback_mode(phba, job);2238	else if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=2239		 LPFC_SLI_INTF_IF_TYPE_2)2240		rc = lpfc_sli4_bsg_diag_loopback_mode(phba, job);2241	else2242		rc = -ENODEV;2243 2244	return rc;2245}2246 2247/**2248 * lpfc_sli4_bsg_diag_mode_end - sli4 bsg vendor command for ending diag mode2249 * @job: LPFC_BSG_VENDOR_DIAG_MODE_END2250 *2251 * This function is responsible for responding to check and dispatch bsg diag2252 * command from the user to proper driver action routines.2253 */2254static int2255lpfc_sli4_bsg_diag_mode_end(struct bsg_job *job)2256{2257	struct fc_bsg_request *bsg_request = job->request;2258	struct fc_bsg_reply *bsg_reply = job->reply;2259	struct Scsi_Host *shost;2260	struct lpfc_vport *vport;2261	struct lpfc_hba *phba;2262	struct diag_mode_set *loopback_mode_end_cmd;2263	uint32_t timeout;2264	int rc, i;2265 2266	shost = fc_bsg_to_shost(job);2267	if (!shost)2268		return -ENODEV;2269	vport = shost_priv(shost);2270	if (!vport)2271		return -ENODEV;2272	phba = vport->phba;2273	if (!phba)2274		return -ENODEV;2275 2276	if (phba->sli_rev < LPFC_SLI_REV4)2277		return -ENODEV;2278	if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <2279	    LPFC_SLI_INTF_IF_TYPE_2)2280		return -ENODEV;2281 2282	/* clear loopback diagnostic mode */2283	spin_lock_irq(&phba->hbalock);2284	phba->link_flag &= ~LS_LOOPBACK_MODE;2285	spin_unlock_irq(&phba->hbalock);2286	loopback_mode_end_cmd = (struct diag_mode_set *)2287			bsg_request->rqst_data.h_vendor.vendor_cmd;2288	timeout = loopback_mode_end_cmd->timeout * 100;2289 2290	rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);2291	if (rc) {2292		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,2293				"3139 Failed to bring link to diagnostic "2294				"state, rc:x%x\n", rc);2295		goto loopback_mode_end_exit;2296	}2297 2298	/* wait for link down before proceeding */2299	i = 0;2300	while (phba->link_state != LPFC_LINK_DOWN) {2301		if (i++ > timeout) {2302			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,2303					"3140 Timeout waiting for link to "2304					"diagnostic mode_end, timeout:%d ms\n",2305					timeout * 10);2306			/* there is nothing much we can do here */2307			break;2308		}2309		msleep(10);2310	}2311 2312	/* reset port resource registrations */2313	rc = lpfc_selective_reset(phba);2314	phba->pport->fc_myDID = 0;2315 2316loopback_mode_end_exit:2317	/* make return code available to userspace */2318	bsg_reply->result = rc;2319	/* complete the job back to userspace if no error */2320	if (rc == 0)2321		bsg_job_done(job, bsg_reply->result,2322			       bsg_reply->reply_payload_rcv_len);2323	return rc;2324}2325 2326/**2327 * lpfc_sli4_bsg_link_diag_test - sli4 bsg vendor command for diag link test2328 * @job: LPFC_BSG_VENDOR_DIAG_LINK_TEST2329 *2330 * This function is to perform SLI4 diag link test request from the user2331 * applicaiton.2332 */2333static int2334lpfc_sli4_bsg_link_diag_test(struct bsg_job *job)2335{2336	struct fc_bsg_request *bsg_request = job->request;2337	struct fc_bsg_reply *bsg_reply = job->reply;2338	struct Scsi_Host *shost;2339	struct lpfc_vport *vport;2340	struct lpfc_hba *phba;2341	LPFC_MBOXQ_t *pmboxq;2342	struct sli4_link_diag *link_diag_test_cmd;2343	uint32_t req_len, alloc_len;2344	struct lpfc_mbx_run_link_diag_test *run_link_diag_test;2345	union lpfc_sli4_cfg_shdr *shdr;2346	uint32_t shdr_status, shdr_add_status;2347	struct diag_status *diag_status_reply;2348	int mbxstatus, rc = -ENODEV, rc1 = 0;2349 2350	shost = fc_bsg_to_shost(job);2351	if (!shost)2352		goto job_error;2353 2354	vport = shost_priv(shost);2355	if (!vport)2356		goto job_error;2357 2358	phba = vport->phba;2359	if (!phba)2360		goto job_error;2361 2362 2363	if (phba->sli_rev < LPFC_SLI_REV4)2364		goto job_error;2365 2366	if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <2367	    LPFC_SLI_INTF_IF_TYPE_2)2368		goto job_error;2369 2370	if (job->request_len < sizeof(struct fc_bsg_request) +2371	    sizeof(struct sli4_link_diag)) {2372		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,2373				"3013 Received LINK DIAG TEST request "2374				" size:%d below the minimum size:%d\n",2375				job->request_len,2376				(int)(sizeof(struct fc_bsg_request) +2377				sizeof(struct sli4_link_diag)));2378		rc = -EINVAL;2379		goto job_error;2380	}2381 2382	rc = lpfc_bsg_diag_mode_enter(phba);2383	if (rc)2384		goto job_error;2385 2386	link_diag_test_cmd = (struct sli4_link_diag *)2387			 bsg_request->rqst_data.h_vendor.vendor_cmd;2388 2389	rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);2390 2391	if (rc)2392		goto job_error;2393 2394	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);2395	if (!pmboxq) {2396		rc = -ENOMEM;2397		goto link_diag_test_exit;2398	}2399 2400	req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) -2401		   sizeof(struct lpfc_sli4_cfg_mhdr));2402	alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,2403				     LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,2404				     req_len, LPFC_SLI4_MBX_EMBED);2405	if (alloc_len != req_len) {2406		rc = -ENOMEM;2407		goto link_diag_test_exit;2408	}2409 2410	run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test;2411	bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req,2412	       phba->sli4_hba.lnk_info.lnk_no);2413	bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req,2414	       phba->sli4_hba.lnk_info.lnk_tp);2415	bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req,2416	       link_diag_test_cmd->test_id);2417	bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req,2418	       link_diag_test_cmd->loops);2419	bf_set(lpfc_mbx_run_diag_test_test_ver, &run_link_diag_test->u.req,2420	       link_diag_test_cmd->test_version);2421	bf_set(lpfc_mbx_run_diag_test_err_act, &run_link_diag_test->u.req,2422	       link_diag_test_cmd->error_action);2423 2424	mbxstatus = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);2425 2426	shdr = (union lpfc_sli4_cfg_shdr *)2427		&pmboxq->u.mqe.un.sli4_config.header.cfg_shdr;2428	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);2429	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);2430	if (shdr_status || shdr_add_status || mbxstatus) {2431		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,2432				"3010 Run link diag test mailbox failed with "2433				"mbx_status x%x status x%x, add_status x%x\n",2434				mbxstatus, shdr_status, shdr_add_status);2435	}2436 2437	diag_status_reply = (struct diag_status *)2438			    bsg_reply->reply_data.vendor_reply.vendor_rsp;2439 2440	if (job->reply_len < sizeof(*bsg_reply) + sizeof(*diag_status_reply)) {2441		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,2442				"3012 Received Run link diag test reply "2443				"below minimum size (%d): reply_len:%d\n",2444				(int)(sizeof(*bsg_reply) +2445				sizeof(*diag_status_reply)),2446				job->reply_len);2447		rc = -EINVAL;2448		goto job_error;2449	}2450 2451	diag_status_reply->mbox_status = mbxstatus;2452	diag_status_reply->shdr_status = shdr_status;2453	diag_status_reply->shdr_add_status = shdr_add_status;2454 2455link_diag_test_exit:2456	rc1 = lpfc_sli4_bsg_set_link_diag_state(phba, 0);2457 2458	if (pmboxq)2459		mempool_free(pmboxq, phba->mbox_mem_pool);2460 2461	lpfc_bsg_diag_mode_exit(phba);2462 2463job_error:2464	/* make error code available to userspace */2465	if (rc1 && !rc)2466		rc = rc1;2467	bsg_reply->result = rc;2468	/* complete the job back to userspace if no error */2469	if (rc == 0)2470		bsg_job_done(job, bsg_reply->result,2471			       bsg_reply->reply_payload_rcv_len);2472	return rc;2473}2474 2475/**2476 * lpfcdiag_loop_self_reg - obtains a remote port login id2477 * @phba: Pointer to HBA context object2478 * @rpi: Pointer to a remote port login id2479 *2480 * This function obtains a remote port login id so the diag loopback test2481 * can send and receive its own unsolicited CT command.2482 **/2483static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi)2484{2485	LPFC_MBOXQ_t *mbox;2486	struct lpfc_dmabuf *dmabuff;2487	int status;2488 2489	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);2490	if (!mbox)2491		return -ENOMEM;2492 2493	if (phba->sli_rev < LPFC_SLI_REV4)2494		status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,2495				(uint8_t *)&phba->pport->fc_sparam,2496				mbox, *rpi);2497	else {2498		*rpi = lpfc_sli4_alloc_rpi(phba);2499		if (*rpi == LPFC_RPI_ALLOC_ERROR) {2500			mempool_free(mbox, phba->mbox_mem_pool);2501			return -EBUSY;2502		}2503		status = lpfc_reg_rpi(phba, phba->pport->vpi,2504				phba->pport->fc_myDID,2505				(uint8_t *)&phba->pport->fc_sparam,2506				mbox, *rpi);2507	}2508 2509	if (status) {2510		mempool_free(mbox, phba->mbox_mem_pool);2511		if (phba->sli_rev == LPFC_SLI_REV4)2512			lpfc_sli4_free_rpi(phba, *rpi);2513		return -ENOMEM;2514	}2515 2516	dmabuff = mbox->ctx_buf;2517	mbox->ctx_buf = NULL;2518	mbox->ctx_ndlp = NULL;2519	status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);2520 2521	if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {2522		lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys);2523		kfree(dmabuff);2524		if (status != MBX_TIMEOUT)2525			mempool_free(mbox, phba->mbox_mem_pool);2526		if (phba->sli_rev == LPFC_SLI_REV4)2527			lpfc_sli4_free_rpi(phba, *rpi);2528		return -ENODEV;2529	}2530 2531	if (phba->sli_rev < LPFC_SLI_REV4)2532		*rpi = mbox->u.mb.un.varWords[0];2533 2534	lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys);2535	kfree(dmabuff);2536	mempool_free(mbox, phba->mbox_mem_pool);2537	return 0;2538}2539 2540/**2541 * lpfcdiag_loop_self_unreg - unregs from the rpi2542 * @phba: Pointer to HBA context object2543 * @rpi: Remote port login id2544 *2545 * This function unregisters the rpi obtained in lpfcdiag_loop_self_reg2546 **/2547static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi)2548{2549	LPFC_MBOXQ_t *mbox;2550	int status;2551 2552	/* Allocate mboxq structure */2553	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);2554	if (mbox == NULL)2555		return -ENOMEM;2556 2557	if (phba->sli_rev < LPFC_SLI_REV4)2558		lpfc_unreg_login(phba, 0, rpi, mbox);2559	else2560		lpfc_unreg_login(phba, phba->pport->vpi,2561				 phba->sli4_hba.rpi_ids[rpi], mbox);2562 2563	status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);2564 2565	if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {2566		if (status != MBX_TIMEOUT)2567			mempool_free(mbox, phba->mbox_mem_pool);2568		return -EIO;2569	}2570	mempool_free(mbox, phba->mbox_mem_pool);2571	if (phba->sli_rev == LPFC_SLI_REV4)2572		lpfc_sli4_free_rpi(phba, rpi);2573	return 0;2574}2575 2576/**2577 * lpfcdiag_loop_get_xri - obtains the transmit and receive ids2578 * @phba: Pointer to HBA context object2579 * @rpi: Remote port login id2580 * @txxri: Pointer to transmit exchange id2581 * @rxxri: Pointer to response exchabge id2582 *2583 * This function obtains the transmit and receive ids required to send2584 * an unsolicited ct command with a payload. A special lpfc FsType and CmdRsp2585 * flags are used to the unsolicited response handler is able to process2586 * the ct command sent on the same port.2587 **/2588static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,2589			 uint16_t *txxri, uint16_t * rxxri)2590{2591	struct lpfc_bsg_event *evt;2592	struct lpfc_iocbq *cmdiocbq, *rspiocbq;2593	struct lpfc_dmabuf *dmabuf;2594	struct ulp_bde64 *bpl = NULL;2595	struct lpfc_sli_ct_request *ctreq = NULL;2596	int ret_val = 0;2597	int time_left;2598	int iocb_stat = IOCB_SUCCESS;2599	unsigned long flags;2600	u32 status;2601 2602	*txxri = 0;2603	*rxxri = 0;2604	evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,2605				SLI_CT_ELX_LOOPBACK);2606	if (!evt)2607		return -ENOMEM;2608 2609	spin_lock_irqsave(&phba->ct_ev_lock, flags);2610	list_add(&evt->node, &phba->ct_ev_waiters);2611	lpfc_bsg_event_ref(evt);2612	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);2613 2614	cmdiocbq = lpfc_sli_get_iocbq(phba);2615	rspiocbq = lpfc_sli_get_iocbq(phba);2616 2617	dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);2618	if (dmabuf) {2619		dmabuf->virt = lpfc_mbuf_alloc(phba, 0, &dmabuf->phys);2620		if (dmabuf->virt) {2621			INIT_LIST_HEAD(&dmabuf->list);2622			bpl = (struct ulp_bde64 *) dmabuf->virt;2623			memset(bpl, 0, sizeof(*bpl));2624			ctreq = (struct lpfc_sli_ct_request *)(bpl + 1);2625			bpl->addrHigh =2626				le32_to_cpu(putPaddrHigh(dmabuf->phys +2627					sizeof(*bpl)));2628			bpl->addrLow =2629				le32_to_cpu(putPaddrLow(dmabuf->phys +2630					sizeof(*bpl)));2631			bpl->tus.f.bdeFlags = 0;2632			bpl->tus.f.bdeSize = ELX_LOOPBACK_HEADER_SZ;2633			bpl->tus.w = le32_to_cpu(bpl->tus.w);2634		}2635	}2636 2637	if (cmdiocbq == NULL || rspiocbq == NULL ||2638	    dmabuf == NULL || bpl == NULL || ctreq == NULL ||2639		dmabuf->virt == NULL) {2640		ret_val = -ENOMEM;2641		goto err_get_xri_exit;2642	}2643 2644	memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ);2645 2646	ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;2647	ctreq->RevisionId.bits.InId = 0;2648	ctreq->FsType = SLI_CT_ELX_LOOPBACK;2649	ctreq->FsSubType = 0;2650	ctreq->CommandResponse.bits.CmdRsp = ELX_LOOPBACK_XRI_SETUP;2651	ctreq->CommandResponse.bits.Size = 0;2652 2653	cmdiocbq->bpl_dmabuf = dmabuf;2654	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;2655	cmdiocbq->vport = phba->pport;2656	cmdiocbq->cmd_cmpl = NULL;2657 2658	lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, dmabuf, rpi, 0, 1,2659				 FC_RCTL_DD_SOL_CTL, 0, CMD_XMIT_SEQUENCE64_CR);2660 2661	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,2662					     rspiocbq, (phba->fc_ratov * 2)2663					     + LPFC_DRVR_TIMEOUT);2664 2665	status = get_job_ulpstatus(phba, rspiocbq);2666	if (iocb_stat != IOCB_SUCCESS || status != IOCB_SUCCESS) {2667		ret_val = -EIO;2668		goto err_get_xri_exit;2669	}2670	*txxri = get_job_ulpcontext(phba, rspiocbq);2671 2672	evt->waiting = 1;2673	evt->wait_time_stamp = jiffies;2674	time_left = wait_event_interruptible_timeout(2675		evt->wq, !list_empty(&evt->events_to_see),2676		msecs_to_jiffies(1000 *2677			((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));2678	if (list_empty(&evt->events_to_see))2679		ret_val = (time_left) ? -EINTR : -ETIMEDOUT;2680	else {2681		spin_lock_irqsave(&phba->ct_ev_lock, flags);2682		list_move(evt->events_to_see.prev, &evt->events_to_get);2683		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);2684		*rxxri = (list_entry(evt->events_to_get.prev,2685				     typeof(struct event_data),2686				     node))->immed_dat;2687	}2688	evt->waiting = 0;2689 2690err_get_xri_exit:2691	spin_lock_irqsave(&phba->ct_ev_lock, flags);2692	lpfc_bsg_event_unref(evt); /* release ref */2693	lpfc_bsg_event_unref(evt); /* delete */2694	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);2695 2696	if (dmabuf) {2697		if (dmabuf->virt)2698			lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);2699		kfree(dmabuf);2700	}2701 2702	if (cmdiocbq && (iocb_stat != IOCB_TIMEDOUT))2703		lpfc_sli_release_iocbq(phba, cmdiocbq);2704	if (rspiocbq)2705		lpfc_sli_release_iocbq(phba, rspiocbq);2706	return ret_val;2707}2708 2709/**2710 * lpfc_bsg_dma_page_alloc - allocate a bsg mbox page sized dma buffers2711 * @phba: Pointer to HBA context object2712 *2713 * This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and2714 * returns the pointer to the buffer.2715 **/2716static struct lpfc_dmabuf *2717lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba)2718{2719	struct lpfc_dmabuf *dmabuf;2720	struct pci_dev *pcidev = phba->pcidev;2721 2722	/* allocate dma buffer struct */2723	dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);2724	if (!dmabuf)2725		return NULL;2726 2727	INIT_LIST_HEAD(&dmabuf->list);2728 2729	/* now, allocate dma buffer */2730	dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,2731					  &(dmabuf->phys), GFP_KERNEL);2732 2733	if (!dmabuf->virt) {2734		kfree(dmabuf);2735		return NULL;2736	}2737 2738	return dmabuf;2739}2740 2741/**2742 * lpfc_bsg_dma_page_free - free a bsg mbox page sized dma buffer2743 * @phba: Pointer to HBA context object.2744 * @dmabuf: Pointer to the bsg mbox page sized dma buffer descriptor.2745 *2746 * This routine just simply frees a dma buffer and its associated buffer2747 * descriptor referred by @dmabuf.2748 **/2749static void2750lpfc_bsg_dma_page_free(struct lpfc_hba *phba, struct lpfc_dmabuf *dmabuf)2751{2752	struct pci_dev *pcidev = phba->pcidev;2753 2754	if (!dmabuf)2755		return;2756 2757	if (dmabuf->virt)2758		dma_free_coherent(&pcidev->dev, BSG_MBOX_SIZE,2759				  dmabuf->virt, dmabuf->phys);2760	kfree(dmabuf);2761	return;2762}2763 2764/**2765 * lpfc_bsg_dma_page_list_free - free a list of bsg mbox page sized dma buffers2766 * @phba: Pointer to HBA context object.2767 * @dmabuf_list: Pointer to a list of bsg mbox page sized dma buffer descs.2768 *2769 * This routine just simply frees all dma buffers and their associated buffer2770 * descriptors referred by @dmabuf_list.2771 **/2772static void2773lpfc_bsg_dma_page_list_free(struct lpfc_hba *phba,2774			    struct list_head *dmabuf_list)2775{2776	struct lpfc_dmabuf *dmabuf, *next_dmabuf;2777 2778	if (list_empty(dmabuf_list))2779		return;2780 2781	list_for_each_entry_safe(dmabuf, next_dmabuf, dmabuf_list, list) {2782		list_del_init(&dmabuf->list);2783		lpfc_bsg_dma_page_free(phba, dmabuf);2784	}2785	return;2786}2787 2788/**2789 * diag_cmd_data_alloc - fills in a bde struct with dma buffers2790 * @phba: Pointer to HBA context object2791 * @bpl: Pointer to 64 bit bde structure2792 * @size: Number of bytes to process2793 * @nocopydata: Flag to copy user data into the allocated buffer2794 *2795 * This function allocates page size buffers and populates an lpfc_dmabufext.2796 * If allowed the user data pointed to with indataptr is copied into the kernel2797 * memory. The chained list of page size buffers is returned.2798 **/2799static struct lpfc_dmabufext *2800diag_cmd_data_alloc(struct lpfc_hba *phba,2801		   struct ulp_bde64 *bpl, uint32_t size,2802		   int nocopydata)2803{2804	struct lpfc_dmabufext *mlist = NULL;2805	struct lpfc_dmabufext *dmp;2806	int cnt, offset = 0, i = 0;2807	struct pci_dev *pcidev;2808 2809	pcidev = phba->pcidev;2810 2811	while (size) {2812		/* We get chunks of 4K */2813		if (size > BUF_SZ_4K)2814			cnt = BUF_SZ_4K;2815		else2816			cnt = size;2817 2818		/* allocate struct lpfc_dmabufext buffer header */2819		dmp = kmalloc(sizeof(struct lpfc_dmabufext), GFP_KERNEL);2820		if (!dmp)2821			goto out;2822 2823		INIT_LIST_HEAD(&dmp->dma.list);2824 2825		/* Queue it to a linked list */2826		if (mlist)2827			list_add_tail(&dmp->dma.list, &mlist->dma.list);2828		else2829			mlist = dmp;2830 2831		/* allocate buffer */2832		dmp->dma.virt = dma_alloc_coherent(&pcidev->dev,2833						   cnt,2834						   &(dmp->dma.phys),2835						   GFP_KERNEL);2836 2837		if (!dmp->dma.virt)2838			goto out;2839 2840		dmp->size = cnt;2841 2842		if (nocopydata) {2843			bpl->tus.f.bdeFlags = 0;2844		} else {2845			memset((uint8_t *)dmp->dma.virt, 0, cnt);2846			bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;2847		}2848 2849		/* build buffer ptr list for IOCB */2850		bpl->addrLow = le32_to_cpu(putPaddrLow(dmp->dma.phys));2851		bpl->addrHigh = le32_to_cpu(putPaddrHigh(dmp->dma.phys));2852		bpl->tus.f.bdeSize = (ushort) cnt;2853		bpl->tus.w = le32_to_cpu(bpl->tus.w);2854		bpl++;2855 2856		i++;2857		offset += cnt;2858		size -= cnt;2859	}2860 2861	if (mlist) {2862		mlist->flag = i;2863		return mlist;2864	}2865out:2866	diag_cmd_data_free(phba, mlist);2867	return NULL;2868}2869 2870/**2871 * lpfcdiag_sli3_loop_post_rxbufs - post the receive buffers for an unsol CT cmd2872 * @phba: Pointer to HBA context object2873 * @rxxri: Receive exchange id2874 * @len: Number of data bytes2875 *2876 * This function allocates and posts a data buffer of sufficient size to receive2877 * an unsolicited CT command.2878 **/2879static int lpfcdiag_sli3_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,2880					  size_t len)2881{2882	struct lpfc_sli_ring *pring;2883	struct lpfc_iocbq *cmdiocbq;2884	IOCB_t *cmd = NULL;2885	struct list_head head, *curr, *next;2886	struct lpfc_dmabuf *rxbmp;2887	struct lpfc_dmabuf *dmp;2888	struct lpfc_dmabuf *mp[2] = {NULL, NULL};2889	struct ulp_bde64 *rxbpl = NULL;2890	uint32_t num_bde;2891	struct lpfc_dmabufext *rxbuffer = NULL;2892	int ret_val = 0;2893	int iocb_stat;2894	int i = 0;2895 2896	pring = lpfc_phba_elsring(phba);2897 2898	cmdiocbq = lpfc_sli_get_iocbq(phba);2899	rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);2900	if (rxbmp != NULL) {2901		rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);2902		if (rxbmp->virt) {2903			INIT_LIST_HEAD(&rxbmp->list);2904			rxbpl = (struct ulp_bde64 *) rxbmp->virt;2905			rxbuffer = diag_cmd_data_alloc(phba, rxbpl, len, 0);2906		}2907	}2908 2909	if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer || !pring) {2910		ret_val = -ENOMEM;2911		goto err_post_rxbufs_exit;2912	}2913 2914	/* Queue buffers for the receive exchange */2915	num_bde = (uint32_t)rxbuffer->flag;2916	dmp = &rxbuffer->dma;2917	cmd = &cmdiocbq->iocb;2918	i = 0;2919 2920	INIT_LIST_HEAD(&head);2921	list_add_tail(&head, &dmp->list);2922	list_for_each_safe(curr, next, &head) {2923		mp[i] = list_entry(curr, struct lpfc_dmabuf, list);2924		list_del(curr);2925 2926		if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {2927			mp[i]->buffer_tag = lpfc_sli_get_buffer_tag(phba);2928			cmd->un.quexri64cx.buff.bde.addrHigh =2929				putPaddrHigh(mp[i]->phys);2930			cmd->un.quexri64cx.buff.bde.addrLow =2931				putPaddrLow(mp[i]->phys);2932			cmd->un.quexri64cx.buff.bde.tus.f.bdeSize =2933				((struct lpfc_dmabufext *)mp[i])->size;2934			cmd->un.quexri64cx.buff.buffer_tag = mp[i]->buffer_tag;2935			cmd->ulpCommand = CMD_QUE_XRI64_CX;2936			cmd->ulpPU = 0;2937			cmd->ulpLe = 1;2938			cmd->ulpBdeCount = 1;2939			cmd->unsli3.que_xri64cx_ext_words.ebde_count = 0;2940 2941		} else {2942			cmd->un.cont64[i].addrHigh = putPaddrHigh(mp[i]->phys);2943			cmd->un.cont64[i].addrLow = putPaddrLow(mp[i]->phys);2944			cmd->un.cont64[i].tus.f.bdeSize =2945				((struct lpfc_dmabufext *)mp[i])->size;2946			cmd->ulpBdeCount = ++i;2947 2948			if ((--num_bde > 0) && (i < 2))2949				continue;2950 2951			cmd->ulpCommand = CMD_QUE_XRI_BUF64_CX;2952			cmd->ulpLe = 1;2953		}2954 2955		cmd->ulpClass = CLASS3;2956		cmd->ulpContext = rxxri;2957 2958		iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,2959						0);2960		if (iocb_stat == IOCB_ERROR) {2961			diag_cmd_data_free(phba,2962				(struct lpfc_dmabufext *)mp[0]);2963			if (mp[1])2964				diag_cmd_data_free(phba,2965					  (struct lpfc_dmabufext *)mp[1]);2966			dmp = list_entry(next, struct lpfc_dmabuf, list);2967			ret_val = -EIO;2968			goto err_post_rxbufs_exit;2969		}2970 2971		lpfc_sli_ringpostbuf_put(phba, pring, mp[0]);2972		if (mp[1]) {2973			lpfc_sli_ringpostbuf_put(phba, pring, mp[1]);2974			mp[1] = NULL;2975		}2976 2977		/* The iocb was freed by lpfc_sli_issue_iocb */2978		cmdiocbq = lpfc_sli_get_iocbq(phba);2979		if (!cmdiocbq) {2980			dmp = list_entry(next, struct lpfc_dmabuf, list);2981			ret_val = -EIO;2982			goto err_post_rxbufs_exit;2983		}2984		cmd = &cmdiocbq->iocb;2985		i = 0;2986	}2987	list_del(&head);2988 2989err_post_rxbufs_exit:2990 2991	if (rxbmp) {2992		if (rxbmp->virt)2993			lpfc_mbuf_free(phba, rxbmp->virt, rxbmp->phys);2994		kfree(rxbmp);2995	}2996 2997	if (cmdiocbq)2998		lpfc_sli_release_iocbq(phba, cmdiocbq);2999	return ret_val;3000}3001 3002/**3003 * lpfc_bsg_diag_loopback_run - run loopback on a port by issue ct cmd to itself3004 * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job3005 *3006 * This function receives a user data buffer to be transmitted and received on3007 * the same port, the link must be up and in loopback mode prior3008 * to being called.3009 * 1. A kernel buffer is allocated to copy the user data into.3010 * 2. The port registers with "itself".3011 * 3. The transmit and receive exchange ids are obtained.3012 * 4. The receive exchange id is posted.3013 * 5. A new els loopback event is created.3014 * 6. The command and response iocbs are allocated.3015 * 7. The cmd iocb FsType is set to elx loopback and the CmdRsp to looppback.3016 *3017 * This function is meant to be called n times while the port is in loopback3018 * so it is the apps responsibility to issue a reset to take the port out3019 * of loopback mode.3020 **/3021static int3022lpfc_bsg_diag_loopback_run(struct bsg_job *job)3023{3024	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));3025	struct fc_bsg_reply *bsg_reply = job->reply;3026	struct lpfc_hba *phba = vport->phba;3027	struct lpfc_bsg_event *evt;3028	struct event_data *evdat;3029	struct lpfc_sli *psli = &phba->sli;3030	uint32_t size;3031	uint32_t full_size;3032	size_t segment_len = 0, segment_offset = 0, current_offset = 0;3033	uint16_t rpi = 0;3034	struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL;3035	union lpfc_wqe128 *cmdwqe, *rspwqe;3036	struct lpfc_sli_ct_request *ctreq;3037	struct lpfc_dmabuf *txbmp;3038	struct ulp_bde64 *txbpl = NULL;3039	struct lpfc_dmabufext *txbuffer = NULL;3040	struct list_head head;3041	struct lpfc_dmabuf  *curr;3042	uint16_t txxri = 0, rxxri;3043	uint32_t num_bde;3044	uint8_t *ptr = NULL, *rx_databuf = NULL;3045	int rc = 0;3046	int time_left;3047	int iocb_stat = IOCB_SUCCESS;3048	unsigned long flags;3049	void *dataout = NULL;3050	uint32_t total_mem;3051 3052	/* in case no data is returned return just the return code */3053	bsg_reply->reply_payload_rcv_len = 0;3054 3055	if (job->request_len <3056	    sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_test)) {3057		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,3058				"2739 Received DIAG TEST request below minimum "3059				"size\n");3060		rc = -EINVAL;3061		goto loopback_test_exit;3062	}3063 3064	if (job->request_payload.payload_len !=3065		job->reply_payload.payload_len) {3066		rc = -EINVAL;3067		goto loopback_test_exit;3068	}3069 3070	if ((phba->link_state == LPFC_HBA_ERROR) ||3071	    (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||3072	    (!(psli->sli_flag & LPFC_SLI_ACTIVE))) {3073		rc = -EACCES;3074		goto loopback_test_exit;3075	}3076 3077	if (!lpfc_is_link_up(phba) || !(phba->link_flag & LS_LOOPBACK_MODE)) {3078		rc = -EACCES;3079		goto loopback_test_exit;3080	}3081 3082	size = job->request_payload.payload_len;3083	full_size = size + ELX_LOOPBACK_HEADER_SZ; /* plus the header */3084 3085	if ((size == 0) || (size > 80 * BUF_SZ_4K)) {3086		rc = -ERANGE;3087		goto loopback_test_exit;3088	}3089 3090	if (full_size >= BUF_SZ_4K) {3091		/*3092		 * Allocate memory for ioctl data. If buffer is bigger than 64k,3093		 * then we allocate 64k and re-use that buffer over and over to3094		 * xfer the whole block. This is because Linux kernel has a3095		 * problem allocating more than 120k of kernel space memory. Saw3096		 * problem with GET_FCPTARGETMAPPING...3097		 */3098		if (size <= (64 * 1024))3099			total_mem = full_size;3100		else3101			total_mem = 64 * 1024;3102	} else3103		/* Allocate memory for ioctl data */3104		total_mem = BUF_SZ_4K;3105 3106	dataout = kmalloc(total_mem, GFP_KERNEL);3107	if (dataout == NULL) {3108		rc = -ENOMEM;3109		goto loopback_test_exit;3110	}3111 3112	ptr = dataout;3113	ptr += ELX_LOOPBACK_HEADER_SZ;3114	sg_copy_to_buffer(job->request_payload.sg_list,3115				job->request_payload.sg_cnt,3116				ptr, size);3117	rc = lpfcdiag_loop_self_reg(phba, &rpi);3118	if (rc)3119		goto loopback_test_exit;3120 3121	if (phba->sli_rev < LPFC_SLI_REV4) {3122		rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);3123		if (rc) {3124			lpfcdiag_loop_self_unreg(phba, rpi);3125			goto loopback_test_exit;3126		}3127 3128		rc = lpfcdiag_sli3_loop_post_rxbufs(phba, rxxri, full_size);3129		if (rc) {3130			lpfcdiag_loop_self_unreg(phba, rpi);3131			goto loopback_test_exit;3132		}3133	}3134	evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,3135				SLI_CT_ELX_LOOPBACK);3136	if (!evt) {3137		lpfcdiag_loop_self_unreg(phba, rpi);3138		rc = -ENOMEM;3139		goto loopback_test_exit;3140	}3141 3142	spin_lock_irqsave(&phba->ct_ev_lock, flags);3143	list_add(&evt->node, &phba->ct_ev_waiters);3144	lpfc_bsg_event_ref(evt);3145	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);3146 3147	cmdiocbq = lpfc_sli_get_iocbq(phba);3148	if (phba->sli_rev < LPFC_SLI_REV4)3149		rspiocbq = lpfc_sli_get_iocbq(phba);3150	txbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);3151 3152	if (txbmp) {3153		txbmp->virt = lpfc_mbuf_alloc(phba, 0, &txbmp->phys);3154		if (txbmp->virt) {3155			INIT_LIST_HEAD(&txbmp->list);3156			txbpl = (struct ulp_bde64 *) txbmp->virt;3157			txbuffer = diag_cmd_data_alloc(phba,3158							txbpl, full_size, 0);3159		}3160	}3161 3162	if (!cmdiocbq || !txbmp || !txbpl || !txbuffer || !txbmp->virt) {3163		rc = -ENOMEM;3164		goto err_loopback_test_exit;3165	}3166	if ((phba->sli_rev < LPFC_SLI_REV4) && !rspiocbq) {3167		rc = -ENOMEM;3168		goto err_loopback_test_exit;3169	}3170 3171	cmdwqe = &cmdiocbq->wqe;3172	memset(cmdwqe, 0, sizeof(*cmdwqe));3173	if (phba->sli_rev < LPFC_SLI_REV4) {3174		rspwqe = &rspiocbq->wqe;3175		memset(rspwqe, 0, sizeof(*rspwqe));3176	}3177 3178	INIT_LIST_HEAD(&head);3179	list_add_tail(&head, &txbuffer->dma.list);3180	list_for_each_entry(curr, &head, list) {3181		segment_len = ((struct lpfc_dmabufext *)curr)->size;3182		if (current_offset == 0) {3183			ctreq = curr->virt;3184			memset(ctreq, 0, ELX_LOOPBACK_HEADER_SZ);3185			ctreq->RevisionId.bits.Revision = SLI_CT_REVISION;3186			ctreq->RevisionId.bits.InId = 0;3187			ctreq->FsType = SLI_CT_ELX_LOOPBACK;3188			ctreq->FsSubType = 0;3189			ctreq->CommandResponse.bits.CmdRsp = cpu_to_be16(ELX_LOOPBACK_DATA);3190			ctreq->CommandResponse.bits.Size   = cpu_to_be16(size);3191			segment_offset = ELX_LOOPBACK_HEADER_SZ;3192		} else3193			segment_offset = 0;3194 3195		BUG_ON(segment_offset >= segment_len);3196		memcpy(curr->virt + segment_offset,3197			ptr + current_offset,3198			segment_len - segment_offset);3199 3200		current_offset += segment_len - segment_offset;3201		BUG_ON(current_offset > size);3202	}3203	list_del(&head);3204 3205	/* Build the XMIT_SEQUENCE iocb */3206	num_bde = (uint32_t)txbuffer->flag;3207 3208	cmdiocbq->num_bdes = num_bde;3209	cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;3210	cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;3211	if (phba->cfg_vmid_app_header)3212		cmdiocbq->cmd_flag |= LPFC_IO_VMID;3213 3214	cmdiocbq->vport = phba->pport;3215	cmdiocbq->cmd_cmpl = NULL;3216	cmdiocbq->bpl_dmabuf = txbmp;3217 3218	if (phba->sli_rev < LPFC_SLI_REV4) {3219		lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp, 0, txxri,3220					 num_bde, FC_RCTL_DD_UNSOL_CTL, 1,3221					 CMD_XMIT_SEQUENCE64_CX);3222 3223	} else {3224		lpfc_sli_prep_xmit_seq64(phba, cmdiocbq, txbmp,3225					 phba->sli4_hba.rpi_ids[rpi], 0xffff,3226					 full_size, FC_RCTL_DD_UNSOL_CTL, 1,3227					 CMD_XMIT_SEQUENCE64_WQE);3228		cmdiocbq->sli4_xritag = NO_XRI;3229	}3230 3231	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,3232					     rspiocbq, (phba->fc_ratov * 2) +3233					     LPFC_DRVR_TIMEOUT);3234	if (iocb_stat != IOCB_SUCCESS ||3235	    (phba->sli_rev < LPFC_SLI_REV4 &&3236	     (get_job_ulpstatus(phba, rspiocbq) != IOSTAT_SUCCESS))) {3237		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3238				"3126 Failed loopback test issue iocb: "3239				"iocb_stat:x%x\n", iocb_stat);3240		rc = -EIO;3241		goto err_loopback_test_exit;3242	}3243 3244	evt->waiting = 1;3245	time_left = wait_event_interruptible_timeout(3246		evt->wq, !list_empty(&evt->events_to_see),3247		msecs_to_jiffies(1000 *3248			((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));3249	evt->waiting = 0;3250	if (list_empty(&evt->events_to_see)) {3251		rc = (time_left) ? -EINTR : -ETIMEDOUT;3252		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3253				"3125 Not receiving unsolicited event, "3254				"rc:x%x\n", rc);3255	} else {3256		spin_lock_irqsave(&phba->ct_ev_lock, flags);3257		list_move(evt->events_to_see.prev, &evt->events_to_get);3258		evdat = list_entry(evt->events_to_get.prev,3259				   typeof(*evdat), node);3260		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);3261		rx_databuf = evdat->data;3262		if (evdat->len != full_size) {3263			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3264				"1603 Loopback test did not receive expected "3265				"data length. actual length 0x%x expected "3266				"length 0x%x\n",3267				evdat->len, full_size);3268			rc = -EIO;3269		} else if (rx_databuf == NULL)3270			rc = -EIO;3271		else {3272			rc = IOCB_SUCCESS;3273			/* skip over elx loopback header */3274			rx_databuf += ELX_LOOPBACK_HEADER_SZ;3275			bsg_reply->reply_payload_rcv_len =3276				sg_copy_from_buffer(job->reply_payload.sg_list,3277						    job->reply_payload.sg_cnt,3278						    rx_databuf, size);3279			bsg_reply->reply_payload_rcv_len = size;3280		}3281	}3282 3283err_loopback_test_exit:3284	lpfcdiag_loop_self_unreg(phba, rpi);3285 3286	spin_lock_irqsave(&phba->ct_ev_lock, flags);3287	lpfc_bsg_event_unref(evt); /* release ref */3288	lpfc_bsg_event_unref(evt); /* delete */3289	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);3290 3291	if ((cmdiocbq != NULL) && (iocb_stat != IOCB_TIMEDOUT))3292		lpfc_sli_release_iocbq(phba, cmdiocbq);3293 3294	if (rspiocbq != NULL)3295		lpfc_sli_release_iocbq(phba, rspiocbq);3296 3297	if (txbmp != NULL) {3298		if (txbpl != NULL) {3299			if (txbuffer != NULL)3300				diag_cmd_data_free(phba, txbuffer);3301			lpfc_mbuf_free(phba, txbmp->virt, txbmp->phys);3302		}3303		kfree(txbmp);3304	}3305 3306loopback_test_exit:3307	kfree(dataout);3308	/* make error code available to userspace */3309	bsg_reply->result = rc;3310	job->dd_data = NULL;3311	/* complete the job back to userspace if no error */3312	if (rc == IOCB_SUCCESS)3313		bsg_job_done(job, bsg_reply->result,3314			       bsg_reply->reply_payload_rcv_len);3315	return rc;3316}3317 3318/**3319 * lpfc_bsg_get_dfc_rev - process a GET_DFC_REV bsg vendor command3320 * @job: GET_DFC_REV fc_bsg_job3321 **/3322static int3323lpfc_bsg_get_dfc_rev(struct bsg_job *job)3324{3325	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));3326	struct fc_bsg_reply *bsg_reply = job->reply;3327	struct lpfc_hba *phba = vport->phba;3328	struct get_mgmt_rev_reply *event_reply;3329	int rc = 0;3330 3331	if (job->request_len <3332	    sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev)) {3333		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,3334				"2740 Received GET_DFC_REV request below "3335				"minimum size\n");3336		rc = -EINVAL;3337		goto job_error;3338	}3339 3340	event_reply = (struct get_mgmt_rev_reply *)3341		bsg_reply->reply_data.vendor_reply.vendor_rsp;3342 3343	if (job->reply_len < sizeof(*bsg_reply) + sizeof(*event_reply)) {3344		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,3345				"2741 Received GET_DFC_REV reply below "3346				"minimum size\n");3347		rc = -EINVAL;3348		goto job_error;3349	}3350 3351	event_reply->info.a_Major = MANAGEMENT_MAJOR_REV;3352	event_reply->info.a_Minor = MANAGEMENT_MINOR_REV;3353job_error:3354	bsg_reply->result = rc;3355	if (rc == 0)3356		bsg_job_done(job, bsg_reply->result,3357			       bsg_reply->reply_payload_rcv_len);3358	return rc;3359}3360 3361/**3362 * lpfc_bsg_issue_mbox_cmpl - lpfc_bsg_issue_mbox mbox completion handler3363 * @phba: Pointer to HBA context object.3364 * @pmboxq: Pointer to mailbox command.3365 *3366 * This is completion handler function for mailbox commands issued from3367 * lpfc_bsg_issue_mbox function. This function is called by the3368 * mailbox event handler function with no lock held. This function3369 * will wake up thread waiting on the wait queue pointed by dd_data3370 * of the mailbox.3371 **/3372static void3373lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)3374{3375	struct bsg_job_data *dd_data;3376	struct fc_bsg_reply *bsg_reply;3377	struct bsg_job *job;3378	uint32_t size;3379	unsigned long flags;3380	uint8_t *pmb, *pmb_buf;3381 3382	dd_data = pmboxq->ctx_u.dd_data;3383 3384	/*3385	 * The outgoing buffer is readily referred from the dma buffer,3386	 * just need to get header part from mailboxq structure.3387	 */3388	pmb = (uint8_t *)&pmboxq->u.mb;3389	pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;3390	memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));3391 3392	/* Determine if job has been aborted */3393 3394	spin_lock_irqsave(&phba->ct_ev_lock, flags);3395	job = dd_data->set_job;3396	if (job) {3397		/* Prevent timeout handling from trying to abort job  */3398		job->dd_data = NULL;3399	}3400	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);3401 3402	/* Copy the mailbox data to the job if it is still active */3403 3404	if (job) {3405		bsg_reply = job->reply;3406		size = job->reply_payload.payload_len;3407		bsg_reply->reply_payload_rcv_len =3408			sg_copy_from_buffer(job->reply_payload.sg_list,3409					    job->reply_payload.sg_cnt,3410					    pmb_buf, size);3411	}3412 3413	dd_data->set_job = NULL;3414	mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);3415	lpfc_bsg_dma_page_free(phba, dd_data->context_un.mbox.dmabuffers);3416	kfree(dd_data);3417 3418	/* Complete the job if the job is still active */3419 3420	if (job) {3421		bsg_reply->result = 0;3422		bsg_job_done(job, bsg_reply->result,3423			       bsg_reply->reply_payload_rcv_len);3424	}3425	return;3426}3427 3428/**3429 * lpfc_bsg_check_cmd_access - test for a supported mailbox command3430 * @phba: Pointer to HBA context object.3431 * @mb: Pointer to a mailbox object.3432 * @vport: Pointer to a vport object.3433 *3434 * Some commands require the port to be offline, some may not be called from3435 * the application.3436 **/3437static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,3438	MAILBOX_t *mb, struct lpfc_vport *vport)3439{3440	/* return negative error values for bsg job */3441	switch (mb->mbxCommand) {3442	/* Offline only */3443	case MBX_INIT_LINK:3444	case MBX_DOWN_LINK:3445	case MBX_CONFIG_LINK:3446	case MBX_CONFIG_RING:3447	case MBX_RESET_RING:3448	case MBX_UNREG_LOGIN:3449	case MBX_CLEAR_LA:3450	case MBX_DUMP_CONTEXT:3451	case MBX_RUN_DIAGS:3452	case MBX_RESTART:3453	case MBX_SET_MASK:3454		if (!test_bit(FC_OFFLINE_MODE, &vport->fc_flag)) {3455			lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,3456				"2743 Command 0x%x is illegal in on-line "3457				"state\n",3458				mb->mbxCommand);3459			return -EPERM;3460		}3461		break;3462	case MBX_WRITE_NV:3463	case MBX_WRITE_VPARMS:3464	case MBX_LOAD_SM:3465	case MBX_READ_NV:3466	case MBX_READ_CONFIG:3467	case MBX_READ_RCONFIG:3468	case MBX_READ_STATUS:3469	case MBX_READ_XRI:3470	case MBX_READ_REV:3471	case MBX_READ_LNK_STAT:3472	case MBX_DUMP_MEMORY:3473	case MBX_DOWN_LOAD:3474	case MBX_UPDATE_CFG:3475	case MBX_KILL_BOARD:3476	case MBX_READ_TOPOLOGY:3477	case MBX_LOAD_AREA:3478	case MBX_LOAD_EXP_ROM:3479	case MBX_BEACON:3480	case MBX_DEL_LD_ENTRY:3481	case MBX_SET_DEBUG:3482	case MBX_WRITE_WWN:3483	case MBX_SLI4_CONFIG:3484	case MBX_READ_EVENT_LOG:3485	case MBX_READ_EVENT_LOG_STATUS:3486	case MBX_WRITE_EVENT_LOG:3487	case MBX_PORT_CAPABILITIES:3488	case MBX_PORT_IOV_CONTROL:3489	case MBX_RUN_BIU_DIAG64:3490		break;3491	case MBX_SET_VARIABLE:3492		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,3493			"1226 mbox: set_variable 0x%x, 0x%x\n",3494			mb->un.varWords[0],3495			mb->un.varWords[1]);3496		break;3497	case MBX_READ_SPARM64:3498	case MBX_REG_LOGIN:3499	case MBX_REG_LOGIN64:3500	case MBX_CONFIG_PORT:3501	case MBX_RUN_BIU_DIAG:3502	default:3503		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,3504			"2742 Unknown Command 0x%x\n",3505			mb->mbxCommand);3506		return -EPERM;3507	}3508 3509	return 0; /* ok */3510}3511 3512/**3513 * lpfc_bsg_mbox_ext_session_reset - clean up context of multi-buffer mbox session3514 * @phba: Pointer to HBA context object.3515 *3516 * This is routine clean up and reset BSG handling of multi-buffer mbox3517 * command session.3518 **/3519static void3520lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba)3521{3522	if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE)3523		return;3524 3525	/* free all memory, including dma buffers */3526	lpfc_bsg_dma_page_list_free(phba,3527				    &phba->mbox_ext_buf_ctx.ext_dmabuf_list);3528	lpfc_bsg_dma_page_free(phba, phba->mbox_ext_buf_ctx.mbx_dmabuf);3529	/* multi-buffer write mailbox command pass-through complete */3530	memset((char *)&phba->mbox_ext_buf_ctx, 0,3531	       sizeof(struct lpfc_mbox_ext_buf_ctx));3532	INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list);3533 3534	return;3535}3536 3537/**3538 * lpfc_bsg_issue_mbox_ext_handle_job - job handler for multi-buffer mbox cmpl3539 * @phba: Pointer to HBA context object.3540 * @pmboxq: Pointer to mailbox command.3541 *3542 * This is routine handles BSG job for mailbox commands completions with3543 * multiple external buffers.3544 **/3545static struct bsg_job *3546lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)3547{3548	struct bsg_job_data *dd_data;3549	struct bsg_job *job;3550	struct fc_bsg_reply *bsg_reply;3551	uint8_t *pmb, *pmb_buf;3552	unsigned long flags;3553	uint32_t size;3554	int rc = 0;3555	struct lpfc_dmabuf *dmabuf;3556	struct lpfc_sli_config_mbox *sli_cfg_mbx;3557	uint8_t *pmbx;3558 3559	dd_data = pmboxq->ctx_u.dd_data;3560 3561	/* Determine if job has been aborted */3562	spin_lock_irqsave(&phba->ct_ev_lock, flags);3563	job = dd_data->set_job;3564	if (job) {3565		bsg_reply = job->reply;3566		/* Prevent timeout handling from trying to abort job  */3567		job->dd_data = NULL;3568	}3569	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);3570 3571	/*3572	 * The outgoing buffer is readily referred from the dma buffer,3573	 * just need to get header part from mailboxq structure.3574	 */3575 3576	pmb = (uint8_t *)&pmboxq->u.mb;3577	pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;3578	/* Copy the byte swapped response mailbox back to the user */3579	memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));3580	/* if there is any non-embedded extended data copy that too */3581	dmabuf = phba->mbox_ext_buf_ctx.mbx_dmabuf;3582	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;3583	if (!bsg_bf_get(lpfc_mbox_hdr_emb,3584	    &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) {3585		pmbx = (uint8_t *)dmabuf->virt;3586		/* byte swap the extended data following the mailbox command */3587		lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)],3588			&pmbx[sizeof(MAILBOX_t)],3589			sli_cfg_mbx->un.sli_config_emb0_subsys.mse[0].buf_len);3590	}3591 3592	/* Complete the job if the job is still active */3593 3594	if (job) {3595		size = job->reply_payload.payload_len;3596		bsg_reply->reply_payload_rcv_len =3597			sg_copy_from_buffer(job->reply_payload.sg_list,3598					    job->reply_payload.sg_cnt,3599					    pmb_buf, size);3600 3601		/* result for successful */3602		bsg_reply->result = 0;3603 3604		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3605				"2937 SLI_CONFIG ext-buffer mailbox command "3606				"(x%x/x%x) complete bsg job done, bsize:%d\n",3607				phba->mbox_ext_buf_ctx.nembType,3608				phba->mbox_ext_buf_ctx.mboxType, size);3609		lpfc_idiag_mbxacc_dump_bsg_mbox(phba,3610					phba->mbox_ext_buf_ctx.nembType,3611					phba->mbox_ext_buf_ctx.mboxType,3612					dma_ebuf, sta_pos_addr,3613					phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);3614	} else {3615		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3616				"2938 SLI_CONFIG ext-buffer mailbox "3617				"command (x%x/x%x) failure, rc:x%x\n",3618				phba->mbox_ext_buf_ctx.nembType,3619				phba->mbox_ext_buf_ctx.mboxType, rc);3620	}3621 3622 3623	/* state change */3624	phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_DONE;3625	kfree(dd_data);3626	return job;3627}3628 3629/**3630 * lpfc_bsg_issue_read_mbox_ext_cmpl - compl handler for multi-buffer read mbox3631 * @phba: Pointer to HBA context object.3632 * @pmboxq: Pointer to mailbox command.3633 *3634 * This is completion handler function for mailbox read commands with multiple3635 * external buffers.3636 **/3637static void3638lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)3639{3640	struct bsg_job *job;3641	struct fc_bsg_reply *bsg_reply;3642 3643	job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);3644 3645	/* handle the BSG job with mailbox command */3646	if (!job)3647		pmboxq->u.mb.mbxStatus = MBXERR_ERROR;3648 3649	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3650			"2939 SLI_CONFIG ext-buffer rd mailbox command "3651			"complete, ctxState:x%x, mbxStatus:x%x\n",3652			phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);3653 3654	if (pmboxq->u.mb.mbxStatus || phba->mbox_ext_buf_ctx.numBuf == 1)3655		lpfc_bsg_mbox_ext_session_reset(phba);3656 3657	/* free base driver mailbox structure memory */3658	mempool_free(pmboxq, phba->mbox_mem_pool);3659 3660	/* if the job is still active, call job done */3661	if (job) {3662		bsg_reply = job->reply;3663		bsg_job_done(job, bsg_reply->result,3664			       bsg_reply->reply_payload_rcv_len);3665	}3666	return;3667}3668 3669/**3670 * lpfc_bsg_issue_write_mbox_ext_cmpl - cmpl handler for multi-buffer write mbox3671 * @phba: Pointer to HBA context object.3672 * @pmboxq: Pointer to mailbox command.3673 *3674 * This is completion handler function for mailbox write commands with multiple3675 * external buffers.3676 **/3677static void3678lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)3679{3680	struct bsg_job *job;3681	struct fc_bsg_reply *bsg_reply;3682 3683	job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq);3684 3685	/* handle the BSG job with the mailbox command */3686	if (!job)3687		pmboxq->u.mb.mbxStatus = MBXERR_ERROR;3688 3689	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3690			"2940 SLI_CONFIG ext-buffer wr mailbox command "3691			"complete, ctxState:x%x, mbxStatus:x%x\n",3692			phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);3693 3694	/* free all memory, including dma buffers */3695	mempool_free(pmboxq, phba->mbox_mem_pool);3696	lpfc_bsg_mbox_ext_session_reset(phba);3697 3698	/* if the job is still active, call job done */3699	if (job) {3700		bsg_reply = job->reply;3701		bsg_job_done(job, bsg_reply->result,3702			       bsg_reply->reply_payload_rcv_len);3703	}3704 3705	return;3706}3707 3708static void3709lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp,3710				uint32_t index, struct lpfc_dmabuf *mbx_dmabuf,3711				struct lpfc_dmabuf *ext_dmabuf)3712{3713	struct lpfc_sli_config_mbox *sli_cfg_mbx;3714 3715	/* pointer to the start of mailbox command */3716	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)mbx_dmabuf->virt;3717 3718	if (nemb_tp == nemb_mse) {3719		if (index == 0) {3720			sli_cfg_mbx->un.sli_config_emb0_subsys.3721				mse[index].pa_hi =3722				putPaddrHigh(mbx_dmabuf->phys +3723					     sizeof(MAILBOX_t));3724			sli_cfg_mbx->un.sli_config_emb0_subsys.3725				mse[index].pa_lo =3726				putPaddrLow(mbx_dmabuf->phys +3727					    sizeof(MAILBOX_t));3728			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3729					"2943 SLI_CONFIG(mse)[%d], "3730					"bufLen:%d, addrHi:x%x, addrLo:x%x\n",3731					index,3732					sli_cfg_mbx->un.sli_config_emb0_subsys.3733					mse[index].buf_len,3734					sli_cfg_mbx->un.sli_config_emb0_subsys.3735					mse[index].pa_hi,3736					sli_cfg_mbx->un.sli_config_emb0_subsys.3737					mse[index].pa_lo);3738		} else {3739			sli_cfg_mbx->un.sli_config_emb0_subsys.3740				mse[index].pa_hi =3741				putPaddrHigh(ext_dmabuf->phys);3742			sli_cfg_mbx->un.sli_config_emb0_subsys.3743				mse[index].pa_lo =3744				putPaddrLow(ext_dmabuf->phys);3745			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3746					"2944 SLI_CONFIG(mse)[%d], "3747					"bufLen:%d, addrHi:x%x, addrLo:x%x\n",3748					index,3749					sli_cfg_mbx->un.sli_config_emb0_subsys.3750					mse[index].buf_len,3751					sli_cfg_mbx->un.sli_config_emb0_subsys.3752					mse[index].pa_hi,3753					sli_cfg_mbx->un.sli_config_emb0_subsys.3754					mse[index].pa_lo);3755		}3756	} else {3757		if (index == 0) {3758			sli_cfg_mbx->un.sli_config_emb1_subsys.3759				hbd[index].pa_hi =3760				putPaddrHigh(mbx_dmabuf->phys +3761					     sizeof(MAILBOX_t));3762			sli_cfg_mbx->un.sli_config_emb1_subsys.3763				hbd[index].pa_lo =3764				putPaddrLow(mbx_dmabuf->phys +3765					    sizeof(MAILBOX_t));3766			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3767					"3007 SLI_CONFIG(hbd)[%d], "3768					"bufLen:%d, addrHi:x%x, addrLo:x%x\n",3769				index,3770				bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,3771				&sli_cfg_mbx->un.3772				sli_config_emb1_subsys.hbd[index]),3773				sli_cfg_mbx->un.sli_config_emb1_subsys.3774				hbd[index].pa_hi,3775				sli_cfg_mbx->un.sli_config_emb1_subsys.3776				hbd[index].pa_lo);3777 3778		} else {3779			sli_cfg_mbx->un.sli_config_emb1_subsys.3780				hbd[index].pa_hi =3781				putPaddrHigh(ext_dmabuf->phys);3782			sli_cfg_mbx->un.sli_config_emb1_subsys.3783				hbd[index].pa_lo =3784				putPaddrLow(ext_dmabuf->phys);3785			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3786					"3008 SLI_CONFIG(hbd)[%d], "3787					"bufLen:%d, addrHi:x%x, addrLo:x%x\n",3788				index,3789				bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,3790				&sli_cfg_mbx->un.3791				sli_config_emb1_subsys.hbd[index]),3792				sli_cfg_mbx->un.sli_config_emb1_subsys.3793				hbd[index].pa_hi,3794				sli_cfg_mbx->un.sli_config_emb1_subsys.3795				hbd[index].pa_lo);3796		}3797	}3798	return;3799}3800 3801/**3802 * lpfc_bsg_sli_cfg_read_cmd_ext - sli_config non-embedded mailbox cmd read3803 * @phba: Pointer to HBA context object.3804 * @job: Pointer to the job object.3805 * @nemb_tp: Enumerate of non-embedded mailbox command type.3806 * @dmabuf: Pointer to a DMA buffer descriptor.3807 *3808 * This routine performs SLI_CONFIG (0x9B) read mailbox command operation with3809 * non-embedded external buffers.3810 **/3811static int3812lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,3813			      enum nemb_type nemb_tp,3814			      struct lpfc_dmabuf *dmabuf)3815{3816	struct fc_bsg_request *bsg_request = job->request;3817	struct lpfc_sli_config_mbox *sli_cfg_mbx;3818	struct dfc_mbox_req *mbox_req;3819	struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf;3820	uint32_t ext_buf_cnt, ext_buf_index;3821	struct lpfc_dmabuf *ext_dmabuf = NULL;3822	struct bsg_job_data *dd_data = NULL;3823	LPFC_MBOXQ_t *pmboxq = NULL;3824	MAILBOX_t *pmb;3825	uint8_t *pmbx;3826	int rc, i;3827 3828	mbox_req =3829	   (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;3830 3831	/* pointer to the start of mailbox command */3832	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;3833 3834	if (nemb_tp == nemb_mse) {3835		ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt,3836			&sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);3837		if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {3838			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3839					"2945 Handled SLI_CONFIG(mse) rd, "3840					"ext_buf_cnt(%d) out of range(%d)\n",3841					ext_buf_cnt,3842					LPFC_MBX_SLI_CONFIG_MAX_MSE);3843			rc = -ERANGE;3844			goto job_error;3845		}3846		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3847				"2941 Handled SLI_CONFIG(mse) rd, "3848				"ext_buf_cnt:%d\n", ext_buf_cnt);3849	} else {3850		/* sanity check on interface type for support */3851		if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <3852		    LPFC_SLI_INTF_IF_TYPE_2) {3853			rc = -ENODEV;3854			goto job_error;3855		}3856		/* nemb_tp == nemb_hbd */3857		ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;3858		if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {3859			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3860					"2946 Handled SLI_CONFIG(hbd) rd, "3861					"ext_buf_cnt(%d) out of range(%d)\n",3862					ext_buf_cnt,3863					LPFC_MBX_SLI_CONFIG_MAX_HBD);3864			rc = -ERANGE;3865			goto job_error;3866		}3867		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3868				"2942 Handled SLI_CONFIG(hbd) rd, "3869				"ext_buf_cnt:%d\n", ext_buf_cnt);3870	}3871 3872	/* before dma descriptor setup */3873	lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,3874					sta_pre_addr, dmabuf, ext_buf_cnt);3875 3876	/* reject non-embedded mailbox command with none external buffer */3877	if (ext_buf_cnt == 0) {3878		rc = -EPERM;3879		goto job_error;3880	} else if (ext_buf_cnt > 1) {3881		/* additional external read buffers */3882		for (i = 1; i < ext_buf_cnt; i++) {3883			ext_dmabuf = lpfc_bsg_dma_page_alloc(phba);3884			if (!ext_dmabuf) {3885				rc = -ENOMEM;3886				goto job_error;3887			}3888			list_add_tail(&ext_dmabuf->list,3889				      &phba->mbox_ext_buf_ctx.ext_dmabuf_list);3890		}3891	}3892 3893	/* bsg tracking structure */3894	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);3895	if (!dd_data) {3896		rc = -ENOMEM;3897		goto job_error;3898	}3899 3900	/* mailbox command structure for base driver */3901	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);3902	if (!pmboxq) {3903		rc = -ENOMEM;3904		goto job_error;3905	}3906	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));3907 3908	/* for the first external buffer */3909	lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);3910 3911	/* for the rest of external buffer descriptors if any */3912	if (ext_buf_cnt > 1) {3913		ext_buf_index = 1;3914		list_for_each_entry_safe(curr_dmabuf, next_dmabuf,3915				&phba->mbox_ext_buf_ctx.ext_dmabuf_list, list) {3916			lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp,3917						ext_buf_index, dmabuf,3918						curr_dmabuf);3919			ext_buf_index++;3920		}3921	}3922 3923	/* after dma descriptor setup */3924	lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,3925					sta_pos_addr, dmabuf, ext_buf_cnt);3926 3927	/* construct base driver mbox command */3928	pmb = &pmboxq->u.mb;3929	pmbx = (uint8_t *)dmabuf->virt;3930	memcpy(pmb, pmbx, sizeof(*pmb));3931	pmb->mbxOwner = OWN_HOST;3932	pmboxq->vport = phba->pport;3933 3934	/* multi-buffer handling context */3935	phba->mbox_ext_buf_ctx.nembType = nemb_tp;3936	phba->mbox_ext_buf_ctx.mboxType = mbox_rd;3937	phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt;3938	phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag;3939	phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum;3940	phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf;3941 3942	/* callback for multi-buffer read mailbox command */3943	pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl;3944 3945	/* context fields to callback function */3946	pmboxq->ctx_u.dd_data = dd_data;3947	dd_data->type = TYPE_MBOX;3948	dd_data->set_job = job;3949	dd_data->context_un.mbox.pmboxq = pmboxq;3950	dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;3951	job->dd_data = dd_data;3952 3953	/* state change */3954	phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;3955 3956	/*3957	 * Non-embedded mailbox subcommand data gets byte swapped here because3958	 * the lower level driver code only does the first 64 mailbox words.3959	 */3960	if ((!bsg_bf_get(lpfc_mbox_hdr_emb,3961	    &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) &&3962		(nemb_tp == nemb_mse))3963		lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)],3964			&pmbx[sizeof(MAILBOX_t)],3965				sli_cfg_mbx->un.sli_config_emb0_subsys.3966					mse[0].buf_len);3967 3968	rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);3969	if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {3970		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,3971				"2947 Issued SLI_CONFIG ext-buffer "3972				"mailbox command, rc:x%x\n", rc);3973		return SLI_CONFIG_HANDLED;3974	}3975	lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,3976			"2948 Failed to issue SLI_CONFIG ext-buffer "3977			"mailbox command, rc:x%x\n", rc);3978	rc = -EPIPE;3979 3980job_error:3981	if (pmboxq)3982		mempool_free(pmboxq, phba->mbox_mem_pool);3983	lpfc_bsg_dma_page_list_free(phba,3984				    &phba->mbox_ext_buf_ctx.ext_dmabuf_list);3985	kfree(dd_data);3986	phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE;3987	return rc;3988}3989 3990/**3991 * lpfc_bsg_sli_cfg_write_cmd_ext - sli_config non-embedded mailbox cmd write3992 * @phba: Pointer to HBA context object.3993 * @job: Pointer to the job object.3994 * @nemb_tp: Enumerate of non-embedded mailbox command type.3995 * @dmabuf: Pointer to a DMA buffer descriptor.3996 *3997 * This routine performs SLI_CONFIG (0x9B) write mailbox command operation with3998 * non-embedded external buffers.3999 **/4000static int4001lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,4002			       enum nemb_type nemb_tp,4003			       struct lpfc_dmabuf *dmabuf)4004{4005	struct fc_bsg_request *bsg_request = job->request;4006	struct fc_bsg_reply *bsg_reply = job->reply;4007	struct dfc_mbox_req *mbox_req;4008	struct lpfc_sli_config_mbox *sli_cfg_mbx;4009	uint32_t ext_buf_cnt;4010	struct bsg_job_data *dd_data = NULL;4011	LPFC_MBOXQ_t *pmboxq = NULL;4012	MAILBOX_t *pmb;4013	uint8_t *mbx;4014	int rc = SLI_CONFIG_NOT_HANDLED, i;4015 4016	mbox_req =4017	   (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;4018 4019	/* pointer to the start of mailbox command */4020	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;4021 4022	if (nemb_tp == nemb_mse) {4023		ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt,4024			&sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);4025		if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {4026			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4027					"2953 Failed SLI_CONFIG(mse) wr, "4028					"ext_buf_cnt(%d) out of range(%d)\n",4029					ext_buf_cnt,4030					LPFC_MBX_SLI_CONFIG_MAX_MSE);4031			return -ERANGE;4032		}4033		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4034				"2949 Handled SLI_CONFIG(mse) wr, "4035				"ext_buf_cnt:%d\n", ext_buf_cnt);4036	} else {4037		/* sanity check on interface type for support */4038		if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <4039		    LPFC_SLI_INTF_IF_TYPE_2)4040			return -ENODEV;4041		/* nemb_tp == nemb_hbd */4042		ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;4043		if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {4044			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4045					"2954 Failed SLI_CONFIG(hbd) wr, "4046					"ext_buf_cnt(%d) out of range(%d)\n",4047					ext_buf_cnt,4048					LPFC_MBX_SLI_CONFIG_MAX_HBD);4049			return -ERANGE;4050		}4051		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4052				"2950 Handled SLI_CONFIG(hbd) wr, "4053				"ext_buf_cnt:%d\n", ext_buf_cnt);4054	}4055 4056	/* before dma buffer descriptor setup */4057	lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,4058					sta_pre_addr, dmabuf, ext_buf_cnt);4059 4060	if (ext_buf_cnt == 0)4061		return -EPERM;4062 4063	/* for the first external buffer */4064	lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);4065 4066	/* after dma descriptor setup */4067	lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,4068					sta_pos_addr, dmabuf, ext_buf_cnt);4069 4070	/* log for looking forward */4071	for (i = 1; i < ext_buf_cnt; i++) {4072		if (nemb_tp == nemb_mse)4073			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4074				"2951 SLI_CONFIG(mse), buf[%d]-length:%d\n",4075				i, sli_cfg_mbx->un.sli_config_emb0_subsys.4076				mse[i].buf_len);4077		else4078			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4079				"2952 SLI_CONFIG(hbd), buf[%d]-length:%d\n",4080				i, bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,4081				&sli_cfg_mbx->un.sli_config_emb1_subsys.4082				hbd[i]));4083	}4084 4085	/* multi-buffer handling context */4086	phba->mbox_ext_buf_ctx.nembType = nemb_tp;4087	phba->mbox_ext_buf_ctx.mboxType = mbox_wr;4088	phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt;4089	phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag;4090	phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum;4091	phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf;4092 4093	if (ext_buf_cnt == 1) {4094		/* bsg tracking structure */4095		dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);4096		if (!dd_data) {4097			rc = -ENOMEM;4098			goto job_error;4099		}4100 4101		/* mailbox command structure for base driver */4102		pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);4103		if (!pmboxq) {4104			rc = -ENOMEM;4105			goto job_error;4106		}4107		memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));4108		pmb = &pmboxq->u.mb;4109		mbx = (uint8_t *)dmabuf->virt;4110		memcpy(pmb, mbx, sizeof(*pmb));4111		pmb->mbxOwner = OWN_HOST;4112		pmboxq->vport = phba->pport;4113 4114		/* callback for multi-buffer read mailbox command */4115		pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;4116 4117		/* context fields to callback function */4118		pmboxq->ctx_u.dd_data = dd_data;4119		dd_data->type = TYPE_MBOX;4120		dd_data->set_job = job;4121		dd_data->context_un.mbox.pmboxq = pmboxq;4122		dd_data->context_un.mbox.mb = (MAILBOX_t *)mbx;4123		job->dd_data = dd_data;4124 4125		/* state change */4126 4127		phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;4128		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);4129		if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {4130			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4131					"2955 Issued SLI_CONFIG ext-buffer "4132					"mailbox command, rc:x%x\n", rc);4133			return SLI_CONFIG_HANDLED;4134		}4135		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4136				"2956 Failed to issue SLI_CONFIG ext-buffer "4137				"mailbox command, rc:x%x\n", rc);4138		rc = -EPIPE;4139		goto job_error;4140	}4141 4142	/* wait for additional external buffers */4143 4144	bsg_reply->result = 0;4145	bsg_job_done(job, bsg_reply->result,4146		       bsg_reply->reply_payload_rcv_len);4147	return SLI_CONFIG_HANDLED;4148 4149job_error:4150	if (pmboxq)4151		mempool_free(pmboxq, phba->mbox_mem_pool);4152	kfree(dd_data);4153 4154	return rc;4155}4156 4157/**4158 * lpfc_bsg_handle_sli_cfg_mbox - handle sli-cfg mailbox cmd with ext buffer4159 * @phba: Pointer to HBA context object.4160 * @job: Pointer to the job object.4161 * @dmabuf: Pointer to a DMA buffer descriptor.4162 *4163 * This routine handles SLI_CONFIG (0x9B) mailbox command with non-embedded4164 * external buffers, including both 0x9B with non-embedded MSEs and 0x9B4165 * with embedded subsystem 0x1 and opcodes with external HBDs.4166 **/4167static int4168lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct bsg_job *job,4169			     struct lpfc_dmabuf *dmabuf)4170{4171	struct lpfc_sli_config_mbox *sli_cfg_mbx;4172	uint32_t subsys;4173	uint32_t opcode;4174	int rc = SLI_CONFIG_NOT_HANDLED;4175 4176	/* state change on new multi-buffer pass-through mailbox command */4177	phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST;4178 4179	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;4180 4181	if (!bsg_bf_get(lpfc_mbox_hdr_emb,4182	    &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) {4183		subsys = bsg_bf_get(lpfc_emb0_subcmnd_subsys,4184				    &sli_cfg_mbx->un.sli_config_emb0_subsys);4185		opcode = bsg_bf_get(lpfc_emb0_subcmnd_opcode,4186				    &sli_cfg_mbx->un.sli_config_emb0_subsys);4187		if (subsys == SLI_CONFIG_SUBSYS_FCOE) {4188			switch (opcode) {4189			case FCOE_OPCODE_READ_FCF:4190			case FCOE_OPCODE_GET_DPORT_RESULTS:4191				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4192						"2957 Handled SLI_CONFIG "4193						"subsys_fcoe, opcode:x%x\n",4194						opcode);4195				rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,4196							nemb_mse, dmabuf);4197				break;4198			case FCOE_OPCODE_ADD_FCF:4199			case FCOE_OPCODE_SET_DPORT_MODE:4200			case LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE:4201				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4202						"2958 Handled SLI_CONFIG "4203						"subsys_fcoe, opcode:x%x\n",4204						opcode);4205				rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job,4206							nemb_mse, dmabuf);4207				break;4208			default:4209				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4210						"2959 Reject SLI_CONFIG "4211						"subsys_fcoe, opcode:x%x\n",4212						opcode);4213				rc = -EPERM;4214				break;4215			}4216		} else if (subsys == SLI_CONFIG_SUBSYS_COMN) {4217			switch (opcode) {4218			case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:4219			case COMN_OPCODE_GET_CNTL_ATTRIBUTES:4220			case COMN_OPCODE_GET_PROFILE_CONFIG:4221			case COMN_OPCODE_SET_FEATURES:4222				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4223						"3106 Handled SLI_CONFIG "4224						"subsys_comn, opcode:x%x\n",4225						opcode);4226				rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,4227							nemb_mse, dmabuf);4228				break;4229			default:4230				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4231						"3107 Reject SLI_CONFIG "4232						"subsys_comn, opcode:x%x\n",4233						opcode);4234				rc = -EPERM;4235				break;4236			}4237		} else {4238			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4239					"2977 Reject SLI_CONFIG "4240					"subsys:x%d, opcode:x%x\n",4241					subsys, opcode);4242			rc = -EPERM;4243		}4244	} else {4245		subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys,4246				    &sli_cfg_mbx->un.sli_config_emb1_subsys);4247		opcode = bsg_bf_get(lpfc_emb1_subcmnd_opcode,4248				    &sli_cfg_mbx->un.sli_config_emb1_subsys);4249		if (subsys == SLI_CONFIG_SUBSYS_COMN) {4250			switch (opcode) {4251			case COMN_OPCODE_READ_OBJECT:4252			case COMN_OPCODE_READ_OBJECT_LIST:4253				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4254						"2960 Handled SLI_CONFIG "4255						"subsys_comn, opcode:x%x\n",4256						opcode);4257				rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,4258							nemb_hbd, dmabuf);4259				break;4260			case COMN_OPCODE_WRITE_OBJECT:4261				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4262						"2961 Handled SLI_CONFIG "4263						"subsys_comn, opcode:x%x\n",4264						opcode);4265				rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job,4266							nemb_hbd, dmabuf);4267				break;4268			default:4269				lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4270						"2962 Not handled SLI_CONFIG "4271						"subsys_comn, opcode:x%x\n",4272						opcode);4273				rc = SLI_CONFIG_NOT_HANDLED;4274				break;4275			}4276		} else {4277			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4278					"2978 Not handled SLI_CONFIG "4279					"subsys:x%d, opcode:x%x\n",4280					subsys, opcode);4281			rc = SLI_CONFIG_NOT_HANDLED;4282		}4283	}4284 4285	/* state reset on not handled new multi-buffer mailbox command */4286	if (rc != SLI_CONFIG_HANDLED)4287		phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE;4288 4289	return rc;4290}4291 4292/**4293 * lpfc_bsg_mbox_ext_abort - request to abort mbox command with ext buffers4294 * @phba: Pointer to HBA context object.4295 *4296 * This routine is for requesting to abort a pass-through mailbox command with4297 * multiple external buffers due to error condition.4298 **/4299static void4300lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba)4301{4302	if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)4303		phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;4304	else4305		lpfc_bsg_mbox_ext_session_reset(phba);4306	return;4307}4308 4309/**4310 * lpfc_bsg_read_ebuf_get - get the next mailbox read external buffer4311 * @phba: Pointer to HBA context object.4312 * @job: Pointer to the job object.4313 *4314 * This routine extracts the next mailbox read external buffer back to4315 * user space through BSG.4316 **/4317static int4318lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct bsg_job *job)4319{4320	struct fc_bsg_reply *bsg_reply = job->reply;4321	struct lpfc_sli_config_mbox *sli_cfg_mbx;4322	struct lpfc_dmabuf *dmabuf;4323	uint8_t *pbuf;4324	uint32_t size;4325	uint32_t index;4326 4327	index = phba->mbox_ext_buf_ctx.seqNum;4328	phba->mbox_ext_buf_ctx.seqNum++;4329 4330	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)4331			phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;4332 4333	if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) {4334		size = bsg_bf_get(lpfc_mbox_sli_config_mse_len,4335			&sli_cfg_mbx->un.sli_config_emb0_subsys.mse[index]);4336		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4337				"2963 SLI_CONFIG (mse) ext-buffer rd get "4338				"buffer[%d], size:%d\n", index, size);4339	} else {4340		size = bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len,4341			&sli_cfg_mbx->un.sli_config_emb1_subsys.hbd[index]);4342		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4343				"2964 SLI_CONFIG (hbd) ext-buffer rd get "4344				"buffer[%d], size:%d\n", index, size);4345	}4346	if (list_empty(&phba->mbox_ext_buf_ctx.ext_dmabuf_list))4347		return -EPIPE;4348	dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list,4349				  struct lpfc_dmabuf, list);4350	list_del_init(&dmabuf->list);4351 4352	/* after dma buffer descriptor setup */4353	lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,4354					mbox_rd, dma_ebuf, sta_pos_addr,4355					dmabuf, index);4356 4357	pbuf = (uint8_t *)dmabuf->virt;4358	bsg_reply->reply_payload_rcv_len =4359		sg_copy_from_buffer(job->reply_payload.sg_list,4360				    job->reply_payload.sg_cnt,4361				    pbuf, size);4362 4363	lpfc_bsg_dma_page_free(phba, dmabuf);4364 4365	if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {4366		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4367				"2965 SLI_CONFIG (hbd) ext-buffer rd mbox "4368				"command session done\n");4369		lpfc_bsg_mbox_ext_session_reset(phba);4370	}4371 4372	bsg_reply->result = 0;4373	bsg_job_done(job, bsg_reply->result,4374		       bsg_reply->reply_payload_rcv_len);4375 4376	return SLI_CONFIG_HANDLED;4377}4378 4379/**4380 * lpfc_bsg_write_ebuf_set - set the next mailbox write external buffer4381 * @phba: Pointer to HBA context object.4382 * @job: Pointer to the job object.4383 * @dmabuf: Pointer to a DMA buffer descriptor.4384 *4385 * This routine sets up the next mailbox read external buffer obtained4386 * from user space through BSG.4387 **/4388static int4389lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,4390			struct lpfc_dmabuf *dmabuf)4391{4392	struct fc_bsg_reply *bsg_reply = job->reply;4393	struct bsg_job_data *dd_data = NULL;4394	LPFC_MBOXQ_t *pmboxq = NULL;4395	MAILBOX_t *pmb;4396	enum nemb_type nemb_tp;4397	uint8_t *pbuf;4398	uint32_t size;4399	uint32_t index;4400	int rc;4401 4402	index = phba->mbox_ext_buf_ctx.seqNum;4403	phba->mbox_ext_buf_ctx.seqNum++;4404	nemb_tp = phba->mbox_ext_buf_ctx.nembType;4405 4406	pbuf = (uint8_t *)dmabuf->virt;4407	size = job->request_payload.payload_len;4408	sg_copy_to_buffer(job->request_payload.sg_list,4409			  job->request_payload.sg_cnt,4410			  pbuf, size);4411 4412	if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) {4413		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4414				"2966 SLI_CONFIG (mse) ext-buffer wr set "4415				"buffer[%d], size:%d\n",4416				phba->mbox_ext_buf_ctx.seqNum, size);4417 4418	} else {4419		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4420				"2967 SLI_CONFIG (hbd) ext-buffer wr set "4421				"buffer[%d], size:%d\n",4422				phba->mbox_ext_buf_ctx.seqNum, size);4423 4424	}4425 4426	/* set up external buffer descriptor and add to external buffer list */4427	lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, index,4428					phba->mbox_ext_buf_ctx.mbx_dmabuf,4429					dmabuf);4430	list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list);4431 4432	/* after write dma buffer */4433	lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,4434					mbox_wr, dma_ebuf, sta_pos_addr,4435					dmabuf, index);4436 4437	if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {4438		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4439				"2968 SLI_CONFIG ext-buffer wr all %d "4440				"ebuffers received\n",4441				phba->mbox_ext_buf_ctx.numBuf);4442 4443		dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);4444		if (!dd_data) {4445			rc = -ENOMEM;4446			goto job_error;4447		}4448 4449		/* mailbox command structure for base driver */4450		pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);4451		if (!pmboxq) {4452			rc = -ENOMEM;4453			goto job_error;4454		}4455		memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));4456		pbuf = (uint8_t *)phba->mbox_ext_buf_ctx.mbx_dmabuf->virt;4457		pmb = &pmboxq->u.mb;4458		memcpy(pmb, pbuf, sizeof(*pmb));4459		pmb->mbxOwner = OWN_HOST;4460		pmboxq->vport = phba->pport;4461 4462		/* callback for multi-buffer write mailbox command */4463		pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;4464 4465		/* context fields to callback function */4466		pmboxq->ctx_u.dd_data = dd_data;4467		dd_data->type = TYPE_MBOX;4468		dd_data->set_job = job;4469		dd_data->context_un.mbox.pmboxq = pmboxq;4470		dd_data->context_un.mbox.mb = (MAILBOX_t *)pbuf;4471		job->dd_data = dd_data;4472 4473		/* state change */4474		phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;4475 4476		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);4477		if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {4478			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4479					"2969 Issued SLI_CONFIG ext-buffer "4480					"mailbox command, rc:x%x\n", rc);4481			return SLI_CONFIG_HANDLED;4482		}4483		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4484				"2970 Failed to issue SLI_CONFIG ext-buffer "4485				"mailbox command, rc:x%x\n", rc);4486		rc = -EPIPE;4487		goto job_error;4488	}4489 4490	/* wait for additional external buffers */4491	bsg_reply->result = 0;4492	bsg_job_done(job, bsg_reply->result,4493		       bsg_reply->reply_payload_rcv_len);4494	return SLI_CONFIG_HANDLED;4495 4496job_error:4497	if (pmboxq)4498		mempool_free(pmboxq, phba->mbox_mem_pool);4499	lpfc_bsg_dma_page_free(phba, dmabuf);4500	kfree(dd_data);4501 4502	return rc;4503}4504 4505/**4506 * lpfc_bsg_handle_sli_cfg_ebuf - handle ext buffer with sli-cfg mailbox cmd4507 * @phba: Pointer to HBA context object.4508 * @job: Pointer to the job object.4509 * @dmabuf: Pointer to a DMA buffer descriptor.4510 *4511 * This routine handles the external buffer with SLI_CONFIG (0x9B) mailbox4512 * command with multiple non-embedded external buffers.4513 **/4514static int4515lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct bsg_job *job,4516			     struct lpfc_dmabuf *dmabuf)4517{4518	int rc;4519 4520	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4521			"2971 SLI_CONFIG buffer (type:x%x)\n",4522			phba->mbox_ext_buf_ctx.mboxType);4523 4524	if (phba->mbox_ext_buf_ctx.mboxType == mbox_rd) {4525		if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_DONE) {4526			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4527					"2972 SLI_CONFIG rd buffer state "4528					"mismatch:x%x\n",4529					phba->mbox_ext_buf_ctx.state);4530			lpfc_bsg_mbox_ext_abort(phba);4531			return -EPIPE;4532		}4533		rc = lpfc_bsg_read_ebuf_get(phba, job);4534		if (rc == SLI_CONFIG_HANDLED)4535			lpfc_bsg_dma_page_free(phba, dmabuf);4536	} else { /* phba->mbox_ext_buf_ctx.mboxType == mbox_wr */4537		if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_HOST) {4538			lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4539					"2973 SLI_CONFIG wr buffer state "4540					"mismatch:x%x\n",4541					phba->mbox_ext_buf_ctx.state);4542			lpfc_bsg_mbox_ext_abort(phba);4543			return -EPIPE;4544		}4545		rc = lpfc_bsg_write_ebuf_set(phba, job, dmabuf);4546	}4547	return rc;4548}4549 4550/**4551 * lpfc_bsg_handle_sli_cfg_ext - handle sli-cfg mailbox with external buffer4552 * @phba: Pointer to HBA context object.4553 * @job: Pointer to the job object.4554 * @dmabuf: Pointer to a DMA buffer descriptor.4555 *4556 * This routine checks and handles non-embedded multi-buffer SLI_CONFIG4557 * (0x9B) mailbox commands and external buffers.4558 **/4559static int4560lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct bsg_job *job,4561			    struct lpfc_dmabuf *dmabuf)4562{4563	struct fc_bsg_request *bsg_request = job->request;4564	struct dfc_mbox_req *mbox_req;4565	int rc = SLI_CONFIG_NOT_HANDLED;4566 4567	mbox_req =4568	   (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;4569 4570	/* mbox command with/without single external buffer */4571	if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0)4572		return rc;4573 4574	/* mbox command and first external buffer */4575	if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) {4576		if (mbox_req->extSeqNum == 1) {4577			lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4578					"2974 SLI_CONFIG mailbox: tag:%d, "4579					"seq:%d\n", mbox_req->extMboxTag,4580					mbox_req->extSeqNum);4581			rc = lpfc_bsg_handle_sli_cfg_mbox(phba, job, dmabuf);4582			return rc;4583		} else4584			goto sli_cfg_ext_error;4585	}4586 4587	/*4588	 * handle additional external buffers4589	 */4590 4591	/* check broken pipe conditions */4592	if (mbox_req->extMboxTag != phba->mbox_ext_buf_ctx.mbxTag)4593		goto sli_cfg_ext_error;4594	if (mbox_req->extSeqNum > phba->mbox_ext_buf_ctx.numBuf)4595		goto sli_cfg_ext_error;4596	if (mbox_req->extSeqNum != phba->mbox_ext_buf_ctx.seqNum + 1)4597		goto sli_cfg_ext_error;4598 4599	lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4600			"2975 SLI_CONFIG mailbox external buffer: "4601			"extSta:x%x, tag:%d, seq:%d\n",4602			phba->mbox_ext_buf_ctx.state, mbox_req->extMboxTag,4603			mbox_req->extSeqNum);4604	rc = lpfc_bsg_handle_sli_cfg_ebuf(phba, job, dmabuf);4605	return rc;4606 4607sli_cfg_ext_error:4608	/* all other cases, broken pipe */4609	lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,4610			"2976 SLI_CONFIG mailbox broken pipe: "4611			"ctxSta:x%x, ctxNumBuf:%d "4612			"ctxTag:%d, ctxSeq:%d, tag:%d, seq:%d\n",4613			phba->mbox_ext_buf_ctx.state,4614			phba->mbox_ext_buf_ctx.numBuf,4615			phba->mbox_ext_buf_ctx.mbxTag,4616			phba->mbox_ext_buf_ctx.seqNum,4617			mbox_req->extMboxTag, mbox_req->extSeqNum);4618 4619	lpfc_bsg_mbox_ext_session_reset(phba);4620 4621	return -EPIPE;4622}4623 4624/**4625 * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app4626 * @phba: Pointer to HBA context object.4627 * @job: Pointer to the job object.4628 * @vport: Pointer to a vport object.4629 *4630 * Allocate a tracking object, mailbox command memory, get a mailbox4631 * from the mailbox pool, copy the caller mailbox command.4632 *4633 * If offline and the sli is active we need to poll for the command (port is4634 * being reset) and complete the job, otherwise issue the mailbox command and4635 * let our completion handler finish the command.4636 **/4637static int4638lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct bsg_job *job,4639	struct lpfc_vport *vport)4640{4641	struct fc_bsg_request *bsg_request = job->request;4642	struct fc_bsg_reply *bsg_reply = job->reply;4643	LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */4644	MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */4645	/* a 4k buffer to hold the mb and extended data from/to the bsg */4646	uint8_t *pmbx = NULL;4647	struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */4648	struct lpfc_dmabuf *dmabuf = NULL;4649	struct dfc_mbox_req *mbox_req;4650	struct READ_EVENT_LOG_VAR *rdEventLog;4651	uint32_t transmit_length, receive_length, mode;4652	struct lpfc_mbx_sli4_config *sli4_config;4653	struct lpfc_mbx_nembed_cmd *nembed_sge;4654	struct ulp_bde64 *bde;4655	uint8_t *ext = NULL;4656	int rc = 0;4657	uint8_t *from;4658	uint32_t size;4659 4660	/* in case no data is transferred */4661	bsg_reply->reply_payload_rcv_len = 0;4662 4663	/* sanity check to protect driver */4664	if (job->reply_payload.payload_len > BSG_MBOX_SIZE ||4665	    job->request_payload.payload_len > BSG_MBOX_SIZE) {4666		rc = -ERANGE;4667		goto job_done;4668	}4669 4670	/*4671	 * Don't allow mailbox commands to be sent when blocked or when in4672	 * the middle of discovery4673	 */4674	if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {4675		rc = -EAGAIN;4676		goto job_done;4677	}4678 4679	mbox_req =4680	    (struct dfc_mbox_req *)bsg_request->rqst_data.h_vendor.vendor_cmd;4681 4682	/* check if requested extended data lengths are valid */4683	if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||4684	    (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) {4685		rc = -ERANGE;4686		goto job_done;4687	}4688 4689	dmabuf = lpfc_bsg_dma_page_alloc(phba);4690	if (!dmabuf || !dmabuf->virt) {4691		rc = -ENOMEM;4692		goto job_done;4693	}4694 4695	/* Get the mailbox command or external buffer from BSG */4696	pmbx = (uint8_t *)dmabuf->virt;4697	size = job->request_payload.payload_len;4698	sg_copy_to_buffer(job->request_payload.sg_list,4699			  job->request_payload.sg_cnt, pmbx, size);4700 4701	/* Handle possible SLI_CONFIG with non-embedded payloads */4702	if (phba->sli_rev == LPFC_SLI_REV4) {4703		rc = lpfc_bsg_handle_sli_cfg_ext(phba, job, dmabuf);4704		if (rc == SLI_CONFIG_HANDLED)4705			goto job_cont;4706		if (rc)4707			goto job_done;4708		/* SLI_CONFIG_NOT_HANDLED for other mailbox commands */4709	}4710 4711	rc = lpfc_bsg_check_cmd_access(phba, (MAILBOX_t *)pmbx, vport);4712	if (rc != 0)4713		goto job_done; /* must be negative */4714 4715	/* allocate our bsg tracking structure */4716	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);4717	if (!dd_data) {4718		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,4719				"2727 Failed allocation of dd_data\n");4720		rc = -ENOMEM;4721		goto job_done;4722	}4723 4724	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);4725	if (!pmboxq) {4726		rc = -ENOMEM;4727		goto job_done;4728	}4729	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));4730 4731	pmb = &pmboxq->u.mb;4732	memcpy(pmb, pmbx, sizeof(*pmb));4733	pmb->mbxOwner = OWN_HOST;4734	pmboxq->vport = vport;4735 4736	/* If HBA encountered an error attention, allow only DUMP4737	 * or RESTART mailbox commands until the HBA is restarted.4738	 */4739	if (phba->pport->stopped &&4740	    pmb->mbxCommand != MBX_DUMP_MEMORY &&4741	    pmb->mbxCommand != MBX_RESTART &&4742	    pmb->mbxCommand != MBX_WRITE_VPARMS &&4743	    pmb->mbxCommand != MBX_WRITE_WWN)4744		lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,4745				"2797 mbox: Issued mailbox cmd "4746				"0x%x while in stopped state.\n",4747				pmb->mbxCommand);4748 4749	/* extended mailbox commands will need an extended buffer */4750	if (mbox_req->inExtWLen || mbox_req->outExtWLen) {4751		from = pmbx;4752		ext = from + sizeof(MAILBOX_t);4753		pmboxq->ext_buf = ext;4754		pmboxq->in_ext_byte_len =4755			mbox_req->inExtWLen * sizeof(uint32_t);4756		pmboxq->out_ext_byte_len =4757			mbox_req->outExtWLen * sizeof(uint32_t);4758		pmboxq->mbox_offset_word = mbox_req->mbOffset;4759	}4760 4761	/* biu diag will need a kernel buffer to transfer the data4762	 * allocate our own buffer and setup the mailbox command to4763	 * use ours4764	 */4765	if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) {4766		transmit_length = pmb->un.varWords[1];4767		receive_length = pmb->un.varWords[4];4768		/* transmit length cannot be greater than receive length or4769		 * mailbox extension size4770		 */4771		if ((transmit_length > receive_length) ||4772			(transmit_length > BSG_MBOX_SIZE - sizeof(MAILBOX_t))) {4773			rc = -ERANGE;4774			goto job_done;4775		}4776		pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =4777			putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t));4778		pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =4779			putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t));4780 4781		pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =4782			putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t)4783			  + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize);4784		pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =4785			putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t)4786			  + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize);4787	} else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) {4788		rdEventLog = &pmb->un.varRdEventLog;4789		receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;4790		mode = bf_get(lpfc_event_log, rdEventLog);4791 4792		/* receive length cannot be greater than mailbox4793		 * extension size4794		 */4795		if (receive_length > BSG_MBOX_SIZE - sizeof(MAILBOX_t)) {4796			rc = -ERANGE;4797			goto job_done;4798		}4799 4800		/* mode zero uses a bde like biu diags command */4801		if (mode == 0) {4802			pmb->un.varWords[3] = putPaddrLow(dmabuf->phys4803							+ sizeof(MAILBOX_t));4804			pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys4805							+ sizeof(MAILBOX_t));4806		}4807	} else if (phba->sli_rev == LPFC_SLI_REV4) {4808		/* Let type 4 (well known data) through because the data is4809		 * returned in varwords[4-8]4810		 * otherwise check the recieve length and fetch the buffer addr4811		 */4812		if ((pmb->mbxCommand == MBX_DUMP_MEMORY) &&4813			(pmb->un.varDmp.type != DMP_WELL_KNOWN)) {4814			/* rebuild the command for sli4 using our own buffers4815			* like we do for biu diags4816			*/4817			receive_length = pmb->un.varWords[2];4818			/* receive length cannot be greater than mailbox4819			 * extension size4820			 */4821			if (receive_length == 0) {4822				rc = -ERANGE;4823				goto job_done;4824			}4825			pmb->un.varWords[3] = putPaddrLow(dmabuf->phys4826						+ sizeof(MAILBOX_t));4827			pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys4828						+ sizeof(MAILBOX_t));4829		} else if ((pmb->mbxCommand == MBX_UPDATE_CFG) &&4830			pmb->un.varUpdateCfg.co) {4831			bde = (struct ulp_bde64 *)&pmb->un.varWords[4];4832 4833			/* bde size cannot be greater than mailbox ext size */4834			if (bde->tus.f.bdeSize >4835			    BSG_MBOX_SIZE - sizeof(MAILBOX_t)) {4836				rc = -ERANGE;4837				goto job_done;4838			}4839			bde->addrHigh = putPaddrHigh(dmabuf->phys4840						+ sizeof(MAILBOX_t));4841			bde->addrLow = putPaddrLow(dmabuf->phys4842						+ sizeof(MAILBOX_t));4843		} else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {4844			/* Handling non-embedded SLI_CONFIG mailbox command */4845			sli4_config = &pmboxq->u.mqe.un.sli4_config;4846			if (!bf_get(lpfc_mbox_hdr_emb,4847			    &sli4_config->header.cfg_mhdr)) {4848				/* rebuild the command for sli4 using our4849				 * own buffers like we do for biu diags4850				 */4851				nembed_sge = (struct lpfc_mbx_nembed_cmd *)4852						&pmb->un.varWords[0];4853				receive_length = nembed_sge->sge[0].length;4854 4855				/* receive length cannot be greater than4856				 * mailbox extension size4857				 */4858				if ((receive_length == 0) ||4859				    (receive_length >4860				     BSG_MBOX_SIZE - sizeof(MAILBOX_t))) {4861					rc = -ERANGE;4862					goto job_done;4863				}4864 4865				nembed_sge->sge[0].pa_hi =4866						putPaddrHigh(dmabuf->phys4867						   + sizeof(MAILBOX_t));4868				nembed_sge->sge[0].pa_lo =4869						putPaddrLow(dmabuf->phys4870						   + sizeof(MAILBOX_t));4871			}4872		}4873	}4874 4875	dd_data->context_un.mbox.dmabuffers = dmabuf;4876 4877	/* setup wake call as IOCB callback */4878	pmboxq->mbox_cmpl = lpfc_bsg_issue_mbox_cmpl;4879 4880	/* setup context field to pass wait_queue pointer to wake function */4881	pmboxq->ctx_u.dd_data = dd_data;4882	dd_data->type = TYPE_MBOX;4883	dd_data->set_job = job;4884	dd_data->context_un.mbox.pmboxq = pmboxq;4885	dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx;4886	dd_data->context_un.mbox.ext = ext;4887	dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset;4888	dd_data->context_un.mbox.inExtWLen = mbox_req->inExtWLen;4889	dd_data->context_un.mbox.outExtWLen = mbox_req->outExtWLen;4890	job->dd_data = dd_data;4891 4892	if (test_bit(FC_OFFLINE_MODE, &vport->fc_flag) ||4893	    (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) {4894		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);4895		if (rc != MBX_SUCCESS) {4896			rc = (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;4897			goto job_done;4898		}4899 4900		/* job finished, copy the data */4901		memcpy(pmbx, pmb, sizeof(*pmb));4902		bsg_reply->reply_payload_rcv_len =4903			sg_copy_from_buffer(job->reply_payload.sg_list,4904					    job->reply_payload.sg_cnt,4905					    pmbx, size);4906		/* not waiting mbox already done */4907		rc = 0;4908		goto job_done;4909	}4910 4911	rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);4912	if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY))4913		return 1; /* job started */4914 4915job_done:4916	/* common exit for error or job completed inline */4917	if (pmboxq)4918		mempool_free(pmboxq, phba->mbox_mem_pool);4919	lpfc_bsg_dma_page_free(phba, dmabuf);4920	kfree(dd_data);4921 4922job_cont:4923	return rc;4924}4925 4926/**4927 * lpfc_bsg_mbox_cmd - process an fc bsg LPFC_BSG_VENDOR_MBOX command4928 * @job: MBOX fc_bsg_job for LPFC_BSG_VENDOR_MBOX.4929 **/4930static int4931lpfc_bsg_mbox_cmd(struct bsg_job *job)4932{4933	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));4934	struct fc_bsg_request *bsg_request = job->request;4935	struct fc_bsg_reply *bsg_reply = job->reply;4936	struct lpfc_hba *phba = vport->phba;4937	struct dfc_mbox_req *mbox_req;4938	int rc = 0;4939 4940	/* mix-and-match backward compatibility */4941	bsg_reply->reply_payload_rcv_len = 0;4942	if (job->request_len <4943	    sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) {4944		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,4945				"2737 Mix-and-match backward compatibility "4946				"between MBOX_REQ old size:%d and "4947				"new request size:%d\n",4948				(int)(job->request_len -4949				      sizeof(struct fc_bsg_request)),4950				(int)sizeof(struct dfc_mbox_req));4951		mbox_req = (struct dfc_mbox_req *)4952				bsg_request->rqst_data.h_vendor.vendor_cmd;4953		mbox_req->extMboxTag = 0;4954		mbox_req->extSeqNum = 0;4955	}4956 4957	rc = lpfc_bsg_issue_mbox(phba, job, vport);4958 4959	if (rc == 0) {4960		/* job done */4961		bsg_reply->result = 0;4962		job->dd_data = NULL;4963		bsg_job_done(job, bsg_reply->result,4964			       bsg_reply->reply_payload_rcv_len);4965	} else if (rc == 1)4966		/* job submitted, will complete later*/4967		rc = 0; /* return zero, no error */4968	else {4969		/* some error occurred */4970		bsg_reply->result = rc;4971		job->dd_data = NULL;4972	}4973 4974	return rc;4975}4976 4977static int4978lpfc_forced_link_speed(struct bsg_job *job)4979{4980	struct Scsi_Host *shost = fc_bsg_to_shost(job);4981	struct lpfc_vport *vport = shost_priv(shost);4982	struct lpfc_hba *phba = vport->phba;4983	struct fc_bsg_reply *bsg_reply = job->reply;4984	struct forced_link_speed_support_reply *forced_reply;4985	int rc = 0;4986 4987	if (job->request_len <4988	    sizeof(struct fc_bsg_request) +4989	    sizeof(struct get_forced_link_speed_support)) {4990		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,4991				"0048 Received FORCED_LINK_SPEED request "4992				"below minimum size\n");4993		rc = -EINVAL;4994		goto job_error;4995	}4996 4997	forced_reply = (struct forced_link_speed_support_reply *)4998		bsg_reply->reply_data.vendor_reply.vendor_rsp;4999 5000	if (job->reply_len < sizeof(*bsg_reply) + sizeof(*forced_reply)) {5001		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,5002				"0049 Received FORCED_LINK_SPEED reply below "5003				"minimum size\n");5004		rc = -EINVAL;5005		goto job_error;5006	}5007 5008	forced_reply->supported = test_bit(HBA_FORCED_LINK_SPEED,5009					   &phba->hba_flag)5010				   ? LPFC_FORCED_LINK_SPEED_SUPPORTED5011				   : LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED;5012job_error:5013	bsg_reply->result = rc;5014	if (rc == 0)5015		bsg_job_done(job, bsg_reply->result,5016			       bsg_reply->reply_payload_rcv_len);5017	return rc;5018}5019 5020/**5021 * lpfc_check_fwlog_support: Check FW log support on the adapter5022 * @phba: Pointer to HBA context object.5023 *5024 * Check if FW Logging support by the adapter5025 **/5026int5027lpfc_check_fwlog_support(struct lpfc_hba *phba)5028{5029	struct lpfc_ras_fwlog *ras_fwlog = NULL;5030 5031	ras_fwlog = &phba->ras_fwlog;5032 5033	if (!ras_fwlog->ras_hwsupport)5034		return -EACCES;5035	else if (!ras_fwlog->ras_enabled)5036		return -EPERM;5037	else5038		return 0;5039}5040 5041/**5042 * lpfc_bsg_get_ras_config: Get RAS configuration settings5043 * @job: fc_bsg_job to handle5044 *5045 * Get RAS configuration values set.5046 **/5047static int5048lpfc_bsg_get_ras_config(struct bsg_job *job)5049{5050	struct Scsi_Host *shost = fc_bsg_to_shost(job);5051	struct lpfc_vport *vport = shost_priv(shost);5052	struct fc_bsg_reply *bsg_reply = job->reply;5053	struct lpfc_hba *phba = vport->phba;5054	struct lpfc_bsg_get_ras_config_reply *ras_reply;5055	struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;5056	int rc = 0;5057 5058	if (job->request_len <5059	    sizeof(struct fc_bsg_request) +5060	    sizeof(struct lpfc_bsg_ras_req)) {5061		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5062				"6192 FW_LOG request received "5063				"below minimum size\n");5064		rc = -EINVAL;5065		goto ras_job_error;5066	}5067 5068	/* Check FW log status */5069	rc = lpfc_check_fwlog_support(phba);5070	if (rc)5071		goto ras_job_error;5072 5073	ras_reply = (struct lpfc_bsg_get_ras_config_reply *)5074		bsg_reply->reply_data.vendor_reply.vendor_rsp;5075 5076	/* Current logging state */5077	spin_lock_irq(&phba->ras_fwlog_lock);5078	if (ras_fwlog->state == ACTIVE)5079		ras_reply->state = LPFC_RASLOG_STATE_RUNNING;5080	else5081		ras_reply->state = LPFC_RASLOG_STATE_STOPPED;5082	spin_unlock_irq(&phba->ras_fwlog_lock);5083 5084	ras_reply->log_level = phba->ras_fwlog.fw_loglevel;5085	ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;5086 5087ras_job_error:5088	/* make error code available to userspace */5089	bsg_reply->result = rc;5090 5091	/* complete the job back to userspace */5092	if (!rc)5093		bsg_job_done(job, bsg_reply->result,5094			     bsg_reply->reply_payload_rcv_len);5095	return rc;5096}5097 5098/**5099 * lpfc_bsg_set_ras_config: Set FW logging parameters5100 * @job: fc_bsg_job to handle5101 *5102 * Set log-level parameters for FW-logging in host memory5103 **/5104static int5105lpfc_bsg_set_ras_config(struct bsg_job *job)5106{5107	struct Scsi_Host *shost = fc_bsg_to_shost(job);5108	struct lpfc_vport *vport = shost_priv(shost);5109	struct lpfc_hba *phba = vport->phba;5110	struct lpfc_bsg_set_ras_config_req *ras_req;5111	struct fc_bsg_request *bsg_request = job->request;5112	struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;5113	struct fc_bsg_reply *bsg_reply = job->reply;5114	uint8_t action = 0, log_level = 0;5115	int rc = 0, action_status = 0;5116 5117	if (job->request_len <5118	    sizeof(struct fc_bsg_request) +5119	    sizeof(struct lpfc_bsg_set_ras_config_req)) {5120		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5121				"6182 Received RAS_LOG request "5122				"below minimum size\n");5123		rc = -EINVAL;5124		goto ras_job_error;5125	}5126 5127	/* Check FW log status */5128	rc = lpfc_check_fwlog_support(phba);5129	if (rc)5130		goto ras_job_error;5131 5132	ras_req = (struct lpfc_bsg_set_ras_config_req *)5133		bsg_request->rqst_data.h_vendor.vendor_cmd;5134	action = ras_req->action;5135	log_level = ras_req->log_level;5136 5137	if (action == LPFC_RASACTION_STOP_LOGGING) {5138		/* Check if already disabled */5139		spin_lock_irq(&phba->ras_fwlog_lock);5140		if (ras_fwlog->state != ACTIVE) {5141			spin_unlock_irq(&phba->ras_fwlog_lock);5142			rc = -ESRCH;5143			goto ras_job_error;5144		}5145		spin_unlock_irq(&phba->ras_fwlog_lock);5146 5147		/* Disable logging */5148		lpfc_ras_stop_fwlog(phba);5149	} else {5150		/*action = LPFC_RASACTION_START_LOGGING*/5151 5152		/* Even though FW-logging is active re-initialize5153		 * FW-logging with new log-level. Return status5154		 * "Logging already Running" to caller.5155		 **/5156		spin_lock_irq(&phba->ras_fwlog_lock);5157		if (ras_fwlog->state != INACTIVE)5158			action_status = -EINPROGRESS;5159		spin_unlock_irq(&phba->ras_fwlog_lock);5160 5161		/* Enable logging */5162		rc = lpfc_sli4_ras_fwlog_init(phba, log_level,5163					      LPFC_RAS_ENABLE_LOGGING);5164		if (rc) {5165			rc = -EINVAL;5166			goto ras_job_error;5167		}5168 5169		/* Check if FW-logging is re-initialized */5170		if (action_status == -EINPROGRESS)5171			rc = action_status;5172	}5173ras_job_error:5174	/* make error code available to userspace */5175	bsg_reply->result = rc;5176 5177	/* complete the job back to userspace */5178	if (!rc)5179		bsg_job_done(job, bsg_reply->result,5180			     bsg_reply->reply_payload_rcv_len);5181 5182	return rc;5183}5184 5185/**5186 * lpfc_bsg_get_ras_lwpd: Get log write position data5187 * @job: fc_bsg_job to handle5188 *5189 * Get Offset/Wrap count of the log message written5190 * in host memory5191 **/5192static int5193lpfc_bsg_get_ras_lwpd(struct bsg_job *job)5194{5195	struct Scsi_Host *shost = fc_bsg_to_shost(job);5196	struct lpfc_vport *vport = shost_priv(shost);5197	struct lpfc_bsg_get_ras_lwpd *ras_reply;5198	struct lpfc_hba *phba = vport->phba;5199	struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;5200	struct fc_bsg_reply *bsg_reply = job->reply;5201	u32 *lwpd_ptr = NULL;5202	int rc = 0;5203 5204	rc = lpfc_check_fwlog_support(phba);5205	if (rc)5206		goto ras_job_error;5207 5208	if (job->request_len <5209	    sizeof(struct fc_bsg_request) +5210	    sizeof(struct lpfc_bsg_ras_req)) {5211		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5212				"6183 Received RAS_LOG request "5213				"below minimum size\n");5214		rc = -EINVAL;5215		goto ras_job_error;5216	}5217 5218	ras_reply = (struct lpfc_bsg_get_ras_lwpd *)5219		bsg_reply->reply_data.vendor_reply.vendor_rsp;5220 5221	if (!ras_fwlog->lwpd.virt) {5222		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5223				"6193 Restart FW Logging\n");5224		rc = -EINVAL;5225		goto ras_job_error;5226	}5227 5228	/* Get lwpd offset */5229	lwpd_ptr = (uint32_t *)(ras_fwlog->lwpd.virt);5230	ras_reply->offset = be32_to_cpu(*lwpd_ptr & 0xffffffff);5231 5232	/* Get wrap count */5233	ras_reply->wrap_count = be32_to_cpu(*(++lwpd_ptr) & 0xffffffff);5234 5235ras_job_error:5236	/* make error code available to userspace */5237	bsg_reply->result = rc;5238 5239	/* complete the job back to userspace */5240	if (!rc)5241		bsg_job_done(job, bsg_reply->result,5242			     bsg_reply->reply_payload_rcv_len);5243 5244	return rc;5245}5246 5247/**5248 * lpfc_bsg_get_ras_fwlog: Read FW log5249 * @job: fc_bsg_job to handle5250 *5251 * Copy the FW log into the passed buffer.5252 **/5253static int5254lpfc_bsg_get_ras_fwlog(struct bsg_job *job)5255{5256	struct Scsi_Host *shost = fc_bsg_to_shost(job);5257	struct lpfc_vport *vport = shost_priv(shost);5258	struct lpfc_hba *phba = vport->phba;5259	struct fc_bsg_request *bsg_request = job->request;5260	struct fc_bsg_reply *bsg_reply = job->reply;5261	struct lpfc_bsg_get_fwlog_req *ras_req;5262	u32 rd_offset, rd_index, offset;5263	void *src, *fwlog_buff;5264	struct lpfc_ras_fwlog *ras_fwlog = NULL;5265	struct lpfc_dmabuf *dmabuf, *next;5266	int rc = 0;5267 5268	ras_fwlog = &phba->ras_fwlog;5269 5270	rc = lpfc_check_fwlog_support(phba);5271	if (rc)5272		goto ras_job_error;5273 5274	/* Logging to be stopped before reading */5275	spin_lock_irq(&phba->ras_fwlog_lock);5276	if (ras_fwlog->state == ACTIVE) {5277		spin_unlock_irq(&phba->ras_fwlog_lock);5278		rc = -EINPROGRESS;5279		goto ras_job_error;5280	}5281	spin_unlock_irq(&phba->ras_fwlog_lock);5282 5283	if (job->request_len <5284	    sizeof(struct fc_bsg_request) +5285	    sizeof(struct lpfc_bsg_get_fwlog_req)) {5286		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5287				"6184 Received RAS_LOG request "5288				"below minimum size\n");5289		rc = -EINVAL;5290		goto ras_job_error;5291	}5292 5293	ras_req = (struct lpfc_bsg_get_fwlog_req *)5294		bsg_request->rqst_data.h_vendor.vendor_cmd;5295	rd_offset = ras_req->read_offset;5296 5297	/* Allocate memory to read fw log*/5298	fwlog_buff = vmalloc(ras_req->read_size);5299	if (!fwlog_buff) {5300		rc = -ENOMEM;5301		goto ras_job_error;5302	}5303 5304	rd_index = (rd_offset / LPFC_RAS_MAX_ENTRY_SIZE);5305	offset = (rd_offset % LPFC_RAS_MAX_ENTRY_SIZE);5306 5307	list_for_each_entry_safe(dmabuf, next,5308			      &ras_fwlog->fwlog_buff_list, list) {5309 5310		if (dmabuf->buffer_tag < rd_index)5311			continue;5312 5313		src = dmabuf->virt + offset;5314		memcpy(fwlog_buff, src, ras_req->read_size);5315		break;5316	}5317 5318	bsg_reply->reply_payload_rcv_len =5319		sg_copy_from_buffer(job->reply_payload.sg_list,5320				    job->reply_payload.sg_cnt,5321				    fwlog_buff, ras_req->read_size);5322 5323	vfree(fwlog_buff);5324 5325ras_job_error:5326	bsg_reply->result = rc;5327	if (!rc)5328		bsg_job_done(job, bsg_reply->result,5329			     bsg_reply->reply_payload_rcv_len);5330 5331	return rc;5332}5333 5334static int5335lpfc_get_trunk_info(struct bsg_job *job)5336{5337	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));5338	struct lpfc_hba *phba = vport->phba;5339	struct fc_bsg_reply *bsg_reply = job->reply;5340	struct lpfc_trunk_info *event_reply;5341	int rc = 0;5342 5343	if (job->request_len <5344	    sizeof(struct fc_bsg_request) + sizeof(struct get_trunk_info_req)) {5345		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5346				"2744 Received GET TRUNK _INFO request below "5347				"minimum size\n");5348		rc = -EINVAL;5349		goto job_error;5350	}5351 5352	event_reply = (struct lpfc_trunk_info *)5353		bsg_reply->reply_data.vendor_reply.vendor_rsp;5354 5355	if (job->reply_len < sizeof(*bsg_reply) + sizeof(*event_reply)) {5356		lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,5357				"2728 Received GET TRUNK _INFO reply below "5358				"minimum size\n");5359		rc = -EINVAL;5360		goto job_error;5361	}5362	if (event_reply == NULL) {5363		rc = -EINVAL;5364		goto job_error;5365	}5366 5367	bsg_bf_set(lpfc_trunk_info_link_status, event_reply,5368		   (phba->link_state >= LPFC_LINK_UP) ? 1 : 0);5369 5370	bsg_bf_set(lpfc_trunk_info_trunk_active0, event_reply,5371		   (phba->trunk_link.link0.state == LPFC_LINK_UP) ? 1 : 0);5372 5373	bsg_bf_set(lpfc_trunk_info_trunk_active1, event_reply,5374		   (phba->trunk_link.link1.state == LPFC_LINK_UP) ? 1 : 0);5375 5376	bsg_bf_set(lpfc_trunk_info_trunk_active2, event_reply,5377		   (phba->trunk_link.link2.state == LPFC_LINK_UP) ? 1 : 0);5378 5379	bsg_bf_set(lpfc_trunk_info_trunk_active3, event_reply,5380		   (phba->trunk_link.link3.state == LPFC_LINK_UP) ? 1 : 0);5381 5382	bsg_bf_set(lpfc_trunk_info_trunk_config0, event_reply,5383		   bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba));5384 5385	bsg_bf_set(lpfc_trunk_info_trunk_config1, event_reply,5386		   bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba));5387 5388	bsg_bf_set(lpfc_trunk_info_trunk_config2, event_reply,5389		   bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba));5390 5391	bsg_bf_set(lpfc_trunk_info_trunk_config3, event_reply,5392		   bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba));5393 5394	event_reply->port_speed = phba->sli4_hba.link_state.speed / 1000;5395	event_reply->logical_speed =5396				phba->sli4_hba.link_state.logical_speed / 1000;5397job_error:5398	bsg_reply->result = rc;5399	if (!rc)5400		bsg_job_done(job, bsg_reply->result,5401			     bsg_reply->reply_payload_rcv_len);5402	return rc;5403 5404}5405 5406static int5407lpfc_get_cgnbuf_info(struct bsg_job *job)5408{5409	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));5410	struct lpfc_hba *phba = vport->phba;5411	struct fc_bsg_request *bsg_request = job->request;5412	struct fc_bsg_reply *bsg_reply = job->reply;5413	struct get_cgnbuf_info_req *cgnbuf_req;5414	struct lpfc_cgn_info *cp;5415	uint8_t *cgn_buff;5416	size_t size, cinfosz;5417	int  rc = 0;5418 5419	if (job->request_len < sizeof(struct fc_bsg_request) +5420	    sizeof(struct get_cgnbuf_info_req)) {5421		rc = -ENOMEM;5422		goto job_exit;5423	}5424 5425	if (!phba->sli4_hba.pc_sli4_params.cmf) {5426		rc = -ENOENT;5427		goto job_exit;5428	}5429 5430	if (!phba->cgn_i || !phba->cgn_i->virt) {5431		rc = -ENOENT;5432		goto job_exit;5433	}5434 5435	cp = phba->cgn_i->virt;5436	if (cp->cgn_info_version < LPFC_CGN_INFO_V3) {5437		rc = -EPERM;5438		goto job_exit;5439	}5440 5441	cgnbuf_req = (struct get_cgnbuf_info_req *)5442		bsg_request->rqst_data.h_vendor.vendor_cmd;5443 5444	/* For reset or size == 0 */5445	bsg_reply->reply_payload_rcv_len = 0;5446 5447	if (cgnbuf_req->reset == LPFC_BSG_CGN_RESET_STAT) {5448		lpfc_init_congestion_stat(phba);5449		goto job_exit;5450	}5451 5452	/* We don't want to include the CRC at the end */5453	cinfosz = sizeof(struct lpfc_cgn_info) - sizeof(uint32_t);5454 5455	size = cgnbuf_req->read_size;5456	if (!size)5457		goto job_exit;5458 5459	if (size < cinfosz) {5460		/* Just copy back what we can */5461		cinfosz = size;5462		rc = -E2BIG;5463	}5464 5465	/* Allocate memory to read congestion info */5466	cgn_buff = vmalloc(cinfosz);5467	if (!cgn_buff) {5468		rc = -ENOMEM;5469		goto job_exit;5470	}5471 5472	memcpy(cgn_buff, cp, cinfosz);5473 5474	bsg_reply->reply_payload_rcv_len =5475		sg_copy_from_buffer(job->reply_payload.sg_list,5476				    job->reply_payload.sg_cnt,5477				    cgn_buff, cinfosz);5478 5479	vfree(cgn_buff);5480 5481job_exit:5482	bsg_reply->result = rc;5483	if (!rc)5484		bsg_job_done(job, bsg_reply->result,5485			     bsg_reply->reply_payload_rcv_len);5486	else5487		lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,5488				"2724 GET CGNBUF error: %d\n", rc);5489	return rc;5490}5491 5492/**5493 * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job5494 * @job: fc_bsg_job to handle5495 **/5496static int5497lpfc_bsg_hst_vendor(struct bsg_job *job)5498{5499	struct fc_bsg_request *bsg_request = job->request;5500	struct fc_bsg_reply *bsg_reply = job->reply;5501	int command = bsg_request->rqst_data.h_vendor.vendor_cmd[0];5502	int rc;5503 5504	switch (command) {5505	case LPFC_BSG_VENDOR_SET_CT_EVENT:5506		rc = lpfc_bsg_hba_set_event(job);5507		break;5508	case LPFC_BSG_VENDOR_GET_CT_EVENT:5509		rc = lpfc_bsg_hba_get_event(job);5510		break;5511	case LPFC_BSG_VENDOR_SEND_MGMT_RESP:5512		rc = lpfc_bsg_send_mgmt_rsp(job);5513		break;5514	case LPFC_BSG_VENDOR_DIAG_MODE:5515		rc = lpfc_bsg_diag_loopback_mode(job);5516		break;5517	case LPFC_BSG_VENDOR_DIAG_MODE_END:5518		rc = lpfc_sli4_bsg_diag_mode_end(job);5519		break;5520	case LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK:5521		rc = lpfc_bsg_diag_loopback_run(job);5522		break;5523	case LPFC_BSG_VENDOR_LINK_DIAG_TEST:5524		rc = lpfc_sli4_bsg_link_diag_test(job);5525		break;5526	case LPFC_BSG_VENDOR_GET_MGMT_REV:5527		rc = lpfc_bsg_get_dfc_rev(job);5528		break;5529	case LPFC_BSG_VENDOR_MBOX:5530		rc = lpfc_bsg_mbox_cmd(job);5531		break;5532	case LPFC_BSG_VENDOR_FORCED_LINK_SPEED:5533		rc = lpfc_forced_link_speed(job);5534		break;5535	case LPFC_BSG_VENDOR_RAS_GET_LWPD:5536		rc = lpfc_bsg_get_ras_lwpd(job);5537		break;5538	case LPFC_BSG_VENDOR_RAS_GET_FWLOG:5539		rc = lpfc_bsg_get_ras_fwlog(job);5540		break;5541	case LPFC_BSG_VENDOR_RAS_GET_CONFIG:5542		rc = lpfc_bsg_get_ras_config(job);5543		break;5544	case LPFC_BSG_VENDOR_RAS_SET_CONFIG:5545		rc = lpfc_bsg_set_ras_config(job);5546		break;5547	case LPFC_BSG_VENDOR_GET_TRUNK_INFO:5548		rc = lpfc_get_trunk_info(job);5549		break;5550	case LPFC_BSG_VENDOR_GET_CGNBUF_INFO:5551		rc = lpfc_get_cgnbuf_info(job);5552		break;5553	default:5554		rc = -EINVAL;5555		bsg_reply->reply_payload_rcv_len = 0;5556		/* make error code available to userspace */5557		bsg_reply->result = rc;5558		break;5559	}5560 5561	return rc;5562}5563 5564/**5565 * lpfc_bsg_request - handle a bsg request from the FC transport5566 * @job: bsg_job to handle5567 **/5568int5569lpfc_bsg_request(struct bsg_job *job)5570{5571	struct fc_bsg_request *bsg_request = job->request;5572	struct fc_bsg_reply *bsg_reply = job->reply;5573	uint32_t msgcode;5574	int rc;5575 5576	msgcode = bsg_request->msgcode;5577	switch (msgcode) {5578	case FC_BSG_HST_VENDOR:5579		rc = lpfc_bsg_hst_vendor(job);5580		break;5581	case FC_BSG_RPT_ELS:5582		rc = lpfc_bsg_rport_els(job);5583		break;5584	case FC_BSG_RPT_CT:5585		rc = lpfc_bsg_send_mgmt_cmd(job);5586		break;5587	default:5588		rc = -EINVAL;5589		bsg_reply->reply_payload_rcv_len = 0;5590		/* make error code available to userspace */5591		bsg_reply->result = rc;5592		break;5593	}5594 5595	return rc;5596}5597 5598/**5599 * lpfc_bsg_timeout - handle timeout of a bsg request from the FC transport5600 * @job: bsg_job that has timed out5601 *5602 * This function just aborts the job's IOCB.  The aborted IOCB will return to5603 * the waiting function which will handle passing the error back to userspace5604 **/5605int5606lpfc_bsg_timeout(struct bsg_job *job)5607{5608	struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));5609	struct lpfc_hba *phba = vport->phba;5610	struct lpfc_iocbq *cmdiocb;5611	struct lpfc_sli_ring *pring;5612	struct bsg_job_data *dd_data;5613	unsigned long flags;5614	int rc = 0;5615	LIST_HEAD(completions);5616	struct lpfc_iocbq *check_iocb, *next_iocb;5617 5618	pring = lpfc_phba_elsring(phba);5619	if (unlikely(!pring))5620		return -EIO;5621 5622	/* if job's driver data is NULL, the command completed or is in the5623	 * the process of completing.  In this case, return status to request5624	 * so the timeout is retried.  This avoids double completion issues5625	 * and the request will be pulled off the timer queue when the5626	 * command's completion handler executes.  Otherwise, prevent the5627	 * command's completion handler from executing the job done callback5628	 * and continue processing to abort the outstanding the command.5629	 */5630 5631	spin_lock_irqsave(&phba->ct_ev_lock, flags);5632	dd_data = (struct bsg_job_data *)job->dd_data;5633	if (dd_data) {5634		dd_data->set_job = NULL;5635		job->dd_data = NULL;5636	} else {5637		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);5638		return -EAGAIN;5639	}5640 5641	switch (dd_data->type) {5642	case TYPE_IOCB:5643		/* Check to see if IOCB was issued to the port or not. If not,5644		 * remove it from the txq queue and call cancel iocbs.5645		 * Otherwise, call abort iotag5646		 */5647		cmdiocb = dd_data->context_un.iocb.cmdiocbq;5648		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);5649 5650		spin_lock_irqsave(&phba->hbalock, flags);5651		/* make sure the I/O abort window is still open */5652		if (!(cmdiocb->cmd_flag & LPFC_IO_CMD_OUTSTANDING)) {5653			spin_unlock_irqrestore(&phba->hbalock, flags);5654			return -EAGAIN;5655		}5656		list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,5657					 list) {5658			if (check_iocb == cmdiocb) {5659				list_move_tail(&check_iocb->list, &completions);5660				break;5661			}5662		}5663		if (list_empty(&completions))5664			lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb, NULL);5665		spin_unlock_irqrestore(&phba->hbalock, flags);5666		if (!list_empty(&completions)) {5667			lpfc_sli_cancel_iocbs(phba, &completions,5668					      IOSTAT_LOCAL_REJECT,5669					      IOERR_SLI_ABORTED);5670		}5671		break;5672 5673	case TYPE_EVT:5674		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);5675		break;5676 5677	case TYPE_MBOX:5678		/* Update the ext buf ctx state if needed */5679 5680		if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)5681			phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;5682		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);5683		break;5684	default:5685		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);5686		break;5687	}5688 5689	/* scsi transport fc fc_bsg_job_timeout expects a zero return code,5690	 * otherwise an error message will be displayed on the console5691	 * so always return success (zero)5692	 */5693	return rc;5694}5695