brintos

brintos / linux-shallow public Read only

0
0
Text · 45.3 KiB · 4e899ec Raw
1560 lines · c
1/*2 * This file is part of the Emulex Linux Device Driver for Enterprise iSCSI3 * Host Bus Adapters. Refer to the README file included with this package4 * for driver version and adapter compatibility.5 *6 * Copyright (c) 2018 Broadcom. All Rights Reserved.7 * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.8 *9 * This program is free software; you can redistribute it and/or modify it10 * under the terms of version 2 of the GNU General Public License as published11 * by the Free Software Foundation.12 *13 * This program is distributed in the hope that it will be useful. ALL EXPRESS14 * OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY15 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,16 * OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH17 * DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.18 * See the GNU General Public License for more details, a copy of which19 * can be found in the file COPYING included with this package.20 *21 * Contact Information:22 * linux-drivers@broadcom.com23 *24 */25 26#include <linux/bsg-lib.h>27#include <scsi/scsi_transport_iscsi.h>28#include <scsi/scsi_bsg_iscsi.h>29#include "be_mgmt.h"30#include "be_iscsi.h"31#include "be_main.h"32 33unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,34					 struct beiscsi_hba *phba,35					 struct bsg_job *job,36					 struct be_dma_mem *nonemb_cmd)37{38	struct be_mcc_wrb *wrb;39	struct be_sge *mcc_sge;40	unsigned int tag = 0;41	struct iscsi_bsg_request *bsg_req = job->request;42	struct be_bsg_vendor_cmd *req = nonemb_cmd->va;43	unsigned short region, sector_size, sector, offset;44 45	nonemb_cmd->size = job->request_payload.payload_len;46	memset(nonemb_cmd->va, 0, nonemb_cmd->size);47	region =  bsg_req->rqst_data.h_vendor.vendor_cmd[1];48	sector_size =  bsg_req->rqst_data.h_vendor.vendor_cmd[2];49	sector =  bsg_req->rqst_data.h_vendor.vendor_cmd[3];50	offset =  bsg_req->rqst_data.h_vendor.vendor_cmd[4];51	req->region = region;52	req->sector = sector;53	req->offset = offset;54 55	if (mutex_lock_interruptible(&ctrl->mbox_lock))56		return 0;57	switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {58	case BEISCSI_WRITE_FLASH:59		offset = sector * sector_size + offset;60		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,61				   OPCODE_COMMON_WRITE_FLASH, sizeof(*req));62		sg_copy_to_buffer(job->request_payload.sg_list,63				  job->request_payload.sg_cnt,64				  nonemb_cmd->va + offset, job->request_len);65		break;66	case BEISCSI_READ_FLASH:67		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,68			   OPCODE_COMMON_READ_FLASH, sizeof(*req));69		break;70	default:71		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,72			    "BG_%d : Unsupported cmd = 0x%x\n\n",73			    bsg_req->rqst_data.h_vendor.vendor_cmd[0]);74 75		mutex_unlock(&ctrl->mbox_lock);76		return -EPERM;77	}78 79	wrb = alloc_mcc_wrb(phba, &tag);80	if (!wrb) {81		mutex_unlock(&ctrl->mbox_lock);82		return 0;83	}84 85	mcc_sge = nonembedded_sgl(wrb);86	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false,87			   job->request_payload.sg_cnt);88	mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));89	mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);90	mcc_sge->len = cpu_to_le32(nonemb_cmd->size);91 92	be_mcc_notify(phba, tag);93 94	mutex_unlock(&ctrl->mbox_lock);95	return tag;96}97 98/**99 * mgmt_open_connection()- Establish a TCP CXN100 * @phba: driver priv structure101 * @dst_addr: Destination Address102 * @beiscsi_ep: ptr to device endpoint struct103 * @nonemb_cmd: ptr to memory allocated for command104 *105 * return106 *	Success: Tag number of the MBX Command issued107 *	Failure: Error code108 **/109int mgmt_open_connection(struct beiscsi_hba *phba,110			 struct sockaddr *dst_addr,111			 struct beiscsi_endpoint *beiscsi_ep,112			 struct be_dma_mem *nonemb_cmd)113{114	struct hwi_controller *phwi_ctrlr;115	struct hwi_context_memory *phwi_context;116	struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;117	struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;118	struct be_ctrl_info *ctrl = &phba->ctrl;119	struct be_mcc_wrb *wrb;120	struct tcp_connect_and_offload_in_v1 *req;121	unsigned short def_hdr_id;122	unsigned short def_data_id;123	struct phys_addr template_address = { 0, 0 };124	struct phys_addr *ptemplate_address;125	unsigned int tag = 0;126	unsigned int i, ulp_num;127	unsigned short cid = beiscsi_ep->ep_cid;128	struct be_sge *sge;129 130	if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) {131		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,132			    "BG_%d : unknown addr family %d\n",133			    dst_addr->sa_family);134		return 0;135	}136 137	phwi_ctrlr = phba->phwi_ctrlr;138	phwi_context = phwi_ctrlr->phwi_ctxt;139 140	ulp_num = phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(cid)].ulp_num;141 142	def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba, ulp_num);143	def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba, ulp_num);144 145	ptemplate_address = &template_address;146	ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);147	if (mutex_lock_interruptible(&ctrl->mbox_lock))148		return 0;149	wrb = alloc_mcc_wrb(phba, &tag);150	if (!wrb) {151		mutex_unlock(&ctrl->mbox_lock);152		return 0;153	}154 155	sge = nonembedded_sgl(wrb);156	req = nonemb_cmd->va;157	memset(req, 0, sizeof(*req));158 159	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);160	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,161			   OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,162			   nonemb_cmd->size);163	if (dst_addr->sa_family == PF_INET) {164		__be32 s_addr = daddr_in->sin_addr.s_addr;165		req->ip_address.ip_type = BEISCSI_IP_TYPE_V4;166		req->ip_address.addr[0] = s_addr & 0x000000ff;167		req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8;168		req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16;169		req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24;170		req->tcp_port = ntohs(daddr_in->sin_port);171		beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;172		beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);173		beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V4;174	} else {175		/* else its PF_INET6 family */176		req->ip_address.ip_type = BEISCSI_IP_TYPE_V6;177		memcpy(&req->ip_address.addr,178		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);179		req->tcp_port = ntohs(daddr_in6->sin6_port);180		beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);181		memcpy(&beiscsi_ep->dst6_addr,182		       &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);183		beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V6;184	}185	req->cid = cid;186	i = phba->nxt_cqid++;187	if (phba->nxt_cqid == phba->num_cpus)188		phba->nxt_cqid = 0;189	req->cq_id = phwi_context->be_cq[i].id;190	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,191		    "BG_%d : i=%d cq_id=%d\n", i, req->cq_id);192	req->defq_id = def_hdr_id;193	req->hdr_ring_id = def_hdr_id;194	req->data_ring_id = def_data_id;195	req->do_offload = 1;196	req->dataout_template_pa.lo = ptemplate_address->lo;197	req->dataout_template_pa.hi = ptemplate_address->hi;198	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));199	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);200	sge->len = cpu_to_le32(nonemb_cmd->size);201 202	if (!is_chip_be2_be3r(phba)) {203		req->hdr.version = MBX_CMD_VER1;204		req->tcp_window_size = 0x8000;205		req->tcp_window_scale_count = 2;206	}207 208	be_mcc_notify(phba, tag);209	mutex_unlock(&ctrl->mbox_lock);210	return tag;211}212 213/**214 * beiscsi_exec_nemb_cmd()- execute non-embedded MBX cmd215 * @phba: driver priv structure216 * @nonemb_cmd: DMA address of the MBX command to be issued217 * @cbfn: callback func on MCC completion218 * @resp_buf: buffer to copy the MBX cmd response219 * @resp_buf_len: response length to be copied220 *221 **/222static int beiscsi_exec_nemb_cmd(struct beiscsi_hba *phba,223				 struct be_dma_mem *nonemb_cmd,224				 void (*cbfn)(struct beiscsi_hba *,225					      unsigned int),226				 void *resp_buf, u32 resp_buf_len)227{228	struct be_ctrl_info *ctrl = &phba->ctrl;229	struct be_mcc_wrb *wrb;230	struct be_sge *sge;231	unsigned int tag;232	int rc = 0;233 234	mutex_lock(&ctrl->mbox_lock);235	wrb = alloc_mcc_wrb(phba, &tag);236	if (!wrb) {237		mutex_unlock(&ctrl->mbox_lock);238		return -ENOMEM;239	}240 241	sge = nonembedded_sgl(wrb);242	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);243	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));244	sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma));245	sge->len = cpu_to_le32(nonemb_cmd->size);246 247	if (cbfn) {248		struct be_dma_mem *tag_mem;249 250		set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);251		ctrl->ptag_state[tag].cbfn = cbfn;252		tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;253 254		/* store DMA mem to be freed in callback */255		tag_mem->size = nonemb_cmd->size;256		tag_mem->va = nonemb_cmd->va;257		tag_mem->dma = nonemb_cmd->dma;258	}259	be_mcc_notify(phba, tag);260	mutex_unlock(&ctrl->mbox_lock);261 262	/* with cbfn set, its async cmd, don't wait */263	if (cbfn)264		return 0;265 266	rc = beiscsi_mccq_compl_wait(phba, tag, NULL, nonemb_cmd);267 268	/* copy the response, if any */269	if (resp_buf)270		memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);271	return rc;272}273 274static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,275				 struct be_dma_mem *cmd,276				 u8 subsystem, u8 opcode, u32 size)277{278	cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,279				     GFP_KERNEL);280	if (!cmd->va) {281		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,282			    "BG_%d : Failed to allocate memory for if info\n");283		return -ENOMEM;284	}285	cmd->size = size;286	be_cmd_hdr_prepare(cmd->va, subsystem, opcode, size);287	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,288		    "BG_%d : subsystem %u cmd %u size %u\n",289		    subsystem, opcode, size);290	return 0;291}292 293static void beiscsi_free_nemb_cmd(struct beiscsi_hba *phba,294				  struct be_dma_mem *cmd, int rc)295{296	/*297	 * If FW is busy the DMA buffer is saved with the tag. When the cmd298	 * completes this buffer is freed.299	 */300	if (rc == -EBUSY)301		return;302 303	dma_free_coherent(&phba->ctrl.pdev->dev, cmd->size, cmd->va, cmd->dma);304}305 306static void __beiscsi_eq_delay_compl(struct beiscsi_hba *phba, unsigned int tag)307{308	struct be_dma_mem *tag_mem;309 310	/* status is ignored */311	__beiscsi_mcc_compl_status(phba, tag, NULL, NULL);312	tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;313	if (tag_mem->size) {314		dma_free_coherent(&phba->pcidev->dev, tag_mem->size,315				    tag_mem->va, tag_mem->dma);316		tag_mem->size = 0;317	}318}319 320int beiscsi_modify_eq_delay(struct beiscsi_hba *phba,321			    struct be_set_eqd *set_eqd, int num)322{323	struct be_cmd_req_modify_eq_delay *req;324	struct be_dma_mem nonemb_cmd;325	int i, rc;326 327	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_COMMON,328			OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));329	if (rc)330		return rc;331 332	req = nonemb_cmd.va;333	req->num_eq = cpu_to_le32(num);334	for (i = 0; i < num; i++) {335		req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id);336		req->delay[i].phase = 0;337		req->delay[i].delay_multiplier =338				cpu_to_le32(set_eqd[i].delay_multiplier);339	}340 341	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, __beiscsi_eq_delay_compl,342				   NULL, 0);343	if (rc) {344		/*345		 * Only free on failure. Async cmds are handled like -EBUSY346		 * where it's handled for us.347		 */348		beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);349	}350	return rc;351}352 353/**354 * beiscsi_get_initiator_name - read initiator name from flash355 * @phba: device priv structure356 * @name: buffer pointer357 * @cfg: fetch user configured358 *359 */360int beiscsi_get_initiator_name(struct beiscsi_hba *phba, char *name, bool cfg)361{362	struct be_dma_mem nonemb_cmd;363	struct be_cmd_hba_name resp;364	struct be_cmd_hba_name *req;365	int rc;366 367	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI_INI,368			OPCODE_ISCSI_INI_CFG_GET_HBA_NAME, sizeof(resp));369	if (rc)370		return rc;371 372	req = nonemb_cmd.va;373	if (cfg)374		req->hdr.version = 1;375	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL,376				   &resp, sizeof(resp));377	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);378	if (rc) {379		beiscsi_log(phba, KERN_ERR,380			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,381			    "BS_%d : Initiator Name MBX Failed\n");382		return rc;383	}384	rc = sprintf(name, "%s\n", resp.initiator_name);385	return rc;386}387 388unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba)389{390	struct be_ctrl_info *ctrl = &phba->ctrl;391	struct be_mcc_wrb *wrb;392	struct be_cmd_get_all_if_id_req *req;393	struct be_cmd_get_all_if_id_req *pbe_allid;394	unsigned int tag;395	int status = 0;396 397	if (mutex_lock_interruptible(&ctrl->mbox_lock))398		return -EINTR;399	wrb = alloc_mcc_wrb(phba, &tag);400	if (!wrb) {401		mutex_unlock(&ctrl->mbox_lock);402		return -ENOMEM;403	}404 405	req = embedded_payload(wrb);406	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);407	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,408			   OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID,409			   sizeof(*req));410	be_mcc_notify(phba, tag);411	mutex_unlock(&ctrl->mbox_lock);412 413	status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);414	if (status) {415		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,416			    "BG_%d : %s failed: %d\n", __func__, status);417		return -EBUSY;418	}419 420	pbe_allid = embedded_payload(wrb);421	/* we now support only one interface per function */422	phba->interface_handle = pbe_allid->if_hndl_list[0];423 424	return status;425}426 427static inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type)428{429	u32 len;430 431	len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN;432	while (len && !ip[len - 1])433		len--;434	return (len == 0);435}436 437static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,438			     u32 action, u32 ip_type, u8 *gw)439{440	struct be_cmd_set_def_gateway_req *req;441	struct be_dma_mem nonemb_cmd;442	int rt_val;443 444	rt_val = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,445			OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY,446			sizeof(*req));447	if (rt_val)448		return rt_val;449 450	req = nonemb_cmd.va;451	req->action = action;452	req->ip_addr.ip_type = ip_type;453	memcpy(req->ip_addr.addr, gw,454	       (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN);455	rt_val = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);456	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rt_val);457	return rt_val;458}459 460int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw)461{462	struct be_cmd_get_def_gateway_resp gw_resp;463	int rt_val;464 465	memset(&gw_resp, 0, sizeof(gw_resp));466	rt_val = beiscsi_if_get_gw(phba, ip_type, &gw_resp);467	if (rt_val) {468		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,469			    "BG_%d : Failed to Get Gateway Addr\n");470		return rt_val;471	}472 473	if (!beiscsi_if_zero_ip(gw_resp.ip_addr.addr, ip_type)) {474		rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type,475					   gw_resp.ip_addr.addr);476		if (rt_val) {477			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,478				    "BG_%d : Failed to clear Gateway Addr Set\n");479			return rt_val;480		}481	}482 483	rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw);484	if (rt_val)485		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,486			    "BG_%d : Failed to Set Gateway Addr\n");487 488	return rt_val;489}490 491int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type,492		      struct be_cmd_get_def_gateway_resp *resp)493{494	struct be_cmd_get_def_gateway_req *req;495	struct be_dma_mem nonemb_cmd;496	int rc;497 498	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,499			OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY,500			sizeof(*resp));501	if (rc)502		return rc;503 504	req = nonemb_cmd.va;505	req->ip_type = ip_type;506 507	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, resp,508				   sizeof(*resp));509	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);510	return rc;511}512 513static int514beiscsi_if_clr_ip(struct beiscsi_hba *phba,515		  struct be_cmd_get_if_info_resp *if_info)516{517	struct be_cmd_set_ip_addr_req *req;518	struct be_dma_mem nonemb_cmd;519	int rc;520 521	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,522			OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,523			sizeof(*req));524	if (rc)525		return rc;526 527	req = nonemb_cmd.va;528	req->ip_params.record_entry_count = 1;529	req->ip_params.ip_record.action = IP_ACTION_DEL;530	req->ip_params.ip_record.interface_hndl =531		phba->interface_handle;532	req->ip_params.ip_record.ip_addr.size_of_structure =533		sizeof(struct be_ip_addr_subnet_format);534	req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type;535	memcpy(req->ip_params.ip_record.ip_addr.addr,536	       if_info->ip_addr.addr,537	       sizeof(if_info->ip_addr.addr));538	memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,539	       if_info->ip_addr.subnet_mask,540	       sizeof(if_info->ip_addr.subnet_mask));541	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);542	if (rc < 0 || req->ip_params.ip_record.status) {543		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,544			    "BG_%d : failed to clear IP: rc %d status %d\n",545			    rc, req->ip_params.ip_record.status);546	}547	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);548	return rc;549}550 551static int552beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,553		  u8 *subnet, u32 ip_type)554{555	struct be_cmd_set_ip_addr_req *req;556	struct be_dma_mem nonemb_cmd;557	uint32_t ip_len;558	int rc;559 560	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,561			OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,562			sizeof(*req));563	if (rc)564		return rc;565 566	req = nonemb_cmd.va;567	req->ip_params.record_entry_count = 1;568	req->ip_params.ip_record.action = IP_ACTION_ADD;569	req->ip_params.ip_record.interface_hndl =570		phba->interface_handle;571	req->ip_params.ip_record.ip_addr.size_of_structure =572		sizeof(struct be_ip_addr_subnet_format);573	req->ip_params.ip_record.ip_addr.ip_type = ip_type;574	ip_len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN;575	memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len);576	if (subnet)577		memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,578		       subnet, ip_len);579 580	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);581	/**582	 * In some cases, host needs to look into individual record status583	 * even though FW reported success for that IOCTL.584	 */585	if (rc < 0 || req->ip_params.ip_record.status) {586		__beiscsi_log(phba, KERN_ERR,587			    "BG_%d : failed to set IP: rc %d status %d\n",588			    rc, req->ip_params.ip_record.status);589		if (req->ip_params.ip_record.status)590			rc = -EINVAL;591	}592	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);593	return rc;594}595 596int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,597			 u8 *ip, u8 *subnet)598{599	struct be_cmd_get_if_info_resp *if_info;600	struct be_cmd_rel_dhcp_req *reldhcp;601	struct be_dma_mem nonemb_cmd;602	int rc;603 604	rc = beiscsi_if_get_info(phba, ip_type, &if_info);605	if (rc)606		return rc;607 608	if (if_info->dhcp_state) {609		rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd,610				CMD_SUBSYSTEM_ISCSI,611				OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,612				sizeof(*reldhcp));613		if (rc)614			goto exit;615 616		reldhcp = nonemb_cmd.va;617		reldhcp->interface_hndl = phba->interface_handle;618		reldhcp->ip_type = ip_type;619		rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);620		beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);621		if (rc < 0) {622			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,623				    "BG_%d : failed to release existing DHCP: %d\n",624				    rc);625			goto exit;626		}627	}628 629	/* first delete any IP set */630	if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) {631		rc = beiscsi_if_clr_ip(phba, if_info);632		if (rc)633			goto exit;634	}635 636	/* if ip == NULL then this is called just to release DHCP IP */637	if (ip)638		rc = beiscsi_if_set_ip(phba, ip, subnet, ip_type);639exit:640	kfree(if_info);641	return rc;642}643 644int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)645{646	struct be_cmd_get_def_gateway_resp gw_resp;647	struct be_cmd_get_if_info_resp *if_info;648	struct be_cmd_set_dhcp_req *dhcpreq;649	struct be_dma_mem nonemb_cmd;650	u8 *gw;651	int rc;652 653	rc = beiscsi_if_get_info(phba, ip_type, &if_info);654	if (rc)655		return rc;656 657	if (if_info->dhcp_state) {658		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,659				"BG_%d : DHCP Already Enabled\n");660		goto exit;661	}662 663	/* first delete any IP set */664	if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) {665		rc = beiscsi_if_clr_ip(phba, if_info);666		if (rc)667			goto exit;668	}669 670	/* delete gateway settings if mode change is to DHCP */671	memset(&gw_resp, 0, sizeof(gw_resp));672	/* use ip_type provided in if_info */673	rc = beiscsi_if_get_gw(phba, if_info->ip_addr.ip_type, &gw_resp);674	if (rc) {675		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,676			    "BG_%d : Failed to Get Gateway Addr\n");677		goto exit;678	}679	gw = (u8 *)&gw_resp.ip_addr.addr;680	if (!beiscsi_if_zero_ip(gw, if_info->ip_addr.ip_type)) {681		rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL,682				       if_info->ip_addr.ip_type, gw);683		if (rc) {684			beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,685				    "BG_%d : Failed to clear Gateway Addr Set\n");686			goto exit;687		}688	}689 690	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,691			OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,692			sizeof(*dhcpreq));693	if (rc)694		goto exit;695 696	dhcpreq = nonemb_cmd.va;697	dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */698	dhcpreq->retry_count = 1;699	dhcpreq->interface_hndl = phba->interface_handle;700	dhcpreq->ip_type = ip_type;701	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0);702	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);703exit:704	kfree(if_info);705	return rc;706}707 708/**709 * beiscsi_if_set_vlan()- Issue and wait for CMD completion710 * @phba: device private structure instance711 * @vlan_tag: VLAN tag712 *713 * Issue the MBX Cmd and wait for the completion of the714 * command.715 *716 * returns717 *	Success: 0718 *	Failure: Non-Xero Value719 **/720int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag)721{722	int rc;723	unsigned int tag;724 725	tag = be_cmd_set_vlan(phba, vlan_tag);726	if (!tag) {727		beiscsi_log(phba, KERN_ERR,728			    (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),729			    "BG_%d : VLAN Setting Failed\n");730		return -EBUSY;731	}732 733	rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);734	if (rc) {735		beiscsi_log(phba, KERN_ERR,736			    (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),737			    "BS_%d : VLAN MBX Cmd Failed\n");738		return rc;739	}740	return rc;741}742 743 744int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,745			struct be_cmd_get_if_info_resp **if_info)746{747	struct be_cmd_get_if_info_req *req;748	struct be_dma_mem nonemb_cmd;749	uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp);750	int rc;751 752	rc = beiscsi_if_get_handle(phba);753	if (rc)754		return rc;755 756	do {757		rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd,758				CMD_SUBSYSTEM_ISCSI,759				OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,760				ioctl_size);761		if (rc)762			return rc;763 764		req = nonemb_cmd.va;765		req->interface_hndl = phba->interface_handle;766		req->ip_type = ip_type;767 768		/* Allocate memory for if_info */769		*if_info = kzalloc(ioctl_size, GFP_KERNEL);770		if (!*if_info) {771			beiscsi_log(phba, KERN_ERR,772				    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,773				    "BG_%d : Memory Allocation Failure\n");774 775				beiscsi_free_nemb_cmd(phba, &nonemb_cmd,776						      -ENOMEM);777				return -ENOMEM;778		}779 780		rc =  beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, *if_info,781					    ioctl_size);782 783		/* Check if the error is because of Insufficent_Buffer */784		if (rc == -EAGAIN) {785 786			/* Get the new memory size */787			ioctl_size = ((struct be_cmd_resp_hdr *)788				      nonemb_cmd.va)->actual_resp_len;789			ioctl_size += sizeof(struct be_cmd_req_hdr);790 791			beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);792			/* Free the virtual memory */793			kfree(*if_info);794		} else {795			beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);796			break;797		}798	} while (true);799	return rc;800}801 802int mgmt_get_nic_conf(struct beiscsi_hba *phba,803		      struct be_cmd_get_nic_conf_resp *nic)804{805	struct be_dma_mem nonemb_cmd;806	int rc;807 808	rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI,809			OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,810			sizeof(*nic));811	if (rc)812		return rc;813 814	rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, nic, sizeof(*nic));815	beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc);816	return rc;817}818 819static void beiscsi_boot_process_compl(struct beiscsi_hba *phba,820				       unsigned int tag)821{822	struct be_cmd_get_boot_target_resp *boot_resp;823	struct be_cmd_resp_logout_fw_sess *logo_resp;824	struct be_cmd_get_session_resp *sess_resp;825	struct be_mcc_wrb *wrb;826	struct boot_struct *bs;827	int boot_work, status;828 829	if (!test_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) {830		__beiscsi_log(phba, KERN_ERR,831			      "BG_%d : %s no boot work %lx\n",832			      __func__, phba->state);833		return;834	}835 836	if (phba->boot_struct.tag != tag) {837		__beiscsi_log(phba, KERN_ERR,838			      "BG_%d : %s tag mismatch %d:%d\n",839			      __func__, tag, phba->boot_struct.tag);840		return;841	}842	bs = &phba->boot_struct;843	boot_work = 1;844	status = 0;845	switch (bs->action) {846	case BEISCSI_BOOT_REOPEN_SESS:847		status = __beiscsi_mcc_compl_status(phba, tag, NULL, NULL);848		if (!status)849			bs->action = BEISCSI_BOOT_GET_SHANDLE;850		else851			bs->retry--;852		break;853	case BEISCSI_BOOT_GET_SHANDLE:854		status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL);855		if (!status) {856			boot_resp = embedded_payload(wrb);857			bs->s_handle = boot_resp->boot_session_handle;858		}859		if (bs->s_handle == BE_BOOT_INVALID_SHANDLE) {860			bs->action = BEISCSI_BOOT_REOPEN_SESS;861			bs->retry--;862		} else {863			bs->action = BEISCSI_BOOT_GET_SINFO;864		}865		break;866	case BEISCSI_BOOT_GET_SINFO:867		status = __beiscsi_mcc_compl_status(phba, tag, NULL,868						    &bs->nonemb_cmd);869		if (!status) {870			sess_resp = bs->nonemb_cmd.va;871			memcpy(&bs->boot_sess, &sess_resp->session_info,872			       sizeof(struct mgmt_session_info));873			bs->action = BEISCSI_BOOT_LOGOUT_SESS;874		} else {875			__beiscsi_log(phba, KERN_ERR,876				      "BG_%d : get boot session info error : 0x%x\n",877				      status);878			boot_work = 0;879		}880		dma_free_coherent(&phba->ctrl.pdev->dev, bs->nonemb_cmd.size,881				    bs->nonemb_cmd.va, bs->nonemb_cmd.dma);882		bs->nonemb_cmd.va = NULL;883		break;884	case BEISCSI_BOOT_LOGOUT_SESS:885		status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL);886		if (!status) {887			logo_resp = embedded_payload(wrb);888			if (logo_resp->session_status != BE_SESS_STATUS_CLOSE) {889				__beiscsi_log(phba, KERN_ERR,890					      "BG_%d : FW boot session logout error : 0x%x\n",891					      logo_resp->session_status);892			}893		}894		/* continue to create boot_kset even if logout failed? */895		bs->action = BEISCSI_BOOT_CREATE_KSET;896		break;897	default:898		break;899	}900 901	/* clear the tag so no other completion matches this tag */902	bs->tag = 0;903	if (!bs->retry) {904		boot_work = 0;905		__beiscsi_log(phba, KERN_ERR,906			      "BG_%d : failed to setup boot target: status %d action %d\n",907			      status, bs->action);908	}909	if (!boot_work) {910		/* wait for next event to start boot_work */911		clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state);912		return;913	}914	schedule_work(&phba->boot_work);915}916 917/**918 * beiscsi_boot_logout_sess()- Logout from boot FW session919 * @phba: Device priv structure instance920 *921 * return922 *	the TAG used for MBOX Command923 *924 */925unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba)926{927	struct be_ctrl_info *ctrl = &phba->ctrl;928	struct be_mcc_wrb *wrb;929	struct be_cmd_req_logout_fw_sess *req;930	unsigned int tag;931 932	mutex_lock(&ctrl->mbox_lock);933	wrb = alloc_mcc_wrb(phba, &tag);934	if (!wrb) {935		mutex_unlock(&ctrl->mbox_lock);936		return 0;937	}938 939	req = embedded_payload(wrb);940	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);941	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,942			   OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET,943			   sizeof(struct be_cmd_req_logout_fw_sess));944	/* Use the session handle copied into boot_sess */945	req->session_handle = phba->boot_struct.boot_sess.session_handle;946 947	phba->boot_struct.tag = tag;948	set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);949	ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;950 951	be_mcc_notify(phba, tag);952	mutex_unlock(&ctrl->mbox_lock);953 954	return tag;955}956/**957 * beiscsi_boot_reopen_sess()- Reopen boot session958 * @phba: Device priv structure instance959 *960 * return961 *	the TAG used for MBOX Command962 *963 **/964unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba)965{966	struct be_ctrl_info *ctrl = &phba->ctrl;967	struct be_mcc_wrb *wrb;968	struct be_cmd_reopen_session_req *req;969	unsigned int tag;970 971	mutex_lock(&ctrl->mbox_lock);972	wrb = alloc_mcc_wrb(phba, &tag);973	if (!wrb) {974		mutex_unlock(&ctrl->mbox_lock);975		return 0;976	}977 978	req = embedded_payload(wrb);979	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);980	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,981			   OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS,982			   sizeof(struct be_cmd_reopen_session_resp));983	req->reopen_type = BE_REOPEN_BOOT_SESSIONS;984	req->session_handle = BE_BOOT_INVALID_SHANDLE;985 986	phba->boot_struct.tag = tag;987	set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);988	ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;989 990	be_mcc_notify(phba, tag);991	mutex_unlock(&ctrl->mbox_lock);992	return tag;993}994 995 996/**997 * beiscsi_boot_get_sinfo()- Get boot session info998 * @phba: device priv structure instance999 *1000 * Fetches the boot_struct.s_handle info from FW.1001 * return1002 *	the TAG used for MBOX Command1003 *1004 **/1005unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba)1006{1007	struct be_ctrl_info *ctrl = &phba->ctrl;1008	struct be_cmd_get_session_req *req;1009	struct be_dma_mem *nonemb_cmd;1010	struct be_mcc_wrb *wrb;1011	struct be_sge *sge;1012	unsigned int tag;1013 1014	mutex_lock(&ctrl->mbox_lock);1015	wrb = alloc_mcc_wrb(phba, &tag);1016	if (!wrb) {1017		mutex_unlock(&ctrl->mbox_lock);1018		return 0;1019	}1020 1021	nonemb_cmd = &phba->boot_struct.nonemb_cmd;1022	nonemb_cmd->size = sizeof(struct be_cmd_get_session_resp);1023	nonemb_cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev,1024					      nonemb_cmd->size,1025					      &nonemb_cmd->dma,1026					      GFP_KERNEL);1027	if (!nonemb_cmd->va) {1028		mutex_unlock(&ctrl->mbox_lock);1029		return 0;1030	}1031 1032	req = nonemb_cmd->va;1033	memset(req, 0, sizeof(*req));1034	sge = nonembedded_sgl(wrb);1035	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);1036	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,1037			   OPCODE_ISCSI_INI_SESSION_GET_A_SESSION,1038			   sizeof(struct be_cmd_get_session_resp));1039	req->session_handle = phba->boot_struct.s_handle;1040	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));1041	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);1042	sge->len = cpu_to_le32(nonemb_cmd->size);1043 1044	phba->boot_struct.tag = tag;1045	set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);1046	ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;1047 1048	be_mcc_notify(phba, tag);1049	mutex_unlock(&ctrl->mbox_lock);1050	return tag;1051}1052 1053unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async)1054{1055	struct be_ctrl_info *ctrl = &phba->ctrl;1056	struct be_mcc_wrb *wrb;1057	struct be_cmd_get_boot_target_req *req;1058	unsigned int tag;1059 1060	mutex_lock(&ctrl->mbox_lock);1061	wrb = alloc_mcc_wrb(phba, &tag);1062	if (!wrb) {1063		mutex_unlock(&ctrl->mbox_lock);1064		return 0;1065	}1066 1067	req = embedded_payload(wrb);1068	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);1069	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,1070			   OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET,1071			   sizeof(struct be_cmd_get_boot_target_resp));1072 1073	if (async) {1074		phba->boot_struct.tag = tag;1075		set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state);1076		ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl;1077	}1078 1079	be_mcc_notify(phba, tag);1080	mutex_unlock(&ctrl->mbox_lock);1081	return tag;1082}1083 1084/**1085 * beiscsi_boot_get_shandle()- Get boot session handle1086 * @phba: device priv structure instance1087 * @s_handle: session handle returned for boot session.1088 *1089 * return1090 *	Success: 11091 *	Failure: negative1092 *1093 **/1094int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle)1095{1096	struct be_cmd_get_boot_target_resp *boot_resp;1097	struct be_mcc_wrb *wrb;1098	unsigned int tag;1099	int rc;1100 1101	*s_handle = BE_BOOT_INVALID_SHANDLE;1102	/* get configured boot session count and handle */1103	tag = __beiscsi_boot_get_shandle(phba, 0);1104	if (!tag) {1105		beiscsi_log(phba, KERN_ERR,1106			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,1107			    "BG_%d : Getting Boot Target Info Failed\n");1108		return -EAGAIN;1109	}1110 1111	rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);1112	if (rc) {1113		beiscsi_log(phba, KERN_ERR,1114			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,1115			    "BG_%d : MBX CMD get_boot_target Failed\n");1116		return -EBUSY;1117	}1118 1119	boot_resp = embedded_payload(wrb);1120	/* check if there are any boot targets configured */1121	if (!boot_resp->boot_session_count) {1122		__beiscsi_log(phba, KERN_INFO,1123			      "BG_%d : No boot targets configured\n");1124		return -ENXIO;1125	}1126 1127	/* only if FW has logged in to the boot target, s_handle is valid */1128	*s_handle = boot_resp->boot_session_handle;1129	return 1;1130}1131 1132/**1133 * beiscsi_drvr_ver_disp()- Display the driver Name and Version1134 * @dev: ptr to device not used.1135 * @attr: device attribute, not used.1136 * @buf: contains formatted text driver name and version1137 *1138 * return1139 * size of the formatted string1140 **/1141ssize_t1142beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr,1143		       char *buf)1144{1145	return snprintf(buf, PAGE_SIZE, BE_NAME "\n");1146}1147 1148/**1149 * beiscsi_fw_ver_disp()- Display Firmware Version1150 * @dev: ptr to device not used.1151 * @attr: device attribute, not used.1152 * @buf: contains formatted text Firmware version1153 *1154 * return1155 * size of the formatted string1156 **/1157ssize_t1158beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr,1159		     char *buf)1160{1161	struct Scsi_Host *shost = class_to_shost(dev);1162	struct beiscsi_hba *phba = iscsi_host_priv(shost);1163 1164	return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str);1165}1166 1167/**1168 * beiscsi_active_session_disp()- Display Sessions Active1169 * @dev: ptr to device not used.1170 * @attr: device attribute, not used.1171 * @buf: contains formatted text Session Count1172 *1173 * return1174 * size of the formatted string1175 **/1176ssize_t1177beiscsi_active_session_disp(struct device *dev, struct device_attribute *attr,1178			 char *buf)1179{1180	struct Scsi_Host *shost = class_to_shost(dev);1181	struct beiscsi_hba *phba = iscsi_host_priv(shost);1182	uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0;1183 1184	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {1185		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) {1186			avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num);1187			total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num);1188			len += scnprintf(buf+len, PAGE_SIZE - len,1189					 "ULP%d : %d\n", ulp_num,1190					 (total_cids - avlbl_cids));1191		} else1192			len += scnprintf(buf+len, PAGE_SIZE - len,1193					 "ULP%d : %d\n", ulp_num, 0);1194	}1195 1196	return len;1197}1198 1199/**1200 * beiscsi_free_session_disp()- Display Avaliable Session1201 * @dev: ptr to device not used.1202 * @attr: device attribute, not used.1203 * @buf: contains formatted text Session Count1204 *1205 * return1206 * size of the formatted string1207 **/1208ssize_t1209beiscsi_free_session_disp(struct device *dev, struct device_attribute *attr,1210		       char *buf)1211{1212	struct Scsi_Host *shost = class_to_shost(dev);1213	struct beiscsi_hba *phba = iscsi_host_priv(shost);1214	uint16_t ulp_num, len = 0;1215 1216	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {1217		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported))1218			len += scnprintf(buf+len, PAGE_SIZE - len,1219					 "ULP%d : %d\n", ulp_num,1220					 BEISCSI_ULP_AVLBL_CID(phba, ulp_num));1221		else1222			len += scnprintf(buf+len, PAGE_SIZE - len,1223					 "ULP%d : %d\n", ulp_num, 0);1224	}1225 1226	return len;1227}1228 1229/**1230 * beiscsi_adap_family_disp()- Display adapter family.1231 * @dev: ptr to device to get priv structure1232 * @attr: device attribute, not used.1233 * @buf: contains formatted text driver name and version1234 *1235 * return1236 * size of the formatted string1237 **/1238ssize_t1239beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,1240			  char *buf)1241{1242	uint16_t dev_id = 0;1243	struct Scsi_Host *shost = class_to_shost(dev);1244	struct beiscsi_hba *phba = iscsi_host_priv(shost);1245 1246	dev_id = phba->pcidev->device;1247	switch (dev_id) {1248	case BE_DEVICE_ID1:1249	case OC_DEVICE_ID1:1250	case OC_DEVICE_ID2:1251		return snprintf(buf, PAGE_SIZE,1252				"Obsolete/Unsupported BE2 Adapter Family\n");1253	case BE_DEVICE_ID2:1254	case OC_DEVICE_ID3:1255		return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n");1256	case OC_SKH_ID1:1257		return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n");1258	default:1259		return snprintf(buf, PAGE_SIZE,1260				"Unknown Adapter Family: 0x%x\n", dev_id);1261	}1262}1263 1264/**1265 * beiscsi_phys_port_disp()- Display Physical Port Identifier1266 * @dev: ptr to device not used.1267 * @attr: device attribute, not used.1268 * @buf: contains formatted text port identifier1269 *1270 * return1271 * size of the formatted string1272 **/1273ssize_t1274beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,1275			 char *buf)1276{1277	struct Scsi_Host *shost = class_to_shost(dev);1278	struct beiscsi_hba *phba = iscsi_host_priv(shost);1279 1280	return snprintf(buf, PAGE_SIZE, "Port Identifier : %u\n",1281			phba->fw_config.phys_port);1282}1283 1284void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,1285			     struct wrb_handle *pwrb_handle,1286			     struct be_mem_descriptor *mem_descr,1287			     struct hwi_wrb_context *pwrb_context)1288{1289	struct iscsi_wrb *pwrb = pwrb_handle->pwrb;1290 1291	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1292		      max_send_data_segment_length, pwrb,1293		      params->dw[offsetof(struct amap_beiscsi_offload_params,1294		      max_send_data_segment_length) / 32]);1295	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,1296		      BE_TGT_CTX_UPDT_CMD);1297	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1298		      first_burst_length,1299		      pwrb,1300		      params->dw[offsetof(struct amap_beiscsi_offload_params,1301		      first_burst_length) / 32]);1302	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,1303		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1304		      erl) / 32] & OFFLD_PARAMS_ERL));1305	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,1306		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1307		       dde) / 32] & OFFLD_PARAMS_DDE) >> 2);1308	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,1309		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1310		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);1311	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,1312		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1313		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);1314	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,1315		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1316		      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);1317	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,1318		      pwrb,1319		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1320		      exp_statsn) / 32] + 1));1321	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,1322		      pwrb, pwrb_handle->wrb_index);1323 1324	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1325		      max_burst_length, pwrb, params->dw[offsetof1326		      (struct amap_beiscsi_offload_params,1327		      max_burst_length) / 32]);1328 1329	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,1330		      pwrb, pwrb_handle->wrb_index);1331	if (pwrb_context->plast_wrb)1332		AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1333			      ptr2nextwrb,1334			      pwrb_context->plast_wrb,1335			      pwrb_handle->wrb_index);1336	pwrb_context->plast_wrb = pwrb;1337 1338	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1339		      session_state, pwrb, 0);1340	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,1341		      pwrb, 1);1342	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,1343		      pwrb, 0);1344	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,1345		      0);1346 1347	mem_descr += ISCSI_MEM_GLOBAL_HEADER;1348	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1349		      pad_buffer_addr_hi, pwrb,1350		      mem_descr->mem_array[0].bus_address.u.a32.address_hi);1351	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,1352		      pad_buffer_addr_lo, pwrb,1353		      mem_descr->mem_array[0].bus_address.u.a32.address_lo);1354}1355 1356void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,1357			     struct wrb_handle *pwrb_handle,1358			     struct hwi_wrb_context *pwrb_context)1359{1360	struct iscsi_wrb *pwrb = pwrb_handle->pwrb;1361 1362	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1363		      max_burst_length, pwrb, params->dw[offsetof1364		      (struct amap_beiscsi_offload_params,1365		      max_burst_length) / 32]);1366	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1367		      type, pwrb,1368		      BE_TGT_CTX_UPDT_CMD);1369	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1370		      ptr2nextwrb,1371		      pwrb, pwrb_handle->wrb_index);1372	if (pwrb_context->plast_wrb)1373		AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1374			      ptr2nextwrb,1375			      pwrb_context->plast_wrb,1376			      pwrb_handle->wrb_index);1377	pwrb_context->plast_wrb = pwrb;1378 1379	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,1380		      pwrb, pwrb_handle->wrb_index);1381	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1382		      max_send_data_segment_length, pwrb,1383		      params->dw[offsetof(struct amap_beiscsi_offload_params,1384		      max_send_data_segment_length) / 32]);1385	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1386		      first_burst_length, pwrb,1387		      params->dw[offsetof(struct amap_beiscsi_offload_params,1388		      first_burst_length) / 32]);1389	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1390		      max_recv_dataseg_len, pwrb,1391		      params->dw[offsetof(struct amap_beiscsi_offload_params,1392		      max_recv_data_segment_length) / 32]);1393	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1394		      max_cxns, pwrb, BEISCSI_MAX_CXNS);1395	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb,1396		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1397		      erl) / 32] & OFFLD_PARAMS_ERL));1398	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb,1399		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1400		      dde) / 32] & OFFLD_PARAMS_DDE) >> 2);1401	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb,1402		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1403		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);1404	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1405		      ir2t, pwrb,1406		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1407		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);1408	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb,1409		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1410		      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);1411	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1412		      data_seq_inorder,1413		      pwrb,1414		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1415		      data_seq_inorder) / 32] &1416		      OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6);1417	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,1418		      pdu_seq_inorder,1419		      pwrb,1420		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1421		      pdu_seq_inorder) / 32] &1422		      OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7);1423	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t,1424		      pwrb,1425		      (params->dw[offsetof(struct amap_beiscsi_offload_params,1426		      max_r2t) / 32] &1427		      OFFLD_PARAMS_MAX_R2T) >> 8);1428	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn,1429		      pwrb,1430		     (params->dw[offsetof(struct amap_beiscsi_offload_params,1431		      exp_statsn) / 32] + 1));1432}1433 1434unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba,1435				    struct beiscsi_endpoint *beiscsi_ep)1436{1437	struct be_invalidate_connection_params_in *req;1438	struct be_ctrl_info *ctrl = &phba->ctrl;1439	struct be_mcc_wrb *wrb;1440	unsigned int tag = 0;1441 1442	mutex_lock(&ctrl->mbox_lock);1443	wrb = alloc_mcc_wrb(phba, &tag);1444	if (!wrb) {1445		mutex_unlock(&ctrl->mbox_lock);1446		return 0;1447	}1448 1449	req = embedded_payload(wrb);1450	be_wrb_hdr_prepare(wrb, sizeof(union be_invalidate_connection_params),1451			   true, 0);1452	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,1453			   OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,1454			   sizeof(*req));1455	req->session_handle = beiscsi_ep->fw_handle;1456	req->cid = beiscsi_ep->ep_cid;1457	if (beiscsi_ep->conn)1458		req->cleanup_type = BE_CLEANUP_TYPE_INVALIDATE;1459	else1460		req->cleanup_type = BE_CLEANUP_TYPE_ISSUE_TCP_RST;1461	/**1462	 * 0 - non-persistent targets1463	 * 1 - save session info on flash1464	 */1465	req->save_cfg = 0;1466	be_mcc_notify(phba, tag);1467	mutex_unlock(&ctrl->mbox_lock);1468	return tag;1469}1470 1471unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba,1472				struct beiscsi_endpoint *beiscsi_ep)1473{1474	struct be_ctrl_info *ctrl = &phba->ctrl;1475	struct be_mcc_wrb *wrb;1476	struct be_tcp_upload_params_in *req;1477	unsigned int tag;1478 1479	mutex_lock(&ctrl->mbox_lock);1480	wrb = alloc_mcc_wrb(phba, &tag);1481	if (!wrb) {1482		mutex_unlock(&ctrl->mbox_lock);1483		return 0;1484	}1485 1486	req = embedded_payload(wrb);1487	be_wrb_hdr_prepare(wrb, sizeof(union be_tcp_upload_params), true, 0);1488	be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,1489			   OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));1490	req->id = beiscsi_ep->ep_cid;1491	if (beiscsi_ep->conn)1492		req->upload_type = BE_UPLOAD_TYPE_GRACEFUL;1493	else1494		req->upload_type = BE_UPLOAD_TYPE_ABORT;1495	be_mcc_notify(phba, tag);1496	mutex_unlock(&ctrl->mbox_lock);1497	return tag;1498}1499 1500int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,1501				 struct invldt_cmd_tbl *inv_tbl,1502				 unsigned int nents)1503{1504	struct be_ctrl_info *ctrl = &phba->ctrl;1505	struct invldt_cmds_params_in *req;1506	struct be_dma_mem nonemb_cmd;1507	struct be_mcc_wrb *wrb;1508	unsigned int i, tag;1509	struct be_sge *sge;1510	int rc;1511 1512	if (!nents || nents > BE_INVLDT_CMD_TBL_SZ)1513		return -EINVAL;1514 1515	nonemb_cmd.size = sizeof(union be_invldt_cmds_params);1516	nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,1517					   nonemb_cmd.size, &nonemb_cmd.dma,1518					   GFP_KERNEL);1519	if (!nonemb_cmd.va) {1520		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,1521			    "BM_%d : invldt_cmds_params alloc failed\n");1522		return -ENOMEM;1523	}1524 1525	mutex_lock(&ctrl->mbox_lock);1526	wrb = alloc_mcc_wrb(phba, &tag);1527	if (!wrb) {1528		mutex_unlock(&ctrl->mbox_lock);1529		dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,1530				    nonemb_cmd.va, nonemb_cmd.dma);1531		return -ENOMEM;1532	}1533 1534	req = nonemb_cmd.va;1535	be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false, 1);1536	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,1537			OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,1538			sizeof(*req));1539	req->ref_handle = 0;1540	req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;1541	for (i = 0; i < nents; i++) {1542		req->table[i].icd = inv_tbl[i].icd;1543		req->table[i].cid = inv_tbl[i].cid;1544		req->icd_count++;1545	}1546	sge = nonembedded_sgl(wrb);1547	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));1548	sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd.dma));1549	sge->len = cpu_to_le32(nonemb_cmd.size);1550 1551	be_mcc_notify(phba, tag);1552	mutex_unlock(&ctrl->mbox_lock);1553 1554	rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);1555	if (rc != -EBUSY)1556		dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,1557				    nonemb_cmd.va, nonemb_cmd.dma);1558	return rc;1559}1560