xref: /linux/drivers/scsi/be2iscsi/be_mgmt.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1942b7654SJitendra Bhivare /*
294583217SKetan Mukadam  * This file is part of the Emulex Linux Device Driver for Enterprise iSCSI
394583217SKetan Mukadam  * Host Bus Adapters. Refer to the README file included with this package
494583217SKetan Mukadam  * for driver version and adapter compatibility.
56733b39aSJayamohan Kallickal  *
694583217SKetan Mukadam  * Copyright (c) 2018 Broadcom. All Rights Reserved.
794583217SKetan Mukadam  * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
894583217SKetan Mukadam  *
994583217SKetan Mukadam  * This program is free software; you can redistribute it and/or modify it
1094583217SKetan Mukadam  * under the terms of version 2 of the GNU General Public License as published
1194583217SKetan Mukadam  * by the Free Software Foundation.
1294583217SKetan Mukadam  *
1394583217SKetan Mukadam  * This program is distributed in the hope that it will be useful. ALL EXPRESS
1494583217SKetan Mukadam  * OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
1594583217SKetan Mukadam  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
1694583217SKetan Mukadam  * OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH
1794583217SKetan Mukadam  * DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
1894583217SKetan Mukadam  * See the GNU General Public License for more details, a copy of which
1994583217SKetan Mukadam  * can be found in the file COPYING included with this package.
206733b39aSJayamohan Kallickal  *
216733b39aSJayamohan Kallickal  * Contact Information:
2260f36e04SJitendra Bhivare  * linux-drivers@broadcom.com
236733b39aSJayamohan Kallickal  *
246733b39aSJayamohan Kallickal  */
256733b39aSJayamohan Kallickal 
26ffce3e2eSJayamohan Kallickal #include <linux/bsg-lib.h>
27ffce3e2eSJayamohan Kallickal #include <scsi/scsi_transport_iscsi.h>
28ffce3e2eSJayamohan Kallickal #include <scsi/scsi_bsg_iscsi.h>
296733b39aSJayamohan Kallickal #include "be_mgmt.h"
306733b39aSJayamohan Kallickal #include "be_iscsi.h"
317a158003SJohn Soni Jose #include "be_main.h"
327a158003SJohn Soni Jose 
mgmt_vendor_specific_fw_cmd(struct be_ctrl_info * ctrl,struct beiscsi_hba * phba,struct bsg_job * job,struct be_dma_mem * nonemb_cmd)33ffce3e2eSJayamohan Kallickal unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
34ffce3e2eSJayamohan Kallickal 					 struct beiscsi_hba *phba,
35ffce3e2eSJayamohan Kallickal 					 struct bsg_job *job,
36ffce3e2eSJayamohan Kallickal 					 struct be_dma_mem *nonemb_cmd)
37ffce3e2eSJayamohan Kallickal {
38daa8dc08SJayamohan Kallickal 	struct be_mcc_wrb *wrb;
39daa8dc08SJayamohan Kallickal 	struct be_sge *mcc_sge;
40ffce3e2eSJayamohan Kallickal 	unsigned int tag = 0;
41ffce3e2eSJayamohan Kallickal 	struct iscsi_bsg_request *bsg_req = job->request;
42ffce3e2eSJayamohan Kallickal 	struct be_bsg_vendor_cmd *req = nonemb_cmd->va;
43ffce3e2eSJayamohan Kallickal 	unsigned short region, sector_size, sector, offset;
44ffce3e2eSJayamohan Kallickal 
45ffce3e2eSJayamohan Kallickal 	nonemb_cmd->size = job->request_payload.payload_len;
46ffce3e2eSJayamohan Kallickal 	memset(nonemb_cmd->va, 0, nonemb_cmd->size);
47ffce3e2eSJayamohan Kallickal 	region =  bsg_req->rqst_data.h_vendor.vendor_cmd[1];
48ffce3e2eSJayamohan Kallickal 	sector_size =  bsg_req->rqst_data.h_vendor.vendor_cmd[2];
49ffce3e2eSJayamohan Kallickal 	sector =  bsg_req->rqst_data.h_vendor.vendor_cmd[3];
50ffce3e2eSJayamohan Kallickal 	offset =  bsg_req->rqst_data.h_vendor.vendor_cmd[4];
51ffce3e2eSJayamohan Kallickal 	req->region = region;
52ffce3e2eSJayamohan Kallickal 	req->sector = sector;
53ffce3e2eSJayamohan Kallickal 	req->offset = offset;
54ffce3e2eSJayamohan Kallickal 
55c03a50f7SJitendra Bhivare 	if (mutex_lock_interruptible(&ctrl->mbox_lock))
56c03a50f7SJitendra Bhivare 		return 0;
57ffce3e2eSJayamohan Kallickal 	switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
58ffce3e2eSJayamohan Kallickal 	case BEISCSI_WRITE_FLASH:
59ffce3e2eSJayamohan Kallickal 		offset = sector * sector_size + offset;
60ffce3e2eSJayamohan Kallickal 		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
61ffce3e2eSJayamohan Kallickal 				   OPCODE_COMMON_WRITE_FLASH, sizeof(*req));
62ffce3e2eSJayamohan Kallickal 		sg_copy_to_buffer(job->request_payload.sg_list,
63ffce3e2eSJayamohan Kallickal 				  job->request_payload.sg_cnt,
64ffce3e2eSJayamohan Kallickal 				  nonemb_cmd->va + offset, job->request_len);
65ffce3e2eSJayamohan Kallickal 		break;
66ffce3e2eSJayamohan Kallickal 	case BEISCSI_READ_FLASH:
67ffce3e2eSJayamohan Kallickal 		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
68ffce3e2eSJayamohan Kallickal 			   OPCODE_COMMON_READ_FLASH, sizeof(*req));
69ffce3e2eSJayamohan Kallickal 		break;
70ffce3e2eSJayamohan Kallickal 	default:
7199bc5d55SJohn Soni Jose 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
7299bc5d55SJohn Soni Jose 			    "BG_%d : Unsupported cmd = 0x%x\n\n",
7399bc5d55SJohn Soni Jose 			    bsg_req->rqst_data.h_vendor.vendor_cmd[0]);
7499bc5d55SJohn Soni Jose 
75c03a50f7SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
76c5bf8889SJitendra Bhivare 		return -EPERM;
77ffce3e2eSJayamohan Kallickal 	}
78ffce3e2eSJayamohan Kallickal 
79090e2184SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
80090e2184SJitendra Bhivare 	if (!wrb) {
81c03a50f7SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
82090e2184SJitendra Bhivare 		return 0;
83ffce3e2eSJayamohan Kallickal 	}
84ffce3e2eSJayamohan Kallickal 
85daa8dc08SJayamohan Kallickal 	mcc_sge = nonembedded_sgl(wrb);
86ffce3e2eSJayamohan Kallickal 	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false,
87ffce3e2eSJayamohan Kallickal 			   job->request_payload.sg_cnt);
88ffce3e2eSJayamohan Kallickal 	mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
89ffce3e2eSJayamohan Kallickal 	mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
90ffce3e2eSJayamohan Kallickal 	mcc_sge->len = cpu_to_le32(nonemb_cmd->size);
91ffce3e2eSJayamohan Kallickal 
92cdde6682SJitendra Bhivare 	be_mcc_notify(phba, tag);
93ffce3e2eSJayamohan Kallickal 
94c03a50f7SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
95ffce3e2eSJayamohan Kallickal 	return tag;
96ffce3e2eSJayamohan Kallickal }
97ffce3e2eSJayamohan Kallickal 
981e4be6ffSJayamohan Kallickal /**
991e4be6ffSJayamohan Kallickal  * mgmt_open_connection()- Establish a TCP CXN
1007405edfdSLee Jones  * @phba: driver priv structure
1011e4be6ffSJayamohan Kallickal  * @dst_addr: Destination Address
1021e4be6ffSJayamohan Kallickal  * @beiscsi_ep: ptr to device endpoint struct
1031e4be6ffSJayamohan Kallickal  * @nonemb_cmd: ptr to memory allocated for command
1041e4be6ffSJayamohan Kallickal  *
1051e4be6ffSJayamohan Kallickal  * return
1061e4be6ffSJayamohan Kallickal  *	Success: Tag number of the MBX Command issued
1071e4be6ffSJayamohan Kallickal  *	Failure: Error code
1081e4be6ffSJayamohan Kallickal  **/
mgmt_open_connection(struct beiscsi_hba * phba,struct sockaddr * dst_addr,struct beiscsi_endpoint * beiscsi_ep,struct be_dma_mem * nonemb_cmd)1096733b39aSJayamohan Kallickal int mgmt_open_connection(struct beiscsi_hba *phba,
1106733b39aSJayamohan Kallickal 			 struct sockaddr *dst_addr,
1113cbb7a74SJayamohan Kallickal 			 struct beiscsi_endpoint *beiscsi_ep,
1123cbb7a74SJayamohan Kallickal 			 struct be_dma_mem *nonemb_cmd)
1136733b39aSJayamohan Kallickal {
1146733b39aSJayamohan Kallickal 	struct hwi_controller *phwi_ctrlr;
1156733b39aSJayamohan Kallickal 	struct hwi_context_memory *phwi_context;
1166733b39aSJayamohan Kallickal 	struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;
1176733b39aSJayamohan Kallickal 	struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
1186733b39aSJayamohan Kallickal 	struct be_ctrl_info *ctrl = &phba->ctrl;
119756d29c8SJayamohan Kallickal 	struct be_mcc_wrb *wrb;
120b3c202dcSJayamohan Kallickal 	struct tcp_connect_and_offload_in_v1 *req;
1216733b39aSJayamohan Kallickal 	unsigned short def_hdr_id;
1226733b39aSJayamohan Kallickal 	unsigned short def_data_id;
1236733b39aSJayamohan Kallickal 	struct phys_addr template_address = { 0, 0 };
1246733b39aSJayamohan Kallickal 	struct phys_addr *ptemplate_address;
125756d29c8SJayamohan Kallickal 	unsigned int tag = 0;
1261e4be6ffSJayamohan Kallickal 	unsigned int i, ulp_num;
1276733b39aSJayamohan Kallickal 	unsigned short cid = beiscsi_ep->ep_cid;
1283cbb7a74SJayamohan Kallickal 	struct be_sge *sge;
1296733b39aSJayamohan Kallickal 
130291fef26SJitendra Bhivare 	if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) {
131291fef26SJitendra Bhivare 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
132291fef26SJitendra Bhivare 			    "BG_%d : unknown addr family %d\n",
133291fef26SJitendra Bhivare 			    dst_addr->sa_family);
1348dd998e6SJitendra Bhivare 		return 0;
135291fef26SJitendra Bhivare 	}
136291fef26SJitendra Bhivare 
1376733b39aSJayamohan Kallickal 	phwi_ctrlr = phba->phwi_ctrlr;
1386733b39aSJayamohan Kallickal 	phwi_context = phwi_ctrlr->phwi_ctxt;
1391e4be6ffSJayamohan Kallickal 
1401e4be6ffSJayamohan Kallickal 	ulp_num = phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(cid)].ulp_num;
1411e4be6ffSJayamohan Kallickal 
1421e4be6ffSJayamohan Kallickal 	def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba, ulp_num);
1431e4be6ffSJayamohan Kallickal 	def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba, ulp_num);
1446733b39aSJayamohan Kallickal 
1456733b39aSJayamohan Kallickal 	ptemplate_address = &template_address;
1466733b39aSJayamohan Kallickal 	ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
147c03a50f7SJitendra Bhivare 	if (mutex_lock_interruptible(&ctrl->mbox_lock))
148c03a50f7SJitendra Bhivare 		return 0;
149090e2184SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
150090e2184SJitendra Bhivare 	if (!wrb) {
151c03a50f7SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
152090e2184SJitendra Bhivare 		return 0;
153756d29c8SJayamohan Kallickal 	}
1543cbb7a74SJayamohan Kallickal 
155090e2184SJitendra Bhivare 	sge = nonembedded_sgl(wrb);
1563cbb7a74SJayamohan Kallickal 	req = nonemb_cmd->va;
1573cbb7a74SJayamohan Kallickal 	memset(req, 0, sizeof(*req));
1586733b39aSJayamohan Kallickal 
159b3c202dcSJayamohan Kallickal 	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
1606733b39aSJayamohan Kallickal 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
1616733b39aSJayamohan Kallickal 			   OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
162b3c202dcSJayamohan Kallickal 			   nonemb_cmd->size);
1636733b39aSJayamohan Kallickal 	if (dst_addr->sa_family == PF_INET) {
1646733b39aSJayamohan Kallickal 		__be32 s_addr = daddr_in->sin_addr.s_addr;
165290aa376SJitendra Bhivare 		req->ip_address.ip_type = BEISCSI_IP_TYPE_V4;
1660e43895eSMike Christie 		req->ip_address.addr[0] = s_addr & 0x000000ff;
1670e43895eSMike Christie 		req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8;
1680e43895eSMike Christie 		req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16;
1690e43895eSMike Christie 		req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24;
1706733b39aSJayamohan Kallickal 		req->tcp_port = ntohs(daddr_in->sin_port);
1716733b39aSJayamohan Kallickal 		beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
1726733b39aSJayamohan Kallickal 		beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
173290aa376SJitendra Bhivare 		beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V4;
174291fef26SJitendra Bhivare 	} else {
175291fef26SJitendra Bhivare 		/* else its PF_INET6 family */
176290aa376SJitendra Bhivare 		req->ip_address.ip_type = BEISCSI_IP_TYPE_V6;
1770e43895eSMike Christie 		memcpy(&req->ip_address.addr,
1786733b39aSJayamohan Kallickal 		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
1796733b39aSJayamohan Kallickal 		req->tcp_port = ntohs(daddr_in6->sin6_port);
1806733b39aSJayamohan Kallickal 		beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
1816733b39aSJayamohan Kallickal 		memcpy(&beiscsi_ep->dst6_addr,
1826733b39aSJayamohan Kallickal 		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
183290aa376SJitendra Bhivare 		beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V6;
1846733b39aSJayamohan Kallickal 	}
1856733b39aSJayamohan Kallickal 	req->cid = cid;
186bfead3b2SJayamohan Kallickal 	i = phba->nxt_cqid++;
187bfead3b2SJayamohan Kallickal 	if (phba->nxt_cqid == phba->num_cpus)
188bfead3b2SJayamohan Kallickal 		phba->nxt_cqid = 0;
189bfead3b2SJayamohan Kallickal 	req->cq_id = phwi_context->be_cq[i].id;
19099bc5d55SJohn Soni Jose 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
19199bc5d55SJohn Soni Jose 		    "BG_%d : i=%d cq_id=%d\n", i, req->cq_id);
1926733b39aSJayamohan Kallickal 	req->defq_id = def_hdr_id;
1936733b39aSJayamohan Kallickal 	req->hdr_ring_id = def_hdr_id;
1946733b39aSJayamohan Kallickal 	req->data_ring_id = def_data_id;
1956733b39aSJayamohan Kallickal 	req->do_offload = 1;
1966733b39aSJayamohan Kallickal 	req->dataout_template_pa.lo = ptemplate_address->lo;
1976733b39aSJayamohan Kallickal 	req->dataout_template_pa.hi = ptemplate_address->hi;
1983cbb7a74SJayamohan Kallickal 	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
1993cbb7a74SJayamohan Kallickal 	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
2003cbb7a74SJayamohan Kallickal 	sge->len = cpu_to_le32(nonemb_cmd->size);
201b3c202dcSJayamohan Kallickal 
202b3c202dcSJayamohan Kallickal 	if (!is_chip_be2_be3r(phba)) {
203b3c202dcSJayamohan Kallickal 		req->hdr.version = MBX_CMD_VER1;
2041b7a7ddcSJitendra Bhivare 		req->tcp_window_size = 0x8000;
205b3c202dcSJayamohan Kallickal 		req->tcp_window_scale_count = 2;
206b3c202dcSJayamohan Kallickal 	}
207b3c202dcSJayamohan Kallickal 
208cdde6682SJitendra Bhivare 	be_mcc_notify(phba, tag);
209c03a50f7SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
210756d29c8SJayamohan Kallickal 	return tag;
2116733b39aSJayamohan Kallickal }
212bfead3b2SJayamohan Kallickal 
2137405edfdSLee Jones /**
214a39e9f71SJitendra Bhivare  * beiscsi_exec_nemb_cmd()- execute non-embedded MBX cmd
215a39e9f71SJitendra Bhivare  * @phba: driver priv structure
216a39e9f71SJitendra Bhivare  * @nonemb_cmd: DMA address of the MBX command to be issued
217a39e9f71SJitendra Bhivare  * @cbfn: callback func on MCC completion
218a39e9f71SJitendra Bhivare  * @resp_buf: buffer to copy the MBX cmd response
219a39e9f71SJitendra Bhivare  * @resp_buf_len: response length to be copied
220e175defeSJohn Soni Jose  *
221e175defeSJohn Soni Jose  **/
beiscsi_exec_nemb_cmd(struct beiscsi_hba * phba,struct be_dma_mem * nonemb_cmd,void (* cbfn)(struct beiscsi_hba *,unsigned int),void * resp_buf,u32 resp_buf_len)222a39e9f71SJitendra Bhivare static int beiscsi_exec_nemb_cmd(struct beiscsi_hba *phba,
223a39e9f71SJitendra Bhivare 				 struct be_dma_mem *nonemb_cmd,
224a39e9f71SJitendra Bhivare 				 void (*cbfn)(struct beiscsi_hba *,
225a39e9f71SJitendra Bhivare 					      unsigned int),
226a39e9f71SJitendra Bhivare 				 void *resp_buf, u32 resp_buf_len)
2270e43895eSMike Christie {
2280e43895eSMike Christie 	struct be_ctrl_info *ctrl = &phba->ctrl;
229daa8dc08SJayamohan Kallickal 	struct be_mcc_wrb *wrb;
2300e43895eSMike Christie 	struct be_sge *sge;
2310e43895eSMike Christie 	unsigned int tag;
2320e43895eSMike Christie 	int rc = 0;
2330e43895eSMike Christie 
234c03a50f7SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
235090e2184SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
236090e2184SJitendra Bhivare 	if (!wrb) {
237c03a50f7SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
2387b0ddc13SMike Christie 		return -ENOMEM;
239756d29c8SJayamohan Kallickal 	}
240daa8dc08SJayamohan Kallickal 
2410e43895eSMike Christie 	sge = nonembedded_sgl(wrb);
2420e43895eSMike Christie 	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
2430e43895eSMike Christie 	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
244e175defeSJohn Soni Jose 	sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma));
2450e43895eSMike Christie 	sge->len = cpu_to_le32(nonemb_cmd->size);
246bfead3b2SJayamohan Kallickal 
247a39e9f71SJitendra Bhivare 	if (cbfn) {
248a39e9f71SJitendra Bhivare 		struct be_dma_mem *tag_mem;
249a39e9f71SJitendra Bhivare 
250a39e9f71SJitendra Bhivare 		set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);
251a39e9f71SJitendra Bhivare 		ctrl->ptag_state[tag].cbfn = cbfn;
252a39e9f71SJitendra Bhivare 		tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;
253a39e9f71SJitendra Bhivare 
254a39e9f71SJitendra Bhivare 		/* store DMA mem to be freed in callback */
255a39e9f71SJitendra Bhivare 		tag_mem->size = nonemb_cmd->size;
256a39e9f71SJitendra Bhivare 		tag_mem->va = nonemb_cmd->va;
257a39e9f71SJitendra Bhivare 		tag_mem->dma = nonemb_cmd->dma;
258a39e9f71SJitendra Bhivare 	}
259cdde6682SJitendra Bhivare 	be_mcc_notify(phba, tag);
260c03a50f7SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
2610e43895eSMike Christie 
262a39e9f71SJitendra Bhivare 	/* with cbfn set, its async cmd, don't wait */
263a39e9f71SJitendra Bhivare 	if (cbfn)
264a39e9f71SJitendra Bhivare 		return 0;
265a39e9f71SJitendra Bhivare 
26688840332SJitendra Bhivare 	rc = beiscsi_mccq_compl_wait(phba, tag, NULL, nonemb_cmd);
267bfead3b2SJayamohan Kallickal 
268a39e9f71SJitendra Bhivare 	/* copy the response, if any */
2690e43895eSMike Christie 	if (resp_buf)
2700e43895eSMike Christie 		memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
2710e43895eSMike Christie 	return rc;
2720e43895eSMike Christie }
2730e43895eSMike Christie 
beiscsi_prep_nemb_cmd(struct beiscsi_hba * phba,struct be_dma_mem * cmd,u8 subsystem,u8 opcode,u32 size)274a39e9f71SJitendra Bhivare static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,
275a39e9f71SJitendra Bhivare 				 struct be_dma_mem *cmd,
276a39e9f71SJitendra Bhivare 				 u8 subsystem, u8 opcode, u32 size)
2770e43895eSMike Christie {
278750afb08SLuis Chamberlain 	cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
27926a4c991SChristoph Hellwig 				     GFP_KERNEL);
2800e43895eSMike Christie 	if (!cmd->va) {
28199bc5d55SJohn Soni Jose 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
28299bc5d55SJohn Soni Jose 			    "BG_%d : Failed to allocate memory for if info\n");
2830e43895eSMike Christie 		return -ENOMEM;
2840e43895eSMike Christie 	}
2850e43895eSMike Christie 	cmd->size = size;
286a39e9f71SJitendra Bhivare 	be_cmd_hdr_prepare(cmd->va, subsystem, opcode, size);
287db02aea9SJitendra Bhivare 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
288a39e9f71SJitendra Bhivare 		    "BG_%d : subsystem %u cmd %u size %u\n",
289a39e9f71SJitendra Bhivare 		    subsystem, opcode, size);
2900e43895eSMike Christie 	return 0;
2910e43895eSMike Christie }
2920e43895eSMike Christie 
beiscsi_free_nemb_cmd(struct beiscsi_hba * phba,struct be_dma_mem * cmd,int rc)2937b0ddc13SMike Christie static void beiscsi_free_nemb_cmd(struct beiscsi_hba *phba,
2947b0ddc13SMike Christie 				  struct be_dma_mem *cmd, int rc)
2957b0ddc13SMike Christie {
2967b0ddc13SMike Christie 	/*
2977b0ddc13SMike Christie 	 * If FW is busy the DMA buffer is saved with the tag. When the cmd
2987b0ddc13SMike Christie 	 * completes this buffer is freed.
2997b0ddc13SMike Christie 	 */
3007b0ddc13SMike Christie 	if (rc == -EBUSY)
3017b0ddc13SMike Christie 		return;
3027b0ddc13SMike Christie 
3037b0ddc13SMike Christie 	dma_free_coherent(&phba->ctrl.pdev->dev, cmd->size, cmd->va, cmd->dma);
3047b0ddc13SMike Christie }
3057b0ddc13SMike Christie 
__beiscsi_eq_delay_compl(struct beiscsi_hba * phba,unsigned int tag)306a39e9f71SJitendra Bhivare static void __beiscsi_eq_delay_compl(struct beiscsi_hba *phba, unsigned int tag)
307a39e9f71SJitendra Bhivare {
308a39e9f71SJitendra Bhivare 	struct be_dma_mem *tag_mem;
309a39e9f71SJitendra Bhivare 
310a39e9f71SJitendra Bhivare 	/* status is ignored */
311a39e9f71SJitendra Bhivare 	__beiscsi_mcc_compl_status(phba, tag, NULL, NULL);
312a39e9f71SJitendra Bhivare 	tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;
313a39e9f71SJitendra Bhivare 	if (tag_mem->size) {
31426a4c991SChristoph Hellwig 		dma_free_coherent(&phba->pcidev->dev, tag_mem->size,
315a39e9f71SJitendra Bhivare 				    tag_mem->va, tag_mem->dma);
316a39e9f71SJitendra Bhivare 		tag_mem->size = 0;
317a39e9f71SJitendra Bhivare 	}
318a39e9f71SJitendra Bhivare }
319a39e9f71SJitendra Bhivare 
beiscsi_modify_eq_delay(struct beiscsi_hba * phba,struct be_set_eqd * set_eqd,int num)320a39e9f71SJitendra Bhivare int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,
321a39e9f71SJitendra Bhivare 			    struct be_set_eqd *set_eqd, int num)
322a39e9f71SJitendra Bhivare {
323a39e9f71SJitendra Bhivare 	struct be_cmd_req_modify_eq_delay *req;
324a39e9f71SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
325a39e9f71SJitendra Bhivare 	int i, rc;
326a39e9f71SJitendra Bhivare 
327a39e9f71SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_COMMON,
328a39e9f71SJitendra Bhivare 			OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
329a39e9f71SJitendra Bhivare 	if (rc)
330a39e9f71SJitendra Bhivare 		return rc;
331a39e9f71SJitendra Bhivare 
332a39e9f71SJitendra Bhivare 	req = nonemb_cmd.va;
333a39e9f71SJitendra Bhivare 	req->num_eq = cpu_to_le32(num);
334a39e9f71SJitendra Bhivare 	for (i = 0; i < num; i++) {
335a39e9f71SJitendra Bhivare 		req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);
336a39e9f71SJitendra Bhivare 		req->delay[i].phase = 0;
337a39e9f71SJitendra Bhivare 		req->delay[i].delay_multiplier =
338a39e9f71SJitendra Bhivare 				cpu_to_le32(set_eqd[i].delay_multiplier);
339a39e9f71SJitendra Bhivare 	}
340a39e9f71SJitendra Bhivare 
3417b0ddc13SMike Christie 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, __beiscsi_eq_delay_compl,
3427b0ddc13SMike Christie 				   NULL, 0);
3437b0ddc13SMike Christie 	if (rc) {
3447b0ddc13SMike Christie 		/*
3457b0ddc13SMike Christie 		 * Only free on failure. Async cmds are handled like -EBUSY
3467b0ddc13SMike Christie 		 * where it's handled for us.
3477b0ddc13SMike Christie 		 */
3487b0ddc13SMike Christie 		beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
3497b0ddc13SMike Christie 	}
3507b0ddc13SMike Christie 	return rc;
351a39e9f71SJitendra Bhivare }
352a39e9f71SJitendra Bhivare 
353c5905bf8SJitendra Bhivare /**
354c5905bf8SJitendra Bhivare  * beiscsi_get_initiator_name - read initiator name from flash
355c5905bf8SJitendra Bhivare  * @phba: device priv structure
356c5905bf8SJitendra Bhivare  * @name: buffer pointer
3574788e732SJitendra Bhivare  * @cfg: fetch user configured
358c5905bf8SJitendra Bhivare  *
359c5905bf8SJitendra Bhivare  */
beiscsi_get_initiator_name(struct beiscsi_hba * phba,char * name,bool cfg)3604788e732SJitendra Bhivare int beiscsi_get_initiator_name(struct beiscsi_hba *phba, char *name, bool cfg)
361c5905bf8SJitendra Bhivare {
362c5905bf8SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
363c5905bf8SJitendra Bhivare 	struct be_cmd_hba_name resp;
3644788e732SJitendra Bhivare 	struct be_cmd_hba_name *req;
365c5905bf8SJitendra Bhivare 	int rc;
366c5905bf8SJitendra Bhivare 
367c5905bf8SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI_INI,
368c5905bf8SJitendra Bhivare 			OPCODE_ISCSI_INI_CFG_GET_HBA_NAME, sizeof(resp));
369c5905bf8SJitendra Bhivare 	if (rc)
370c5905bf8SJitendra Bhivare 		return rc;
371c5905bf8SJitendra Bhivare 
3724788e732SJitendra Bhivare 	req = nonemb_cmd.va;
3734788e732SJitendra Bhivare 	if (cfg)
3744788e732SJitendra Bhivare 		req->hdr.version = 1;
375c5905bf8SJitendra Bhivare 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,
376c5905bf8SJitendra Bhivare 				   &resp, sizeof(resp));
3777b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
378c5905bf8SJitendra Bhivare 	if (rc) {
379c5905bf8SJitendra Bhivare 		beiscsi_log(phba, KERN_ERR,
380c5905bf8SJitendra Bhivare 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
381c5905bf8SJitendra Bhivare 			    "BS_%d : Initiator Name MBX Failed\n");
382c5905bf8SJitendra Bhivare 		return rc;
383c5905bf8SJitendra Bhivare 	}
384c5905bf8SJitendra Bhivare 	rc = sprintf(name, "%s\n", resp.initiator_name);
385c5905bf8SJitendra Bhivare 	return rc;
386c5905bf8SJitendra Bhivare }
387c5905bf8SJitendra Bhivare 
beiscsi_if_get_handle(struct beiscsi_hba * phba)388c5bf8889SJitendra Bhivare unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba)
389c5bf8889SJitendra Bhivare {
390c5bf8889SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
391c5bf8889SJitendra Bhivare 	struct be_mcc_wrb *wrb;
392c5bf8889SJitendra Bhivare 	struct be_cmd_get_all_if_id_req *req;
393c5bf8889SJitendra Bhivare 	struct be_cmd_get_all_if_id_req *pbe_allid;
394c5bf8889SJitendra Bhivare 	unsigned int tag;
395c5bf8889SJitendra Bhivare 	int status = 0;
396c5bf8889SJitendra Bhivare 
397c5bf8889SJitendra Bhivare 	if (mutex_lock_interruptible(&ctrl->mbox_lock))
398c5bf8889SJitendra Bhivare 		return -EINTR;
399c5bf8889SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
400c5bf8889SJitendra Bhivare 	if (!wrb) {
401c5bf8889SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
402c5bf8889SJitendra Bhivare 		return -ENOMEM;
403c5bf8889SJitendra Bhivare 	}
404c5bf8889SJitendra Bhivare 
405c5bf8889SJitendra Bhivare 	req = embedded_payload(wrb);
406c5bf8889SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
407c5bf8889SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
408c5bf8889SJitendra Bhivare 			   OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID,
409c5bf8889SJitendra Bhivare 			   sizeof(*req));
410c5bf8889SJitendra Bhivare 	be_mcc_notify(phba, tag);
411c5bf8889SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
412c5bf8889SJitendra Bhivare 
413c5bf8889SJitendra Bhivare 	status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
414c5bf8889SJitendra Bhivare 	if (status) {
415c5bf8889SJitendra Bhivare 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
416c5bf8889SJitendra Bhivare 			    "BG_%d : %s failed: %d\n", __func__, status);
417c5bf8889SJitendra Bhivare 		return -EBUSY;
418c5bf8889SJitendra Bhivare 	}
419c5bf8889SJitendra Bhivare 
420c5bf8889SJitendra Bhivare 	pbe_allid = embedded_payload(wrb);
421c5bf8889SJitendra Bhivare 	/* we now support only one interface per function */
422c5bf8889SJitendra Bhivare 	phba->interface_handle = pbe_allid->if_hndl_list[0];
423c5bf8889SJitendra Bhivare 
424c5bf8889SJitendra Bhivare 	return status;
425c5bf8889SJitendra Bhivare }
426c5bf8889SJitendra Bhivare 
beiscsi_if_zero_ip(u8 * ip,u32 ip_type)427290aa376SJitendra Bhivare static inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type)
428290aa376SJitendra Bhivare {
429290aa376SJitendra Bhivare 	u32 len;
430290aa376SJitendra Bhivare 
431290aa376SJitendra Bhivare 	len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN;
432290aa376SJitendra Bhivare 	while (len && !ip[len - 1])
433290aa376SJitendra Bhivare 		len--;
434290aa376SJitendra Bhivare 	return (len == 0);
435290aa376SJitendra Bhivare }
436290aa376SJitendra Bhivare 
beiscsi_if_mod_gw(struct beiscsi_hba * phba,u32 action,u32 ip_type,u8 * gw)43737f21648SJitendra Bhivare static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
43837f21648SJitendra Bhivare 			     u32 action, u32 ip_type, u8 *gw)
4390e43895eSMike Christie {
4400e43895eSMike Christie 	struct be_cmd_set_def_gateway_req *req;
4410e43895eSMike Christie 	struct be_dma_mem nonemb_cmd;
4420e43895eSMike Christie 	int rt_val;
4430e43895eSMike Christie 
444a39e9f71SJitendra Bhivare 	rt_val = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
4450e43895eSMike Christie 			OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,
4460e43895eSMike Christie 			sizeof(*req));
4470e43895eSMike Christie 	if (rt_val)
4480e43895eSMike Christie 		return rt_val;
4490e43895eSMike Christie 
4500e43895eSMike Christie 	req = nonemb_cmd.va;
45137f21648SJitendra Bhivare 	req->action = action;
45237f21648SJitendra Bhivare 	req->ip_addr.ip_type = ip_type;
45337f21648SJitendra Bhivare 	memcpy(req->ip_addr.addr, gw,
454290aa376SJitendra Bhivare 	       (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN);
4557b0ddc13SMike Christie 	rt_val = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
4567b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rt_val);
4577b0ddc13SMike Christie 	return rt_val;
4580e43895eSMike Christie }
4590e43895eSMike Christie 
beiscsi_if_set_gw(struct beiscsi_hba * phba,u32 ip_type,u8 * gw)46037f21648SJitendra Bhivare int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw)
46137f21648SJitendra Bhivare {
46237f21648SJitendra Bhivare 	struct be_cmd_get_def_gateway_resp gw_resp;
46337f21648SJitendra Bhivare 	int rt_val;
46437f21648SJitendra Bhivare 
46537f21648SJitendra Bhivare 	memset(&gw_resp, 0, sizeof(gw_resp));
46637f21648SJitendra Bhivare 	rt_val = beiscsi_if_get_gw(phba, ip_type, &gw_resp);
46737f21648SJitendra Bhivare 	if (rt_val) {
46837f21648SJitendra Bhivare 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
46937f21648SJitendra Bhivare 			    "BG_%d : Failed to Get Gateway Addr\n");
47037f21648SJitendra Bhivare 		return rt_val;
47137f21648SJitendra Bhivare 	}
47237f21648SJitendra Bhivare 
473290aa376SJitendra Bhivare 	if (!beiscsi_if_zero_ip(gw_resp.ip_addr.addr, ip_type)) {
47437f21648SJitendra Bhivare 		rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type,
47537f21648SJitendra Bhivare 					   gw_resp.ip_addr.addr);
47637f21648SJitendra Bhivare 		if (rt_val) {
47737f21648SJitendra Bhivare 			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
47837f21648SJitendra Bhivare 				    "BG_%d : Failed to clear Gateway Addr Set\n");
47937f21648SJitendra Bhivare 			return rt_val;
48037f21648SJitendra Bhivare 		}
481290aa376SJitendra Bhivare 	}
48237f21648SJitendra Bhivare 
48337f21648SJitendra Bhivare 	rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw);
48437f21648SJitendra Bhivare 	if (rt_val)
48537f21648SJitendra Bhivare 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
48637f21648SJitendra Bhivare 			    "BG_%d : Failed to Set Gateway Addr\n");
48737f21648SJitendra Bhivare 
48837f21648SJitendra Bhivare 	return rt_val;
48937f21648SJitendra Bhivare }
49037f21648SJitendra Bhivare 
beiscsi_if_get_gw(struct beiscsi_hba * phba,u32 ip_type,struct be_cmd_get_def_gateway_resp * resp)49137f21648SJitendra Bhivare int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type,
49237f21648SJitendra Bhivare 		      struct be_cmd_get_def_gateway_resp *resp)
49337f21648SJitendra Bhivare {
49437f21648SJitendra Bhivare 	struct be_cmd_get_def_gateway_req *req;
49537f21648SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
49637f21648SJitendra Bhivare 	int rc;
49737f21648SJitendra Bhivare 
498a39e9f71SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
49937f21648SJitendra Bhivare 			OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,
50037f21648SJitendra Bhivare 			sizeof(*resp));
50137f21648SJitendra Bhivare 	if (rc)
50237f21648SJitendra Bhivare 		return rc;
50337f21648SJitendra Bhivare 
50437f21648SJitendra Bhivare 	req = nonemb_cmd.va;
50537f21648SJitendra Bhivare 	req->ip_type = ip_type;
50637f21648SJitendra Bhivare 
5077b0ddc13SMike Christie 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, resp,
5087b0ddc13SMike Christie 				   sizeof(*resp));
5097b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
5107b0ddc13SMike Christie 	return rc;
51137f21648SJitendra Bhivare }
51237f21648SJitendra Bhivare 
5130152a7e9SJitendra Bhivare static int
beiscsi_if_clr_ip(struct beiscsi_hba * phba,struct be_cmd_get_if_info_resp * if_info)5140152a7e9SJitendra Bhivare beiscsi_if_clr_ip(struct beiscsi_hba *phba,
5150152a7e9SJitendra Bhivare 		  struct be_cmd_get_if_info_resp *if_info)
5160e43895eSMike Christie {
5170152a7e9SJitendra Bhivare 	struct be_cmd_set_ip_addr_req *req;
5180e43895eSMike Christie 	struct be_dma_mem nonemb_cmd;
5190e43895eSMike Christie 	int rc;
5200e43895eSMike Christie 
521a39e9f71SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
5220152a7e9SJitendra Bhivare 			OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
5230152a7e9SJitendra Bhivare 			sizeof(*req));
5243c9d903bSJitendra Bhivare 	if (rc)
5253c9d903bSJitendra Bhivare 		return rc;
5260e43895eSMike Christie 
5270152a7e9SJitendra Bhivare 	req = nonemb_cmd.va;
5280152a7e9SJitendra Bhivare 	req->ip_params.record_entry_count = 1;
5290152a7e9SJitendra Bhivare 	req->ip_params.ip_record.action = IP_ACTION_DEL;
5300152a7e9SJitendra Bhivare 	req->ip_params.ip_record.interface_hndl =
5310152a7e9SJitendra Bhivare 		phba->interface_handle;
5320152a7e9SJitendra Bhivare 	req->ip_params.ip_record.ip_addr.size_of_structure =
5330152a7e9SJitendra Bhivare 		sizeof(struct be_ip_addr_subnet_format);
5340152a7e9SJitendra Bhivare 	req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type;
5350152a7e9SJitendra Bhivare 	memcpy(req->ip_params.ip_record.ip_addr.addr,
5360152a7e9SJitendra Bhivare 	       if_info->ip_addr.addr,
5370152a7e9SJitendra Bhivare 	       sizeof(if_info->ip_addr.addr));
5380152a7e9SJitendra Bhivare 	memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
5390152a7e9SJitendra Bhivare 	       if_info->ip_addr.subnet_mask,
5400152a7e9SJitendra Bhivare 	       sizeof(if_info->ip_addr.subnet_mask));
541a39e9f71SJitendra Bhivare 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
5420152a7e9SJitendra Bhivare 	if (rc < 0 || req->ip_params.ip_record.status) {
5430152a7e9SJitendra Bhivare 		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
5440152a7e9SJitendra Bhivare 			    "BG_%d : failed to clear IP: rc %d status %d\n",
5450152a7e9SJitendra Bhivare 			    rc, req->ip_params.ip_record.status);
5460152a7e9SJitendra Bhivare 	}
5477b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
5480152a7e9SJitendra Bhivare 	return rc;
5490152a7e9SJitendra Bhivare }
5500152a7e9SJitendra Bhivare 
5510152a7e9SJitendra Bhivare static int
beiscsi_if_set_ip(struct beiscsi_hba * phba,u8 * ip,u8 * subnet,u32 ip_type)5520152a7e9SJitendra Bhivare beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,
5530152a7e9SJitendra Bhivare 		  u8 *subnet, u32 ip_type)
5540152a7e9SJitendra Bhivare {
5550152a7e9SJitendra Bhivare 	struct be_cmd_set_ip_addr_req *req;
5560152a7e9SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
5570152a7e9SJitendra Bhivare 	uint32_t ip_len;
5580152a7e9SJitendra Bhivare 	int rc;
5590152a7e9SJitendra Bhivare 
560a39e9f71SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
5610152a7e9SJitendra Bhivare 			OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
5620152a7e9SJitendra Bhivare 			sizeof(*req));
5630152a7e9SJitendra Bhivare 	if (rc)
5640152a7e9SJitendra Bhivare 		return rc;
5650152a7e9SJitendra Bhivare 
5660152a7e9SJitendra Bhivare 	req = nonemb_cmd.va;
5670152a7e9SJitendra Bhivare 	req->ip_params.record_entry_count = 1;
5680152a7e9SJitendra Bhivare 	req->ip_params.ip_record.action = IP_ACTION_ADD;
5690152a7e9SJitendra Bhivare 	req->ip_params.ip_record.interface_hndl =
5700152a7e9SJitendra Bhivare 		phba->interface_handle;
5710152a7e9SJitendra Bhivare 	req->ip_params.ip_record.ip_addr.size_of_structure =
5720152a7e9SJitendra Bhivare 		sizeof(struct be_ip_addr_subnet_format);
5730152a7e9SJitendra Bhivare 	req->ip_params.ip_record.ip_addr.ip_type = ip_type;
574290aa376SJitendra Bhivare 	ip_len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN;
5750152a7e9SJitendra Bhivare 	memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len);
5760152a7e9SJitendra Bhivare 	if (subnet)
5770152a7e9SJitendra Bhivare 		memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
5780152a7e9SJitendra Bhivare 		       subnet, ip_len);
5790152a7e9SJitendra Bhivare 
580a39e9f71SJitendra Bhivare 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
5810152a7e9SJitendra Bhivare 	/**
5820152a7e9SJitendra Bhivare 	 * In some cases, host needs to look into individual record status
5830152a7e9SJitendra Bhivare 	 * even though FW reported success for that IOCTL.
5840152a7e9SJitendra Bhivare 	 */
5850152a7e9SJitendra Bhivare 	if (rc < 0 || req->ip_params.ip_record.status) {
5860152a7e9SJitendra Bhivare 		__beiscsi_log(phba, KERN_ERR,
5870152a7e9SJitendra Bhivare 			    "BG_%d : failed to set IP: rc %d status %d\n",
5880152a7e9SJitendra Bhivare 			    rc, req->ip_params.ip_record.status);
5890152a7e9SJitendra Bhivare 		if (req->ip_params.ip_record.status)
5900152a7e9SJitendra Bhivare 			rc = -EINVAL;
5910152a7e9SJitendra Bhivare 	}
5927b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
5930152a7e9SJitendra Bhivare 	return rc;
5940152a7e9SJitendra Bhivare }
5950152a7e9SJitendra Bhivare 
beiscsi_if_en_static(struct beiscsi_hba * phba,u32 ip_type,u8 * ip,u8 * subnet)5960152a7e9SJitendra Bhivare int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
5970152a7e9SJitendra Bhivare 			 u8 *ip, u8 *subnet)
5980152a7e9SJitendra Bhivare {
5990152a7e9SJitendra Bhivare 	struct be_cmd_get_if_info_resp *if_info;
6000152a7e9SJitendra Bhivare 	struct be_cmd_rel_dhcp_req *reldhcp;
6010152a7e9SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
6020152a7e9SJitendra Bhivare 	int rc;
6030e43895eSMike Christie 
60496b48b92SJitendra Bhivare 	rc = beiscsi_if_get_info(phba, ip_type, &if_info);
605beff6549STomas Henzl 	if (rc)
6060e43895eSMike Christie 		return rc;
6070e43895eSMike Christie 
6081f536d49SJayamohan Kallickal 	if (if_info->dhcp_state) {
609a39e9f71SJitendra Bhivare 		rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd,
610a39e9f71SJitendra Bhivare 				CMD_SUBSYSTEM_ISCSI,
6110e43895eSMike Christie 				OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
6120e43895eSMike Christie 				sizeof(*reldhcp));
6130e43895eSMike Christie 		if (rc)
6146d67726bSMaurizio Lombardi 			goto exit;
6150e43895eSMike Christie 
6160e43895eSMike Christie 		reldhcp = nonemb_cmd.va;
6170e43895eSMike Christie 		reldhcp->interface_hndl = phba->interface_handle;
6180e43895eSMike Christie 		reldhcp->ip_type = ip_type;
619a39e9f71SJitendra Bhivare 		rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
6207b0ddc13SMike Christie 		beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
6210e43895eSMike Christie 		if (rc < 0) {
6220152a7e9SJitendra Bhivare 			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
6230152a7e9SJitendra Bhivare 				    "BG_%d : failed to release existing DHCP: %d\n",
6240152a7e9SJitendra Bhivare 				    rc);
6256d67726bSMaurizio Lombardi 			goto exit;
6260e43895eSMike Christie 		}
6270e43895eSMike Christie 	}
6280e43895eSMike Christie 
629290aa376SJitendra Bhivare 	/* first delete any IP set */
630290aa376SJitendra Bhivare 	if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) {
6310152a7e9SJitendra Bhivare 		rc = beiscsi_if_clr_ip(phba, if_info);
6320e43895eSMike Christie 		if (rc)
6336d67726bSMaurizio Lombardi 			goto exit;
634290aa376SJitendra Bhivare 	}
6350152a7e9SJitendra Bhivare 
6360152a7e9SJitendra Bhivare 	/* if ip == NULL then this is called just to release DHCP IP */
6370152a7e9SJitendra Bhivare 	if (ip)
6380152a7e9SJitendra Bhivare 		rc = beiscsi_if_set_ip(phba, ip, subnet, ip_type);
6390152a7e9SJitendra Bhivare exit:
6400152a7e9SJitendra Bhivare 	kfree(if_info);
6410152a7e9SJitendra Bhivare 	return rc;
6420e43895eSMike Christie }
6430e43895eSMike Christie 
beiscsi_if_en_dhcp(struct beiscsi_hba * phba,u32 ip_type)6440152a7e9SJitendra Bhivare int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
6450152a7e9SJitendra Bhivare {
6460152a7e9SJitendra Bhivare 	struct be_cmd_get_def_gateway_resp gw_resp;
6470152a7e9SJitendra Bhivare 	struct be_cmd_get_if_info_resp *if_info;
6480152a7e9SJitendra Bhivare 	struct be_cmd_set_dhcp_req *dhcpreq;
6490152a7e9SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
6500152a7e9SJitendra Bhivare 	u8 *gw;
6510152a7e9SJitendra Bhivare 	int rc;
6520152a7e9SJitendra Bhivare 
65396b48b92SJitendra Bhivare 	rc = beiscsi_if_get_info(phba, ip_type, &if_info);
6540152a7e9SJitendra Bhivare 	if (rc)
6550152a7e9SJitendra Bhivare 		return rc;
6560152a7e9SJitendra Bhivare 
6570152a7e9SJitendra Bhivare 	if (if_info->dhcp_state) {
6580152a7e9SJitendra Bhivare 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
6590152a7e9SJitendra Bhivare 				"BG_%d : DHCP Already Enabled\n");
6600152a7e9SJitendra Bhivare 		goto exit;
6610152a7e9SJitendra Bhivare 	}
6620152a7e9SJitendra Bhivare 
663290aa376SJitendra Bhivare 	/* first delete any IP set */
664290aa376SJitendra Bhivare 	if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) {
6650152a7e9SJitendra Bhivare 		rc = beiscsi_if_clr_ip(phba, if_info);
6660152a7e9SJitendra Bhivare 		if (rc)
6670152a7e9SJitendra Bhivare 			goto exit;
668290aa376SJitendra Bhivare 	}
6690152a7e9SJitendra Bhivare 
6700152a7e9SJitendra Bhivare 	/* delete gateway settings if mode change is to DHCP */
6710152a7e9SJitendra Bhivare 	memset(&gw_resp, 0, sizeof(gw_resp));
6720152a7e9SJitendra Bhivare 	/* use ip_type provided in if_info */
6730152a7e9SJitendra Bhivare 	rc = beiscsi_if_get_gw(phba, if_info->ip_addr.ip_type, &gw_resp);
6740e43895eSMike Christie 	if (rc) {
67599bc5d55SJohn Soni Jose 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
67699bc5d55SJohn Soni Jose 			    "BG_%d : Failed to Get Gateway Addr\n");
6776d67726bSMaurizio Lombardi 		goto exit;
6780e43895eSMike Christie 	}
6790152a7e9SJitendra Bhivare 	gw = (u8 *)&gw_resp.ip_addr.addr;
680290aa376SJitendra Bhivare 	if (!beiscsi_if_zero_ip(gw, if_info->ip_addr.ip_type)) {
68137f21648SJitendra Bhivare 		rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL,
6820152a7e9SJitendra Bhivare 				       if_info->ip_addr.ip_type, gw);
6830e43895eSMike Christie 		if (rc) {
6840152a7e9SJitendra Bhivare 			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
68599bc5d55SJohn Soni Jose 				    "BG_%d : Failed to clear Gateway Addr Set\n");
6866d67726bSMaurizio Lombardi 			goto exit;
6870e43895eSMike Christie 		}
688290aa376SJitendra Bhivare 	}
6890e43895eSMike Christie 
690a39e9f71SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
6910e43895eSMike Christie 			OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
6920e43895eSMike Christie 			sizeof(*dhcpreq));
6930e43895eSMike Christie 	if (rc)
6946d67726bSMaurizio Lombardi 		goto exit;
6950e43895eSMike Christie 
6960e43895eSMike Christie 	dhcpreq = nonemb_cmd.va;
697290aa376SJitendra Bhivare 	dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */
6980e43895eSMike Christie 	dhcpreq->retry_count = 1;
6990e43895eSMike Christie 	dhcpreq->interface_hndl = phba->interface_handle;
7000152a7e9SJitendra Bhivare 	dhcpreq->ip_type = ip_type;
701a39e9f71SJitendra Bhivare 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);
7027b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
7036d67726bSMaurizio Lombardi exit:
7046d67726bSMaurizio Lombardi 	kfree(if_info);
7050e43895eSMike Christie 	return rc;
7060e43895eSMike Christie }
7070e43895eSMike Christie 
708db02aea9SJitendra Bhivare /**
709db02aea9SJitendra Bhivare  * beiscsi_if_set_vlan()- Issue and wait for CMD completion
710db02aea9SJitendra Bhivare  * @phba: device private structure instance
711db02aea9SJitendra Bhivare  * @vlan_tag: VLAN tag
712db02aea9SJitendra Bhivare  *
713db02aea9SJitendra Bhivare  * Issue the MBX Cmd and wait for the completion of the
714db02aea9SJitendra Bhivare  * command.
715db02aea9SJitendra Bhivare  *
716db02aea9SJitendra Bhivare  * returns
717db02aea9SJitendra Bhivare  *	Success: 0
718db02aea9SJitendra Bhivare  *	Failure: Non-Xero Value
719db02aea9SJitendra Bhivare  **/
beiscsi_if_set_vlan(struct beiscsi_hba * phba,uint16_t vlan_tag)720db02aea9SJitendra Bhivare int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag)
721db02aea9SJitendra Bhivare {
722db02aea9SJitendra Bhivare 	int rc;
723db02aea9SJitendra Bhivare 	unsigned int tag;
724db02aea9SJitendra Bhivare 
725db02aea9SJitendra Bhivare 	tag = be_cmd_set_vlan(phba, vlan_tag);
726db02aea9SJitendra Bhivare 	if (!tag) {
727db02aea9SJitendra Bhivare 		beiscsi_log(phba, KERN_ERR,
728db02aea9SJitendra Bhivare 			    (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
729db02aea9SJitendra Bhivare 			    "BG_%d : VLAN Setting Failed\n");
730db02aea9SJitendra Bhivare 		return -EBUSY;
731db02aea9SJitendra Bhivare 	}
732db02aea9SJitendra Bhivare 
733db02aea9SJitendra Bhivare 	rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
734db02aea9SJitendra Bhivare 	if (rc) {
735db02aea9SJitendra Bhivare 		beiscsi_log(phba, KERN_ERR,
736db02aea9SJitendra Bhivare 			    (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
737db02aea9SJitendra Bhivare 			    "BS_%d : VLAN MBX Cmd Failed\n");
738db02aea9SJitendra Bhivare 		return rc;
739db02aea9SJitendra Bhivare 	}
740db02aea9SJitendra Bhivare 	return rc;
741db02aea9SJitendra Bhivare }
742db02aea9SJitendra Bhivare 
743db02aea9SJitendra Bhivare 
beiscsi_if_get_info(struct beiscsi_hba * phba,int ip_type,struct be_cmd_get_if_info_resp ** if_info)74496b48b92SJitendra Bhivare int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,
7451f536d49SJayamohan Kallickal 			struct be_cmd_get_if_info_resp **if_info)
7460e43895eSMike Christie {
7470e43895eSMike Christie 	struct be_cmd_get_if_info_req *req;
7480e43895eSMike Christie 	struct be_dma_mem nonemb_cmd;
7491f536d49SJayamohan Kallickal 	uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp);
7500e43895eSMike Christie 	int rc;
7510e43895eSMike Christie 
752c5bf8889SJitendra Bhivare 	rc = beiscsi_if_get_handle(phba);
7533c9d903bSJitendra Bhivare 	if (rc)
7543c9d903bSJitendra Bhivare 		return rc;
7550e43895eSMike Christie 
7561f536d49SJayamohan Kallickal 	do {
757a39e9f71SJitendra Bhivare 		rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd,
758a39e9f71SJitendra Bhivare 				CMD_SUBSYSTEM_ISCSI,
7590e43895eSMike Christie 				OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
7601f536d49SJayamohan Kallickal 				ioctl_size);
7610e43895eSMike Christie 		if (rc)
7620e43895eSMike Christie 			return rc;
7630e43895eSMike Christie 
7640e43895eSMike Christie 		req = nonemb_cmd.va;
7650e43895eSMike Christie 		req->interface_hndl = phba->interface_handle;
7660e43895eSMike Christie 		req->ip_type = ip_type;
7670e43895eSMike Christie 
7681f536d49SJayamohan Kallickal 		/* Allocate memory for if_info */
7691f536d49SJayamohan Kallickal 		*if_info = kzalloc(ioctl_size, GFP_KERNEL);
7701f536d49SJayamohan Kallickal 		if (!*if_info) {
7711f536d49SJayamohan Kallickal 			beiscsi_log(phba, KERN_ERR,
7721f536d49SJayamohan Kallickal 				    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
7731f536d49SJayamohan Kallickal 				    "BG_%d : Memory Allocation Failure\n");
7741f536d49SJayamohan Kallickal 
7757b0ddc13SMike Christie 				beiscsi_free_nemb_cmd(phba, &nonemb_cmd,
7767b0ddc13SMike Christie 						      -ENOMEM);
7771f536d49SJayamohan Kallickal 				return -ENOMEM;
7781f536d49SJayamohan Kallickal 		}
7791f536d49SJayamohan Kallickal 
780a39e9f71SJitendra Bhivare 		rc =  beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, *if_info,
7811f536d49SJayamohan Kallickal 					    ioctl_size);
7821f536d49SJayamohan Kallickal 
7831f536d49SJayamohan Kallickal 		/* Check if the error is because of Insufficent_Buffer */
7841f536d49SJayamohan Kallickal 		if (rc == -EAGAIN) {
7851f536d49SJayamohan Kallickal 
7861f536d49SJayamohan Kallickal 			/* Get the new memory size */
7871f536d49SJayamohan Kallickal 			ioctl_size = ((struct be_cmd_resp_hdr *)
7881f536d49SJayamohan Kallickal 				      nonemb_cmd.va)->actual_resp_len;
7891f536d49SJayamohan Kallickal 			ioctl_size += sizeof(struct be_cmd_req_hdr);
7901f536d49SJayamohan Kallickal 
7917b0ddc13SMike Christie 			beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
7921f536d49SJayamohan Kallickal 			/* Free the virtual memory */
7931f536d49SJayamohan Kallickal 			kfree(*if_info);
7947b0ddc13SMike Christie 		} else {
7957b0ddc13SMike Christie 			beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
7961f536d49SJayamohan Kallickal 			break;
7977b0ddc13SMike Christie 		}
7981f536d49SJayamohan Kallickal 	} while (true);
7991f536d49SJayamohan Kallickal 	return rc;
8000e43895eSMike Christie }
8010e43895eSMike Christie 
mgmt_get_nic_conf(struct beiscsi_hba * phba,struct be_cmd_get_nic_conf_resp * nic)8020e43895eSMike Christie int mgmt_get_nic_conf(struct beiscsi_hba *phba,
8030e43895eSMike Christie 		      struct be_cmd_get_nic_conf_resp *nic)
8040e43895eSMike Christie {
8050e43895eSMike Christie 	struct be_dma_mem nonemb_cmd;
8060e43895eSMike Christie 	int rc;
8070e43895eSMike Christie 
808a39e9f71SJitendra Bhivare 	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,
8090e43895eSMike Christie 			OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
8100e43895eSMike Christie 			sizeof(*nic));
8110e43895eSMike Christie 	if (rc)
8120e43895eSMike Christie 		return rc;
8130e43895eSMike Christie 
8147b0ddc13SMike Christie 	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, nic, sizeof(*nic));
8157b0ddc13SMike Christie 	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);
8167b0ddc13SMike Christie 	return rc;
8170e43895eSMike Christie }
8180e43895eSMike Christie 
beiscsi_boot_process_compl(struct beiscsi_hba * phba,unsigned int tag)81950a4b824SJitendra Bhivare static void beiscsi_boot_process_compl(struct beiscsi_hba *phba,
82050a4b824SJitendra Bhivare 				       unsigned int tag)
82150a4b824SJitendra Bhivare {
82250a4b824SJitendra Bhivare 	struct be_cmd_get_boot_target_resp *boot_resp;
82350a4b824SJitendra Bhivare 	struct be_cmd_resp_logout_fw_sess *logo_resp;
82450a4b824SJitendra Bhivare 	struct be_cmd_get_session_resp *sess_resp;
82550a4b824SJitendra Bhivare 	struct be_mcc_wrb *wrb;
82650a4b824SJitendra Bhivare 	struct boot_struct *bs;
82750a4b824SJitendra Bhivare 	int boot_work, status;
82850a4b824SJitendra Bhivare 
82950a4b824SJitendra Bhivare 	if (!test_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) {
83050a4b824SJitendra Bhivare 		__beiscsi_log(phba, KERN_ERR,
83150a4b824SJitendra Bhivare 			      "BG_%d : %s no boot work %lx\n",
83250a4b824SJitendra Bhivare 			      __func__, phba->state);
83350a4b824SJitendra Bhivare 		return;
83450a4b824SJitendra Bhivare 	}
83550a4b824SJitendra Bhivare 
83650a4b824SJitendra Bhivare 	if (phba->boot_struct.tag != tag) {
83750a4b824SJitendra Bhivare 		__beiscsi_log(phba, KERN_ERR,
83850a4b824SJitendra Bhivare 			      "BG_%d : %s tag mismatch %d:%d\n",
83950a4b824SJitendra Bhivare 			      __func__, tag, phba->boot_struct.tag);
84050a4b824SJitendra Bhivare 		return;
84150a4b824SJitendra Bhivare 	}
84250a4b824SJitendra Bhivare 	bs = &phba->boot_struct;
84350a4b824SJitendra Bhivare 	boot_work = 1;
84450a4b824SJitendra Bhivare 	status = 0;
84550a4b824SJitendra Bhivare 	switch (bs->action) {
84650a4b824SJitendra Bhivare 	case BEISCSI_BOOT_REOPEN_SESS:
84750a4b824SJitendra Bhivare 		status = __beiscsi_mcc_compl_status(phba, tag, NULL, NULL);
84850a4b824SJitendra Bhivare 		if (!status)
84950a4b824SJitendra Bhivare 			bs->action = BEISCSI_BOOT_GET_SHANDLE;
85050a4b824SJitendra Bhivare 		else
85150a4b824SJitendra Bhivare 			bs->retry--;
85250a4b824SJitendra Bhivare 		break;
85350a4b824SJitendra Bhivare 	case BEISCSI_BOOT_GET_SHANDLE:
85450a4b824SJitendra Bhivare 		status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL);
85550a4b824SJitendra Bhivare 		if (!status) {
85650a4b824SJitendra Bhivare 			boot_resp = embedded_payload(wrb);
85750a4b824SJitendra Bhivare 			bs->s_handle = boot_resp->boot_session_handle;
85850a4b824SJitendra Bhivare 		}
85950a4b824SJitendra Bhivare 		if (bs->s_handle == BE_BOOT_INVALID_SHANDLE) {
86050a4b824SJitendra Bhivare 			bs->action = BEISCSI_BOOT_REOPEN_SESS;
86150a4b824SJitendra Bhivare 			bs->retry--;
86250a4b824SJitendra Bhivare 		} else {
86350a4b824SJitendra Bhivare 			bs->action = BEISCSI_BOOT_GET_SINFO;
86450a4b824SJitendra Bhivare 		}
86550a4b824SJitendra Bhivare 		break;
86650a4b824SJitendra Bhivare 	case BEISCSI_BOOT_GET_SINFO:
86750a4b824SJitendra Bhivare 		status = __beiscsi_mcc_compl_status(phba, tag, NULL,
86850a4b824SJitendra Bhivare 						    &bs->nonemb_cmd);
86950a4b824SJitendra Bhivare 		if (!status) {
87050a4b824SJitendra Bhivare 			sess_resp = bs->nonemb_cmd.va;
87150a4b824SJitendra Bhivare 			memcpy(&bs->boot_sess, &sess_resp->session_info,
87250a4b824SJitendra Bhivare 			       sizeof(struct mgmt_session_info));
87350a4b824SJitendra Bhivare 			bs->action = BEISCSI_BOOT_LOGOUT_SESS;
87450a4b824SJitendra Bhivare 		} else {
87550a4b824SJitendra Bhivare 			__beiscsi_log(phba, KERN_ERR,
87650a4b824SJitendra Bhivare 				      "BG_%d : get boot session info error : 0x%x\n",
87750a4b824SJitendra Bhivare 				      status);
87850a4b824SJitendra Bhivare 			boot_work = 0;
87950a4b824SJitendra Bhivare 		}
88026a4c991SChristoph Hellwig 		dma_free_coherent(&phba->ctrl.pdev->dev, bs->nonemb_cmd.size,
88150a4b824SJitendra Bhivare 				    bs->nonemb_cmd.va, bs->nonemb_cmd.dma);
88250a4b824SJitendra Bhivare 		bs->nonemb_cmd.va = NULL;
88350a4b824SJitendra Bhivare 		break;
88450a4b824SJitendra Bhivare 	case BEISCSI_BOOT_LOGOUT_SESS:
88550a4b824SJitendra Bhivare 		status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL);
88650a4b824SJitendra Bhivare 		if (!status) {
88750a4b824SJitendra Bhivare 			logo_resp = embedded_payload(wrb);
88850a4b824SJitendra Bhivare 			if (logo_resp->session_status != BE_SESS_STATUS_CLOSE) {
88950a4b824SJitendra Bhivare 				__beiscsi_log(phba, KERN_ERR,
89050a4b824SJitendra Bhivare 					      "BG_%d : FW boot session logout error : 0x%x\n",
89150a4b824SJitendra Bhivare 					      logo_resp->session_status);
89250a4b824SJitendra Bhivare 			}
89350a4b824SJitendra Bhivare 		}
89450a4b824SJitendra Bhivare 		/* continue to create boot_kset even if logout failed? */
89550a4b824SJitendra Bhivare 		bs->action = BEISCSI_BOOT_CREATE_KSET;
89650a4b824SJitendra Bhivare 		break;
89750a4b824SJitendra Bhivare 	default:
89850a4b824SJitendra Bhivare 		break;
89950a4b824SJitendra Bhivare 	}
90050a4b824SJitendra Bhivare 
90150a4b824SJitendra Bhivare 	/* clear the tag so no other completion matches this tag */
90250a4b824SJitendra Bhivare 	bs->tag = 0;
90350a4b824SJitendra Bhivare 	if (!bs->retry) {
90450a4b824SJitendra Bhivare 		boot_work = 0;
90550a4b824SJitendra Bhivare 		__beiscsi_log(phba, KERN_ERR,
90650a4b824SJitendra Bhivare 			      "BG_%d : failed to setup boot target: status %d action %d\n",
90750a4b824SJitendra Bhivare 			      status, bs->action);
90850a4b824SJitendra Bhivare 	}
90950a4b824SJitendra Bhivare 	if (!boot_work) {
91050a4b824SJitendra Bhivare 		/* wait for next event to start boot_work */
91150a4b824SJitendra Bhivare 		clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state);
91250a4b824SJitendra Bhivare 		return;
91350a4b824SJitendra Bhivare 	}
91450a4b824SJitendra Bhivare 	schedule_work(&phba->boot_work);
91550a4b824SJitendra Bhivare }
91650a4b824SJitendra Bhivare 
9179aef4200SJohn Soni Jose /**
91850a4b824SJitendra Bhivare  * beiscsi_boot_logout_sess()- Logout from boot FW session
91950a4b824SJitendra Bhivare  * @phba: Device priv structure instance
92050a4b824SJitendra Bhivare  *
92150a4b824SJitendra Bhivare  * return
92250a4b824SJitendra Bhivare  *	the TAG used for MBOX Command
92350a4b824SJitendra Bhivare  *
92450a4b824SJitendra Bhivare  */
beiscsi_boot_logout_sess(struct beiscsi_hba * phba)92550a4b824SJitendra Bhivare unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba)
92650a4b824SJitendra Bhivare {
92750a4b824SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
92850a4b824SJitendra Bhivare 	struct be_mcc_wrb *wrb;
92950a4b824SJitendra Bhivare 	struct be_cmd_req_logout_fw_sess *req;
93050a4b824SJitendra Bhivare 	unsigned int tag;
93150a4b824SJitendra Bhivare 
93250a4b824SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
93350a4b824SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
93450a4b824SJitendra Bhivare 	if (!wrb) {
93550a4b824SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
93650a4b824SJitendra Bhivare 		return 0;
93750a4b824SJitendra Bhivare 	}
93850a4b824SJitendra Bhivare 
93950a4b824SJitendra Bhivare 	req = embedded_payload(wrb);
94050a4b824SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
94150a4b824SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
94250a4b824SJitendra Bhivare 			   OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET,
94350a4b824SJitendra Bhivare 			   sizeof(struct be_cmd_req_logout_fw_sess));
94450a4b824SJitendra Bhivare 	/* Use the session handle copied into boot_sess */
94550a4b824SJitendra Bhivare 	req->session_handle = phba->boot_struct.boot_sess.session_handle;
94650a4b824SJitendra Bhivare 
94750a4b824SJitendra Bhivare 	phba->boot_struct.tag = tag;
94850a4b824SJitendra Bhivare 	set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);
94950a4b824SJitendra Bhivare 	ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;
95050a4b824SJitendra Bhivare 
95150a4b824SJitendra Bhivare 	be_mcc_notify(phba, tag);
95250a4b824SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
95350a4b824SJitendra Bhivare 
95450a4b824SJitendra Bhivare 	return tag;
95550a4b824SJitendra Bhivare }
95650a4b824SJitendra Bhivare /**
95750a4b824SJitendra Bhivare  * beiscsi_boot_reopen_sess()- Reopen boot session
95850a4b824SJitendra Bhivare  * @phba: Device priv structure instance
95950a4b824SJitendra Bhivare  *
96050a4b824SJitendra Bhivare  * return
96150a4b824SJitendra Bhivare  *	the TAG used for MBOX Command
96250a4b824SJitendra Bhivare  *
96350a4b824SJitendra Bhivare  **/
beiscsi_boot_reopen_sess(struct beiscsi_hba * phba)96450a4b824SJitendra Bhivare unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba)
96550a4b824SJitendra Bhivare {
96650a4b824SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
96750a4b824SJitendra Bhivare 	struct be_mcc_wrb *wrb;
96850a4b824SJitendra Bhivare 	struct be_cmd_reopen_session_req *req;
96950a4b824SJitendra Bhivare 	unsigned int tag;
97050a4b824SJitendra Bhivare 
97150a4b824SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
97250a4b824SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
97350a4b824SJitendra Bhivare 	if (!wrb) {
97450a4b824SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
97550a4b824SJitendra Bhivare 		return 0;
97650a4b824SJitendra Bhivare 	}
97750a4b824SJitendra Bhivare 
97850a4b824SJitendra Bhivare 	req = embedded_payload(wrb);
97950a4b824SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
98050a4b824SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
98150a4b824SJitendra Bhivare 			   OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS,
98250a4b824SJitendra Bhivare 			   sizeof(struct be_cmd_reopen_session_resp));
98350a4b824SJitendra Bhivare 	req->reopen_type = BE_REOPEN_BOOT_SESSIONS;
98450a4b824SJitendra Bhivare 	req->session_handle = BE_BOOT_INVALID_SHANDLE;
98550a4b824SJitendra Bhivare 
98650a4b824SJitendra Bhivare 	phba->boot_struct.tag = tag;
98750a4b824SJitendra Bhivare 	set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);
98850a4b824SJitendra Bhivare 	ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;
98950a4b824SJitendra Bhivare 
99050a4b824SJitendra Bhivare 	be_mcc_notify(phba, tag);
99150a4b824SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
99250a4b824SJitendra Bhivare 	return tag;
99350a4b824SJitendra Bhivare }
99450a4b824SJitendra Bhivare 
99550a4b824SJitendra Bhivare 
99650a4b824SJitendra Bhivare /**
99750a4b824SJitendra Bhivare  * beiscsi_boot_get_sinfo()- Get boot session info
99850a4b824SJitendra Bhivare  * @phba: device priv structure instance
99950a4b824SJitendra Bhivare  *
100050a4b824SJitendra Bhivare  * Fetches the boot_struct.s_handle info from FW.
100150a4b824SJitendra Bhivare  * return
100250a4b824SJitendra Bhivare  *	the TAG used for MBOX Command
100350a4b824SJitendra Bhivare  *
100450a4b824SJitendra Bhivare  **/
beiscsi_boot_get_sinfo(struct beiscsi_hba * phba)100550a4b824SJitendra Bhivare unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba)
100650a4b824SJitendra Bhivare {
100750a4b824SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
100850a4b824SJitendra Bhivare 	struct be_cmd_get_session_req *req;
100950a4b824SJitendra Bhivare 	struct be_dma_mem *nonemb_cmd;
101050a4b824SJitendra Bhivare 	struct be_mcc_wrb *wrb;
101150a4b824SJitendra Bhivare 	struct be_sge *sge;
101250a4b824SJitendra Bhivare 	unsigned int tag;
101350a4b824SJitendra Bhivare 
101450a4b824SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
101550a4b824SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
101650a4b824SJitendra Bhivare 	if (!wrb) {
101750a4b824SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
101850a4b824SJitendra Bhivare 		return 0;
101950a4b824SJitendra Bhivare 	}
102050a4b824SJitendra Bhivare 
102150a4b824SJitendra Bhivare 	nonemb_cmd = &phba->boot_struct.nonemb_cmd;
1022fa1261c4SJitendra Bhivare 	nonemb_cmd->size = sizeof(struct be_cmd_get_session_resp);
102326a4c991SChristoph Hellwig 	nonemb_cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
102423b98e4bSDan Carpenter 					      nonemb_cmd->size,
102526a4c991SChristoph Hellwig 					      &nonemb_cmd->dma,
102626a4c991SChristoph Hellwig 					      GFP_KERNEL);
1027658f18d1SJitendra Bhivare 	if (!nonemb_cmd->va) {
1028658f18d1SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
102950a4b824SJitendra Bhivare 		return 0;
1030658f18d1SJitendra Bhivare 	}
103150a4b824SJitendra Bhivare 
103250a4b824SJitendra Bhivare 	req = nonemb_cmd->va;
103350a4b824SJitendra Bhivare 	memset(req, 0, sizeof(*req));
103450a4b824SJitendra Bhivare 	sge = nonembedded_sgl(wrb);
103550a4b824SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
103650a4b824SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
103750a4b824SJitendra Bhivare 			   OPCODE_ISCSI_INI_SESSION_GET_A_SESSION,
1038fa1261c4SJitendra Bhivare 			   sizeof(struct be_cmd_get_session_resp));
103950a4b824SJitendra Bhivare 	req->session_handle = phba->boot_struct.s_handle;
104050a4b824SJitendra Bhivare 	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
104150a4b824SJitendra Bhivare 	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
104250a4b824SJitendra Bhivare 	sge->len = cpu_to_le32(nonemb_cmd->size);
104350a4b824SJitendra Bhivare 
104450a4b824SJitendra Bhivare 	phba->boot_struct.tag = tag;
104550a4b824SJitendra Bhivare 	set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);
104650a4b824SJitendra Bhivare 	ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;
104750a4b824SJitendra Bhivare 
104850a4b824SJitendra Bhivare 	be_mcc_notify(phba, tag);
104950a4b824SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
105050a4b824SJitendra Bhivare 	return tag;
105150a4b824SJitendra Bhivare }
105250a4b824SJitendra Bhivare 
__beiscsi_boot_get_shandle(struct beiscsi_hba * phba,int async)105350a4b824SJitendra Bhivare unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async)
105450a4b824SJitendra Bhivare {
105550a4b824SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
105650a4b824SJitendra Bhivare 	struct be_mcc_wrb *wrb;
105750a4b824SJitendra Bhivare 	struct be_cmd_get_boot_target_req *req;
105850a4b824SJitendra Bhivare 	unsigned int tag;
105950a4b824SJitendra Bhivare 
106050a4b824SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
106150a4b824SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
106250a4b824SJitendra Bhivare 	if (!wrb) {
106350a4b824SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
106450a4b824SJitendra Bhivare 		return 0;
106550a4b824SJitendra Bhivare 	}
106650a4b824SJitendra Bhivare 
106750a4b824SJitendra Bhivare 	req = embedded_payload(wrb);
106850a4b824SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
106950a4b824SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
107050a4b824SJitendra Bhivare 			   OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET,
107150a4b824SJitendra Bhivare 			   sizeof(struct be_cmd_get_boot_target_resp));
107250a4b824SJitendra Bhivare 
107350a4b824SJitendra Bhivare 	if (async) {
107450a4b824SJitendra Bhivare 		phba->boot_struct.tag = tag;
107550a4b824SJitendra Bhivare 		set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);
107650a4b824SJitendra Bhivare 		ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;
107750a4b824SJitendra Bhivare 	}
107850a4b824SJitendra Bhivare 
107950a4b824SJitendra Bhivare 	be_mcc_notify(phba, tag);
108050a4b824SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
108150a4b824SJitendra Bhivare 	return tag;
108250a4b824SJitendra Bhivare }
108350a4b824SJitendra Bhivare 
108450a4b824SJitendra Bhivare /**
108550a4b824SJitendra Bhivare  * beiscsi_boot_get_shandle()- Get boot session handle
10869aef4200SJohn Soni Jose  * @phba: device priv structure instance
10879aef4200SJohn Soni Jose  * @s_handle: session handle returned for boot session.
10889aef4200SJohn Soni Jose  *
10899aef4200SJohn Soni Jose  * return
109050a4b824SJitendra Bhivare  *	Success: 1
109150a4b824SJitendra Bhivare  *	Failure: negative
10929aef4200SJohn Soni Jose  *
10939aef4200SJohn Soni Jose  **/
beiscsi_boot_get_shandle(struct beiscsi_hba * phba,unsigned int * s_handle)109450a4b824SJitendra Bhivare int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle)
10959aef4200SJohn Soni Jose {
10969aef4200SJohn Soni Jose 	struct be_cmd_get_boot_target_resp *boot_resp;
10979aef4200SJohn Soni Jose 	struct be_mcc_wrb *wrb;
1098e175defeSJohn Soni Jose 	unsigned int tag;
1099e175defeSJohn Soni Jose 	int rc;
11009aef4200SJohn Soni Jose 
110150a4b824SJitendra Bhivare 	*s_handle = BE_BOOT_INVALID_SHANDLE;
110250a4b824SJitendra Bhivare 	/* get configured boot session count and handle */
110350a4b824SJitendra Bhivare 	tag = __beiscsi_boot_get_shandle(phba, 0);
11049aef4200SJohn Soni Jose 	if (!tag) {
110599bc5d55SJohn Soni Jose 		beiscsi_log(phba, KERN_ERR,
110699bc5d55SJohn Soni Jose 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
110799bc5d55SJohn Soni Jose 			    "BG_%d : Getting Boot Target Info Failed\n");
11089aef4200SJohn Soni Jose 		return -EAGAIN;
1109e175defeSJohn Soni Jose 	}
11109aef4200SJohn Soni Jose 
111188840332SJitendra Bhivare 	rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
1112e175defeSJohn Soni Jose 	if (rc) {
111399bc5d55SJohn Soni Jose 		beiscsi_log(phba, KERN_ERR,
111499bc5d55SJohn Soni Jose 			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
1115e175defeSJohn Soni Jose 			    "BG_%d : MBX CMD get_boot_target Failed\n");
11169aef4200SJohn Soni Jose 		return -EBUSY;
11179aef4200SJohn Soni Jose 	}
1118e175defeSJohn Soni Jose 
11199aef4200SJohn Soni Jose 	boot_resp = embedded_payload(wrb);
112050a4b824SJitendra Bhivare 	/* check if there are any boot targets configured */
11219aef4200SJohn Soni Jose 	if (!boot_resp->boot_session_count) {
112250a4b824SJitendra Bhivare 		__beiscsi_log(phba, KERN_INFO,
112350a4b824SJitendra Bhivare 			      "BG_%d : No boot targets configured\n");
11249aef4200SJohn Soni Jose 		return -ENXIO;
11259aef4200SJohn Soni Jose 	}
11269aef4200SJohn Soni Jose 
112750a4b824SJitendra Bhivare 	/* only if FW has logged in to the boot target, s_handle is valid */
11289aef4200SJohn Soni Jose 	*s_handle = boot_resp->boot_session_handle;
112950a4b824SJitendra Bhivare 	return 1;
11309aef4200SJohn Soni Jose }
11316f72238eSJohn Soni Jose 
11326f72238eSJohn Soni Jose /**
11335cac7596SJohn Soni Jose  * beiscsi_drvr_ver_disp()- Display the driver Name and Version
11345cac7596SJohn Soni Jose  * @dev: ptr to device not used.
11355cac7596SJohn Soni Jose  * @attr: device attribute, not used.
11365cac7596SJohn Soni Jose  * @buf: contains formatted text driver name and version
11375cac7596SJohn Soni Jose  *
11385cac7596SJohn Soni Jose  * return
11395cac7596SJohn Soni Jose  * size of the formatted string
11405cac7596SJohn Soni Jose  **/
11415cac7596SJohn Soni Jose ssize_t
beiscsi_drvr_ver_disp(struct device * dev,struct device_attribute * attr,char * buf)11425cac7596SJohn Soni Jose beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr,
11435cac7596SJohn Soni Jose 		       char *buf)
11445cac7596SJohn Soni Jose {
11455cac7596SJohn Soni Jose 	return snprintf(buf, PAGE_SIZE, BE_NAME "\n");
11465cac7596SJohn Soni Jose }
1147acb9693cSJohn Soni Jose 
114826000db7SJohn Soni Jose /**
114922661e25SJayamohan Kallickal  * beiscsi_fw_ver_disp()- Display Firmware Version
115022661e25SJayamohan Kallickal  * @dev: ptr to device not used.
115122661e25SJayamohan Kallickal  * @attr: device attribute, not used.
115222661e25SJayamohan Kallickal  * @buf: contains formatted text Firmware version
115322661e25SJayamohan Kallickal  *
115422661e25SJayamohan Kallickal  * return
115522661e25SJayamohan Kallickal  * size of the formatted string
115622661e25SJayamohan Kallickal  **/
115722661e25SJayamohan Kallickal ssize_t
beiscsi_fw_ver_disp(struct device * dev,struct device_attribute * attr,char * buf)115822661e25SJayamohan Kallickal beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr,
115922661e25SJayamohan Kallickal 		     char *buf)
116022661e25SJayamohan Kallickal {
116122661e25SJayamohan Kallickal 	struct Scsi_Host *shost = class_to_shost(dev);
116222661e25SJayamohan Kallickal 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
116322661e25SJayamohan Kallickal 
116422661e25SJayamohan Kallickal 	return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str);
116522661e25SJayamohan Kallickal }
116622661e25SJayamohan Kallickal 
116722661e25SJayamohan Kallickal /**
11686103c1f7SJayamohan Kallickal  * beiscsi_active_session_disp()- Display Sessions Active
11697ad4dfe1SJayamohan Kallickal  * @dev: ptr to device not used.
11707ad4dfe1SJayamohan Kallickal  * @attr: device attribute, not used.
11717ad4dfe1SJayamohan Kallickal  * @buf: contains formatted text Session Count
11727ad4dfe1SJayamohan Kallickal  *
11737ad4dfe1SJayamohan Kallickal  * return
11747ad4dfe1SJayamohan Kallickal  * size of the formatted string
11757ad4dfe1SJayamohan Kallickal  **/
11767ad4dfe1SJayamohan Kallickal ssize_t
beiscsi_active_session_disp(struct device * dev,struct device_attribute * attr,char * buf)11776103c1f7SJayamohan Kallickal beiscsi_active_session_disp(struct device *dev, struct device_attribute *attr,
11787ad4dfe1SJayamohan Kallickal 			 char *buf)
11797ad4dfe1SJayamohan Kallickal {
11807ad4dfe1SJayamohan Kallickal 	struct Scsi_Host *shost = class_to_shost(dev);
11817ad4dfe1SJayamohan Kallickal 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
11820a3db7c0SJayamohan Kallickal 	uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0;
11837ad4dfe1SJayamohan Kallickal 
11840a3db7c0SJayamohan Kallickal 	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
11850a3db7c0SJayamohan Kallickal 		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) {
11860a3db7c0SJayamohan Kallickal 			avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num);
11870a3db7c0SJayamohan Kallickal 			total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num);
11887cd1615eSTakashi Iwai 			len += scnprintf(buf+len, PAGE_SIZE - len,
11890a3db7c0SJayamohan Kallickal 					 "ULP%d : %d\n", ulp_num,
11900a3db7c0SJayamohan Kallickal 					 (total_cids - avlbl_cids));
11910a3db7c0SJayamohan Kallickal 		} else
11927cd1615eSTakashi Iwai 			len += scnprintf(buf+len, PAGE_SIZE - len,
11930a3db7c0SJayamohan Kallickal 					 "ULP%d : %d\n", ulp_num, 0);
11940a3db7c0SJayamohan Kallickal 	}
11950a3db7c0SJayamohan Kallickal 
11960a3db7c0SJayamohan Kallickal 	return len;
11977ad4dfe1SJayamohan Kallickal }
11987ad4dfe1SJayamohan Kallickal 
11997ad4dfe1SJayamohan Kallickal /**
12006103c1f7SJayamohan Kallickal  * beiscsi_free_session_disp()- Display Avaliable Session
12016103c1f7SJayamohan Kallickal  * @dev: ptr to device not used.
12026103c1f7SJayamohan Kallickal  * @attr: device attribute, not used.
12036103c1f7SJayamohan Kallickal  * @buf: contains formatted text Session Count
12046103c1f7SJayamohan Kallickal  *
12056103c1f7SJayamohan Kallickal  * return
12066103c1f7SJayamohan Kallickal  * size of the formatted string
12076103c1f7SJayamohan Kallickal  **/
12086103c1f7SJayamohan Kallickal ssize_t
beiscsi_free_session_disp(struct device * dev,struct device_attribute * attr,char * buf)12096103c1f7SJayamohan Kallickal beiscsi_free_session_disp(struct device *dev, struct device_attribute *attr,
12106103c1f7SJayamohan Kallickal 		       char *buf)
12116103c1f7SJayamohan Kallickal {
12126103c1f7SJayamohan Kallickal 	struct Scsi_Host *shost = class_to_shost(dev);
12136103c1f7SJayamohan Kallickal 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
12146103c1f7SJayamohan Kallickal 	uint16_t ulp_num, len = 0;
12156103c1f7SJayamohan Kallickal 
12166103c1f7SJayamohan Kallickal 	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
12176103c1f7SJayamohan Kallickal 		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported))
12187cd1615eSTakashi Iwai 			len += scnprintf(buf+len, PAGE_SIZE - len,
12196103c1f7SJayamohan Kallickal 					 "ULP%d : %d\n", ulp_num,
12206103c1f7SJayamohan Kallickal 					 BEISCSI_ULP_AVLBL_CID(phba, ulp_num));
12216103c1f7SJayamohan Kallickal 		else
12227cd1615eSTakashi Iwai 			len += scnprintf(buf+len, PAGE_SIZE - len,
12236103c1f7SJayamohan Kallickal 					 "ULP%d : %d\n", ulp_num, 0);
12246103c1f7SJayamohan Kallickal 	}
12256103c1f7SJayamohan Kallickal 
12266103c1f7SJayamohan Kallickal 	return len;
12276103c1f7SJayamohan Kallickal }
12286103c1f7SJayamohan Kallickal 
12296103c1f7SJayamohan Kallickal /**
123026000db7SJohn Soni Jose  * beiscsi_adap_family_disp()- Display adapter family.
123126000db7SJohn Soni Jose  * @dev: ptr to device to get priv structure
123226000db7SJohn Soni Jose  * @attr: device attribute, not used.
123326000db7SJohn Soni Jose  * @buf: contains formatted text driver name and version
123426000db7SJohn Soni Jose  *
123526000db7SJohn Soni Jose  * return
123626000db7SJohn Soni Jose  * size of the formatted string
123726000db7SJohn Soni Jose  **/
123826000db7SJohn Soni Jose ssize_t
beiscsi_adap_family_disp(struct device * dev,struct device_attribute * attr,char * buf)123926000db7SJohn Soni Jose beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,
124026000db7SJohn Soni Jose 			  char *buf)
124126000db7SJohn Soni Jose {
124226000db7SJohn Soni Jose 	uint16_t dev_id = 0;
124326000db7SJohn Soni Jose 	struct Scsi_Host *shost = class_to_shost(dev);
124426000db7SJohn Soni Jose 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
124526000db7SJohn Soni Jose 
124626000db7SJohn Soni Jose 	dev_id = phba->pcidev->device;
124726000db7SJohn Soni Jose 	switch (dev_id) {
124826000db7SJohn Soni Jose 	case BE_DEVICE_ID1:
124926000db7SJohn Soni Jose 	case OC_DEVICE_ID1:
125026000db7SJohn Soni Jose 	case OC_DEVICE_ID2:
12515fa7db21SKetan Mukadam 		return snprintf(buf, PAGE_SIZE,
12525fa7db21SKetan Mukadam 				"Obsolete/Unsupported BE2 Adapter Family\n");
125326000db7SJohn Soni Jose 	case BE_DEVICE_ID2:
125426000db7SJohn Soni Jose 	case OC_DEVICE_ID3:
125526000db7SJohn Soni Jose 		return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n");
125626000db7SJohn Soni Jose 	case OC_SKH_ID1:
125726000db7SJohn Soni Jose 		return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n");
125826000db7SJohn Soni Jose 	default:
125926000db7SJohn Soni Jose 		return snprintf(buf, PAGE_SIZE,
1260b23f7a09SMasanari Iida 				"Unknown Adapter Family: 0x%x\n", dev_id);
126126000db7SJohn Soni Jose 	}
126226000db7SJohn Soni Jose }
126326000db7SJohn Soni Jose 
1264d3fea9afSJayamohan Kallickal /**
1265ab4bab7aSLee Jones  * beiscsi_phys_port_disp()- Display Physical Port Identifier
1266d3fea9afSJayamohan Kallickal  * @dev: ptr to device not used.
1267d3fea9afSJayamohan Kallickal  * @attr: device attribute, not used.
1268d3fea9afSJayamohan Kallickal  * @buf: contains formatted text port identifier
1269d3fea9afSJayamohan Kallickal  *
1270d3fea9afSJayamohan Kallickal  * return
1271d3fea9afSJayamohan Kallickal  * size of the formatted string
1272d3fea9afSJayamohan Kallickal  **/
1273d3fea9afSJayamohan Kallickal ssize_t
beiscsi_phys_port_disp(struct device * dev,struct device_attribute * attr,char * buf)1274d3fea9afSJayamohan Kallickal beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
1275d3fea9afSJayamohan Kallickal 			 char *buf)
1276d3fea9afSJayamohan Kallickal {
1277d3fea9afSJayamohan Kallickal 	struct Scsi_Host *shost = class_to_shost(dev);
1278d3fea9afSJayamohan Kallickal 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
1279d3fea9afSJayamohan Kallickal 
1280fa1261c4SJitendra Bhivare 	return snprintf(buf, PAGE_SIZE, "Port Identifier : %u\n",
1281d3fea9afSJayamohan Kallickal 			phba->fw_config.phys_port);
1282d3fea9afSJayamohan Kallickal }
128326000db7SJohn Soni Jose 
beiscsi_offload_cxn_v0(struct beiscsi_offload_params * params,struct wrb_handle * pwrb_handle,struct be_mem_descriptor * mem_descr,struct hwi_wrb_context * pwrb_context)1284acb9693cSJohn Soni Jose void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
1285acb9693cSJohn Soni Jose 			     struct wrb_handle *pwrb_handle,
1286340c99e9SJohn Soni Jose 			     struct be_mem_descriptor *mem_descr,
1287340c99e9SJohn Soni Jose 			     struct hwi_wrb_context *pwrb_context)
1288acb9693cSJohn Soni Jose {
1289acb9693cSJohn Soni Jose 	struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
1290acb9693cSJohn Soni Jose 
1291acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1292acb9693cSJohn Soni Jose 		      max_send_data_segment_length, pwrb,
1293acb9693cSJohn Soni Jose 		      params->dw[offsetof(struct amap_beiscsi_offload_params,
1294acb9693cSJohn Soni Jose 		      max_send_data_segment_length) / 32]);
1295acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
1296acb9693cSJohn Soni Jose 		      BE_TGT_CTX_UPDT_CMD);
1297acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1298acb9693cSJohn Soni Jose 		      first_burst_length,
1299acb9693cSJohn Soni Jose 		      pwrb,
1300acb9693cSJohn Soni Jose 		      params->dw[offsetof(struct amap_beiscsi_offload_params,
1301acb9693cSJohn Soni Jose 		      first_burst_length) / 32]);
1302acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
1303acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1304acb9693cSJohn Soni Jose 		      erl) / 32] & OFFLD_PARAMS_ERL));
1305acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
1306acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1307acb9693cSJohn Soni Jose 		       dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
1308acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
1309acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1310acb9693cSJohn Soni Jose 		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
1311acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
1312acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1313acb9693cSJohn Soni Jose 		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
1314acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
1315acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1316acb9693cSJohn Soni Jose 		      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
1317acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
1318acb9693cSJohn Soni Jose 		      pwrb,
1319acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1320acb9693cSJohn Soni Jose 		      exp_statsn) / 32] + 1));
1321acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
1322acb9693cSJohn Soni Jose 		      pwrb, pwrb_handle->wrb_index);
1323acb9693cSJohn Soni Jose 
1324acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1325acb9693cSJohn Soni Jose 		      max_burst_length, pwrb, params->dw[offsetof
1326acb9693cSJohn Soni Jose 		      (struct amap_beiscsi_offload_params,
1327acb9693cSJohn Soni Jose 		      max_burst_length) / 32]);
1328acb9693cSJohn Soni Jose 
1329acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
1330340c99e9SJohn Soni Jose 		      pwrb, pwrb_handle->wrb_index);
1331340c99e9SJohn Soni Jose 	if (pwrb_context->plast_wrb)
1332340c99e9SJohn Soni Jose 		AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1333340c99e9SJohn Soni Jose 			      ptr2nextwrb,
1334340c99e9SJohn Soni Jose 			      pwrb_context->plast_wrb,
1335340c99e9SJohn Soni Jose 			      pwrb_handle->wrb_index);
1336340c99e9SJohn Soni Jose 	pwrb_context->plast_wrb = pwrb;
1337340c99e9SJohn Soni Jose 
1338acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1339acb9693cSJohn Soni Jose 		      session_state, pwrb, 0);
1340acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
1341acb9693cSJohn Soni Jose 		      pwrb, 1);
1342acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
1343acb9693cSJohn Soni Jose 		      pwrb, 0);
1344acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
1345acb9693cSJohn Soni Jose 		      0);
1346acb9693cSJohn Soni Jose 
1347acb9693cSJohn Soni Jose 	mem_descr += ISCSI_MEM_GLOBAL_HEADER;
1348acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1349acb9693cSJohn Soni Jose 		      pad_buffer_addr_hi, pwrb,
1350acb9693cSJohn Soni Jose 		      mem_descr->mem_array[0].bus_address.u.a32.address_hi);
1351acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
1352acb9693cSJohn Soni Jose 		      pad_buffer_addr_lo, pwrb,
1353acb9693cSJohn Soni Jose 		      mem_descr->mem_array[0].bus_address.u.a32.address_lo);
1354acb9693cSJohn Soni Jose }
1355acb9693cSJohn Soni Jose 
beiscsi_offload_cxn_v2(struct beiscsi_offload_params * params,struct wrb_handle * pwrb_handle,struct hwi_wrb_context * pwrb_context)1356acb9693cSJohn Soni Jose void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
1357340c99e9SJohn Soni Jose 			     struct wrb_handle *pwrb_handle,
1358340c99e9SJohn Soni Jose 			     struct hwi_wrb_context *pwrb_context)
1359acb9693cSJohn Soni Jose {
1360acb9693cSJohn Soni Jose 	struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
1361acb9693cSJohn Soni Jose 
1362acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1363acb9693cSJohn Soni Jose 		      max_burst_length, pwrb, params->dw[offsetof
1364acb9693cSJohn Soni Jose 		      (struct amap_beiscsi_offload_params,
1365acb9693cSJohn Soni Jose 		      max_burst_length) / 32]);
1366acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1367acb9693cSJohn Soni Jose 		      type, pwrb,
1368acb9693cSJohn Soni Jose 		      BE_TGT_CTX_UPDT_CMD);
1369acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1370acb9693cSJohn Soni Jose 		      ptr2nextwrb,
1371340c99e9SJohn Soni Jose 		      pwrb, pwrb_handle->wrb_index);
1372340c99e9SJohn Soni Jose 	if (pwrb_context->plast_wrb)
1373340c99e9SJohn Soni Jose 		AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1374340c99e9SJohn Soni Jose 			      ptr2nextwrb,
1375340c99e9SJohn Soni Jose 			      pwrb_context->plast_wrb,
1376340c99e9SJohn Soni Jose 			      pwrb_handle->wrb_index);
1377340c99e9SJohn Soni Jose 	pwrb_context->plast_wrb = pwrb;
1378340c99e9SJohn Soni Jose 
1379acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
1380acb9693cSJohn Soni Jose 		      pwrb, pwrb_handle->wrb_index);
1381acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1382acb9693cSJohn Soni Jose 		      max_send_data_segment_length, pwrb,
1383acb9693cSJohn Soni Jose 		      params->dw[offsetof(struct amap_beiscsi_offload_params,
1384acb9693cSJohn Soni Jose 		      max_send_data_segment_length) / 32]);
1385acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1386acb9693cSJohn Soni Jose 		      first_burst_length, pwrb,
1387acb9693cSJohn Soni Jose 		      params->dw[offsetof(struct amap_beiscsi_offload_params,
1388acb9693cSJohn Soni Jose 		      first_burst_length) / 32]);
1389acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
13907331613eSJayamohan Kallickal 		      max_recv_dataseg_len, pwrb,
13917331613eSJayamohan Kallickal 		      params->dw[offsetof(struct amap_beiscsi_offload_params,
13927331613eSJayamohan Kallickal 		      max_recv_data_segment_length) / 32]);
1393acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1394acb9693cSJohn Soni Jose 		      max_cxns, pwrb, BEISCSI_MAX_CXNS);
1395acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb,
1396acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1397acb9693cSJohn Soni Jose 		      erl) / 32] & OFFLD_PARAMS_ERL));
1398acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb,
1399acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1400acb9693cSJohn Soni Jose 		      dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
1401acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb,
1402acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1403acb9693cSJohn Soni Jose 		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
1404acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1405acb9693cSJohn Soni Jose 		      ir2t, pwrb,
1406acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1407acb9693cSJohn Soni Jose 		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
1408acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb,
1409acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1410acb9693cSJohn Soni Jose 		      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
1411acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1412acb9693cSJohn Soni Jose 		      data_seq_inorder,
1413acb9693cSJohn Soni Jose 		      pwrb,
1414acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1415acb9693cSJohn Soni Jose 		      data_seq_inorder) / 32] &
1416acb9693cSJohn Soni Jose 		      OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6);
1417acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
1418acb9693cSJohn Soni Jose 		      pdu_seq_inorder,
1419acb9693cSJohn Soni Jose 		      pwrb,
1420acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1421acb9693cSJohn Soni Jose 		      pdu_seq_inorder) / 32] &
1422acb9693cSJohn Soni Jose 		      OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7);
1423acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t,
1424acb9693cSJohn Soni Jose 		      pwrb,
1425acb9693cSJohn Soni Jose 		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
1426acb9693cSJohn Soni Jose 		      max_r2t) / 32] &
1427acb9693cSJohn Soni Jose 		      OFFLD_PARAMS_MAX_R2T) >> 8);
1428acb9693cSJohn Soni Jose 	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn,
1429acb9693cSJohn Soni Jose 		      pwrb,
1430acb9693cSJohn Soni Jose 		     (params->dw[offsetof(struct amap_beiscsi_offload_params,
1431acb9693cSJohn Soni Jose 		      exp_statsn) / 32] + 1));
1432acb9693cSJohn Soni Jose }
143398713216SJitendra Bhivare 
beiscsi_invalidate_cxn(struct beiscsi_hba * phba,struct beiscsi_endpoint * beiscsi_ep)143449fc5152SJitendra Bhivare unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba,
143549fc5152SJitendra Bhivare 				    struct beiscsi_endpoint *beiscsi_ep)
143649fc5152SJitendra Bhivare {
143749fc5152SJitendra Bhivare 	struct be_invalidate_connection_params_in *req;
143849fc5152SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
143949fc5152SJitendra Bhivare 	struct be_mcc_wrb *wrb;
144049fc5152SJitendra Bhivare 	unsigned int tag = 0;
144149fc5152SJitendra Bhivare 
144249fc5152SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
144349fc5152SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
144449fc5152SJitendra Bhivare 	if (!wrb) {
144549fc5152SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
144649fc5152SJitendra Bhivare 		return 0;
144749fc5152SJitendra Bhivare 	}
144849fc5152SJitendra Bhivare 
144949fc5152SJitendra Bhivare 	req = embedded_payload(wrb);
145049fc5152SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(union be_invalidate_connection_params),
145149fc5152SJitendra Bhivare 			   true, 0);
145249fc5152SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
145349fc5152SJitendra Bhivare 			   OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
145449fc5152SJitendra Bhivare 			   sizeof(*req));
145549fc5152SJitendra Bhivare 	req->session_handle = beiscsi_ep->fw_handle;
145649fc5152SJitendra Bhivare 	req->cid = beiscsi_ep->ep_cid;
145749fc5152SJitendra Bhivare 	if (beiscsi_ep->conn)
145849fc5152SJitendra Bhivare 		req->cleanup_type = BE_CLEANUP_TYPE_INVALIDATE;
145949fc5152SJitendra Bhivare 	else
146049fc5152SJitendra Bhivare 		req->cleanup_type = BE_CLEANUP_TYPE_ISSUE_TCP_RST;
146149fc5152SJitendra Bhivare 	/**
146249fc5152SJitendra Bhivare 	 * 0 - non-persistent targets
146349fc5152SJitendra Bhivare 	 * 1 - save session info on flash
146449fc5152SJitendra Bhivare 	 */
146549fc5152SJitendra Bhivare 	req->save_cfg = 0;
146649fc5152SJitendra Bhivare 	be_mcc_notify(phba, tag);
146749fc5152SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
146849fc5152SJitendra Bhivare 	return tag;
146949fc5152SJitendra Bhivare }
147049fc5152SJitendra Bhivare 
beiscsi_upload_cxn(struct beiscsi_hba * phba,struct beiscsi_endpoint * beiscsi_ep)147149fc5152SJitendra Bhivare unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba,
147249fc5152SJitendra Bhivare 				struct beiscsi_endpoint *beiscsi_ep)
147349fc5152SJitendra Bhivare {
147449fc5152SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
147549fc5152SJitendra Bhivare 	struct be_mcc_wrb *wrb;
147649fc5152SJitendra Bhivare 	struct be_tcp_upload_params_in *req;
147749fc5152SJitendra Bhivare 	unsigned int tag;
147849fc5152SJitendra Bhivare 
147949fc5152SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
148049fc5152SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
148149fc5152SJitendra Bhivare 	if (!wrb) {
148249fc5152SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
148349fc5152SJitendra Bhivare 		return 0;
148449fc5152SJitendra Bhivare 	}
148549fc5152SJitendra Bhivare 
148649fc5152SJitendra Bhivare 	req = embedded_payload(wrb);
148749fc5152SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, sizeof(union be_tcp_upload_params), true, 0);
148849fc5152SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
148949fc5152SJitendra Bhivare 			   OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
149049fc5152SJitendra Bhivare 	req->id = beiscsi_ep->ep_cid;
149149fc5152SJitendra Bhivare 	if (beiscsi_ep->conn)
149249fc5152SJitendra Bhivare 		req->upload_type = BE_UPLOAD_TYPE_GRACEFUL;
149349fc5152SJitendra Bhivare 	else
149449fc5152SJitendra Bhivare 		req->upload_type = BE_UPLOAD_TYPE_ABORT;
149549fc5152SJitendra Bhivare 	be_mcc_notify(phba, tag);
149649fc5152SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
149749fc5152SJitendra Bhivare 	return tag;
149849fc5152SJitendra Bhivare }
149949fc5152SJitendra Bhivare 
beiscsi_mgmt_invalidate_icds(struct beiscsi_hba * phba,struct invldt_cmd_tbl * inv_tbl,unsigned int nents)150098713216SJitendra Bhivare int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
150198713216SJitendra Bhivare 				 struct invldt_cmd_tbl *inv_tbl,
150298713216SJitendra Bhivare 				 unsigned int nents)
150398713216SJitendra Bhivare {
150498713216SJitendra Bhivare 	struct be_ctrl_info *ctrl = &phba->ctrl;
150598713216SJitendra Bhivare 	struct invldt_cmds_params_in *req;
150698713216SJitendra Bhivare 	struct be_dma_mem nonemb_cmd;
150798713216SJitendra Bhivare 	struct be_mcc_wrb *wrb;
150898713216SJitendra Bhivare 	unsigned int i, tag;
150998713216SJitendra Bhivare 	struct be_sge *sge;
151098713216SJitendra Bhivare 	int rc;
151198713216SJitendra Bhivare 
151298713216SJitendra Bhivare 	if (!nents || nents > BE_INVLDT_CMD_TBL_SZ)
151398713216SJitendra Bhivare 		return -EINVAL;
151498713216SJitendra Bhivare 
151598713216SJitendra Bhivare 	nonemb_cmd.size = sizeof(union be_invldt_cmds_params);
1516750afb08SLuis Chamberlain 	nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
1517750afb08SLuis Chamberlain 					   nonemb_cmd.size, &nonemb_cmd.dma,
151826a4c991SChristoph Hellwig 					   GFP_KERNEL);
151998713216SJitendra Bhivare 	if (!nonemb_cmd.va) {
152098713216SJitendra Bhivare 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
152198713216SJitendra Bhivare 			    "BM_%d : invldt_cmds_params alloc failed\n");
152298713216SJitendra Bhivare 		return -ENOMEM;
152398713216SJitendra Bhivare 	}
152498713216SJitendra Bhivare 
152598713216SJitendra Bhivare 	mutex_lock(&ctrl->mbox_lock);
152698713216SJitendra Bhivare 	wrb = alloc_mcc_wrb(phba, &tag);
152798713216SJitendra Bhivare 	if (!wrb) {
152898713216SJitendra Bhivare 		mutex_unlock(&ctrl->mbox_lock);
152926a4c991SChristoph Hellwig 		dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
153098713216SJitendra Bhivare 				    nonemb_cmd.va, nonemb_cmd.dma);
153198713216SJitendra Bhivare 		return -ENOMEM;
153298713216SJitendra Bhivare 	}
153398713216SJitendra Bhivare 
153498713216SJitendra Bhivare 	req = nonemb_cmd.va;
153598713216SJitendra Bhivare 	be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false, 1);
153698713216SJitendra Bhivare 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
153798713216SJitendra Bhivare 			OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
153898713216SJitendra Bhivare 			sizeof(*req));
153998713216SJitendra Bhivare 	req->ref_handle = 0;
154098713216SJitendra Bhivare 	req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
154198713216SJitendra Bhivare 	for (i = 0; i < nents; i++) {
154298713216SJitendra Bhivare 		req->table[i].icd = inv_tbl[i].icd;
154398713216SJitendra Bhivare 		req->table[i].cid = inv_tbl[i].cid;
154498713216SJitendra Bhivare 		req->icd_count++;
154598713216SJitendra Bhivare 	}
154698713216SJitendra Bhivare 	sge = nonembedded_sgl(wrb);
154798713216SJitendra Bhivare 	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
154898713216SJitendra Bhivare 	sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd.dma));
154998713216SJitendra Bhivare 	sge->len = cpu_to_le32(nonemb_cmd.size);
155098713216SJitendra Bhivare 
155198713216SJitendra Bhivare 	be_mcc_notify(phba, tag);
155298713216SJitendra Bhivare 	mutex_unlock(&ctrl->mbox_lock);
155398713216SJitendra Bhivare 
155498713216SJitendra Bhivare 	rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
155598713216SJitendra Bhivare 	if (rc != -EBUSY)
155626a4c991SChristoph Hellwig 		dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
155798713216SJitendra Bhivare 				    nonemb_cmd.va, nonemb_cmd.dma);
155898713216SJitendra Bhivare 	return rc;
155998713216SJitendra Bhivare }
1560