162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for Enterprise iSCSI 362306a36Sopenharmony_ci * Host Bus Adapters. Refer to the README file included with this package 462306a36Sopenharmony_ci * for driver version and adapter compatibility. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2018 Broadcom. All Rights Reserved. 762306a36Sopenharmony_ci * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it 1062306a36Sopenharmony_ci * under the terms of version 2 of the GNU General Public License as published 1162306a36Sopenharmony_ci * by the Free Software Foundation. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful. ALL EXPRESS 1462306a36Sopenharmony_ci * OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY 1562306a36Sopenharmony_ci * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, 1662306a36Sopenharmony_ci * OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH 1762306a36Sopenharmony_ci * DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 1862306a36Sopenharmony_ci * See the GNU General Public License for more details, a copy of which 1962306a36Sopenharmony_ci * can be found in the file COPYING included with this package. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Contact Information: 2262306a36Sopenharmony_ci * linux-drivers@broadcom.com 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/bsg-lib.h> 2762306a36Sopenharmony_ci#include <scsi/scsi_transport_iscsi.h> 2862306a36Sopenharmony_ci#include <scsi/scsi_bsg_iscsi.h> 2962306a36Sopenharmony_ci#include "be_mgmt.h" 3062306a36Sopenharmony_ci#include "be_iscsi.h" 3162306a36Sopenharmony_ci#include "be_main.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciunsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, 3462306a36Sopenharmony_ci struct beiscsi_hba *phba, 3562306a36Sopenharmony_ci struct bsg_job *job, 3662306a36Sopenharmony_ci struct be_dma_mem *nonemb_cmd) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 3962306a36Sopenharmony_ci struct be_sge *mcc_sge; 4062306a36Sopenharmony_ci unsigned int tag = 0; 4162306a36Sopenharmony_ci struct iscsi_bsg_request *bsg_req = job->request; 4262306a36Sopenharmony_ci struct be_bsg_vendor_cmd *req = nonemb_cmd->va; 4362306a36Sopenharmony_ci unsigned short region, sector_size, sector, offset; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci nonemb_cmd->size = job->request_payload.payload_len; 4662306a36Sopenharmony_ci memset(nonemb_cmd->va, 0, nonemb_cmd->size); 4762306a36Sopenharmony_ci region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; 4862306a36Sopenharmony_ci sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; 4962306a36Sopenharmony_ci sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; 5062306a36Sopenharmony_ci offset = bsg_req->rqst_data.h_vendor.vendor_cmd[4]; 5162306a36Sopenharmony_ci req->region = region; 5262306a36Sopenharmony_ci req->sector = sector; 5362306a36Sopenharmony_ci req->offset = offset; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (mutex_lock_interruptible(&ctrl->mbox_lock)) 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) { 5862306a36Sopenharmony_ci case BEISCSI_WRITE_FLASH: 5962306a36Sopenharmony_ci offset = sector * sector_size + offset; 6062306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 6162306a36Sopenharmony_ci OPCODE_COMMON_WRITE_FLASH, sizeof(*req)); 6262306a36Sopenharmony_ci sg_copy_to_buffer(job->request_payload.sg_list, 6362306a36Sopenharmony_ci job->request_payload.sg_cnt, 6462306a36Sopenharmony_ci nonemb_cmd->va + offset, job->request_len); 6562306a36Sopenharmony_ci break; 6662306a36Sopenharmony_ci case BEISCSI_READ_FLASH: 6762306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 6862306a36Sopenharmony_ci OPCODE_COMMON_READ_FLASH, sizeof(*req)); 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci default: 7162306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 7262306a36Sopenharmony_ci "BG_%d : Unsupported cmd = 0x%x\n\n", 7362306a36Sopenharmony_ci bsg_req->rqst_data.h_vendor.vendor_cmd[0]); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 7662306a36Sopenharmony_ci return -EPERM; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 8062306a36Sopenharmony_ci if (!wrb) { 8162306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 8262306a36Sopenharmony_ci return 0; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci mcc_sge = nonembedded_sgl(wrb); 8662306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 8762306a36Sopenharmony_ci job->request_payload.sg_cnt); 8862306a36Sopenharmony_ci mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 8962306a36Sopenharmony_ci mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 9062306a36Sopenharmony_ci mcc_sge->len = cpu_to_le32(nonemb_cmd->size); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci be_mcc_notify(phba, tag); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 9562306a36Sopenharmony_ci return tag; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/** 9962306a36Sopenharmony_ci * mgmt_open_connection()- Establish a TCP CXN 10062306a36Sopenharmony_ci * @phba: driver priv structure 10162306a36Sopenharmony_ci * @dst_addr: Destination Address 10262306a36Sopenharmony_ci * @beiscsi_ep: ptr to device endpoint struct 10362306a36Sopenharmony_ci * @nonemb_cmd: ptr to memory allocated for command 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * return 10662306a36Sopenharmony_ci * Success: Tag number of the MBX Command issued 10762306a36Sopenharmony_ci * Failure: Error code 10862306a36Sopenharmony_ci **/ 10962306a36Sopenharmony_ciint mgmt_open_connection(struct beiscsi_hba *phba, 11062306a36Sopenharmony_ci struct sockaddr *dst_addr, 11162306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep, 11262306a36Sopenharmony_ci struct be_dma_mem *nonemb_cmd) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct hwi_controller *phwi_ctrlr; 11562306a36Sopenharmony_ci struct hwi_context_memory *phwi_context; 11662306a36Sopenharmony_ci struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; 11762306a36Sopenharmony_ci struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; 11862306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 11962306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 12062306a36Sopenharmony_ci struct tcp_connect_and_offload_in_v1 *req; 12162306a36Sopenharmony_ci unsigned short def_hdr_id; 12262306a36Sopenharmony_ci unsigned short def_data_id; 12362306a36Sopenharmony_ci struct phys_addr template_address = { 0, 0 }; 12462306a36Sopenharmony_ci struct phys_addr *ptemplate_address; 12562306a36Sopenharmony_ci unsigned int tag = 0; 12662306a36Sopenharmony_ci unsigned int i, ulp_num; 12762306a36Sopenharmony_ci unsigned short cid = beiscsi_ep->ep_cid; 12862306a36Sopenharmony_ci struct be_sge *sge; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) { 13162306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 13262306a36Sopenharmony_ci "BG_%d : unknown addr family %d\n", 13362306a36Sopenharmony_ci dst_addr->sa_family); 13462306a36Sopenharmony_ci return 0; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci phwi_ctrlr = phba->phwi_ctrlr; 13862306a36Sopenharmony_ci phwi_context = phwi_ctrlr->phwi_ctxt; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci ulp_num = phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(cid)].ulp_num; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba, ulp_num); 14362306a36Sopenharmony_ci def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba, ulp_num); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci ptemplate_address = &template_address; 14662306a36Sopenharmony_ci ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); 14762306a36Sopenharmony_ci if (mutex_lock_interruptible(&ctrl->mbox_lock)) 14862306a36Sopenharmony_ci return 0; 14962306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 15062306a36Sopenharmony_ci if (!wrb) { 15162306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci sge = nonembedded_sgl(wrb); 15662306a36Sopenharmony_ci req = nonemb_cmd->va; 15762306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1); 16062306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 16162306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, 16262306a36Sopenharmony_ci nonemb_cmd->size); 16362306a36Sopenharmony_ci if (dst_addr->sa_family == PF_INET) { 16462306a36Sopenharmony_ci __be32 s_addr = daddr_in->sin_addr.s_addr; 16562306a36Sopenharmony_ci req->ip_address.ip_type = BEISCSI_IP_TYPE_V4; 16662306a36Sopenharmony_ci req->ip_address.addr[0] = s_addr & 0x000000ff; 16762306a36Sopenharmony_ci req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; 16862306a36Sopenharmony_ci req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16; 16962306a36Sopenharmony_ci req->ip_address.addr[3] = (s_addr & 0xff000000) >> 24; 17062306a36Sopenharmony_ci req->tcp_port = ntohs(daddr_in->sin_port); 17162306a36Sopenharmony_ci beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; 17262306a36Sopenharmony_ci beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); 17362306a36Sopenharmony_ci beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V4; 17462306a36Sopenharmony_ci } else { 17562306a36Sopenharmony_ci /* else its PF_INET6 family */ 17662306a36Sopenharmony_ci req->ip_address.ip_type = BEISCSI_IP_TYPE_V6; 17762306a36Sopenharmony_ci memcpy(&req->ip_address.addr, 17862306a36Sopenharmony_ci &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 17962306a36Sopenharmony_ci req->tcp_port = ntohs(daddr_in6->sin6_port); 18062306a36Sopenharmony_ci beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); 18162306a36Sopenharmony_ci memcpy(&beiscsi_ep->dst6_addr, 18262306a36Sopenharmony_ci &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); 18362306a36Sopenharmony_ci beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V6; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci req->cid = cid; 18662306a36Sopenharmony_ci i = phba->nxt_cqid++; 18762306a36Sopenharmony_ci if (phba->nxt_cqid == phba->num_cpus) 18862306a36Sopenharmony_ci phba->nxt_cqid = 0; 18962306a36Sopenharmony_ci req->cq_id = phwi_context->be_cq[i].id; 19062306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 19162306a36Sopenharmony_ci "BG_%d : i=%d cq_id=%d\n", i, req->cq_id); 19262306a36Sopenharmony_ci req->defq_id = def_hdr_id; 19362306a36Sopenharmony_ci req->hdr_ring_id = def_hdr_id; 19462306a36Sopenharmony_ci req->data_ring_id = def_data_id; 19562306a36Sopenharmony_ci req->do_offload = 1; 19662306a36Sopenharmony_ci req->dataout_template_pa.lo = ptemplate_address->lo; 19762306a36Sopenharmony_ci req->dataout_template_pa.hi = ptemplate_address->hi; 19862306a36Sopenharmony_ci sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 19962306a36Sopenharmony_ci sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 20062306a36Sopenharmony_ci sge->len = cpu_to_le32(nonemb_cmd->size); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci if (!is_chip_be2_be3r(phba)) { 20362306a36Sopenharmony_ci req->hdr.version = MBX_CMD_VER1; 20462306a36Sopenharmony_ci req->tcp_window_size = 0x8000; 20562306a36Sopenharmony_ci req->tcp_window_scale_count = 2; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci be_mcc_notify(phba, tag); 20962306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 21062306a36Sopenharmony_ci return tag; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/** 21462306a36Sopenharmony_ci * beiscsi_exec_nemb_cmd()- execute non-embedded MBX cmd 21562306a36Sopenharmony_ci * @phba: driver priv structure 21662306a36Sopenharmony_ci * @nonemb_cmd: DMA address of the MBX command to be issued 21762306a36Sopenharmony_ci * @cbfn: callback func on MCC completion 21862306a36Sopenharmony_ci * @resp_buf: buffer to copy the MBX cmd response 21962306a36Sopenharmony_ci * @resp_buf_len: response length to be copied 22062306a36Sopenharmony_ci * 22162306a36Sopenharmony_ci **/ 22262306a36Sopenharmony_cistatic int beiscsi_exec_nemb_cmd(struct beiscsi_hba *phba, 22362306a36Sopenharmony_ci struct be_dma_mem *nonemb_cmd, 22462306a36Sopenharmony_ci void (*cbfn)(struct beiscsi_hba *, 22562306a36Sopenharmony_ci unsigned int), 22662306a36Sopenharmony_ci void *resp_buf, u32 resp_buf_len) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 22962306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 23062306a36Sopenharmony_ci struct be_sge *sge; 23162306a36Sopenharmony_ci unsigned int tag; 23262306a36Sopenharmony_ci int rc = 0; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 23562306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 23662306a36Sopenharmony_ci if (!wrb) { 23762306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 23862306a36Sopenharmony_ci return -ENOMEM; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci sge = nonembedded_sgl(wrb); 24262306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1); 24362306a36Sopenharmony_ci sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 24462306a36Sopenharmony_ci sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma)); 24562306a36Sopenharmony_ci sge->len = cpu_to_le32(nonemb_cmd->size); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (cbfn) { 24862306a36Sopenharmony_ci struct be_dma_mem *tag_mem; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); 25162306a36Sopenharmony_ci ctrl->ptag_state[tag].cbfn = cbfn; 25262306a36Sopenharmony_ci tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* store DMA mem to be freed in callback */ 25562306a36Sopenharmony_ci tag_mem->size = nonemb_cmd->size; 25662306a36Sopenharmony_ci tag_mem->va = nonemb_cmd->va; 25762306a36Sopenharmony_ci tag_mem->dma = nonemb_cmd->dma; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci be_mcc_notify(phba, tag); 26062306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* with cbfn set, its async cmd, don't wait */ 26362306a36Sopenharmony_ci if (cbfn) 26462306a36Sopenharmony_ci return 0; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci rc = beiscsi_mccq_compl_wait(phba, tag, NULL, nonemb_cmd); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* copy the response, if any */ 26962306a36Sopenharmony_ci if (resp_buf) 27062306a36Sopenharmony_ci memcpy(resp_buf, nonemb_cmd->va, resp_buf_len); 27162306a36Sopenharmony_ci return rc; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba, 27562306a36Sopenharmony_ci struct be_dma_mem *cmd, 27662306a36Sopenharmony_ci u8 subsystem, u8 opcode, u32 size) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma, 27962306a36Sopenharmony_ci GFP_KERNEL); 28062306a36Sopenharmony_ci if (!cmd->va) { 28162306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 28262306a36Sopenharmony_ci "BG_%d : Failed to allocate memory for if info\n"); 28362306a36Sopenharmony_ci return -ENOMEM; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci cmd->size = size; 28662306a36Sopenharmony_ci be_cmd_hdr_prepare(cmd->va, subsystem, opcode, size); 28762306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 28862306a36Sopenharmony_ci "BG_%d : subsystem %u cmd %u size %u\n", 28962306a36Sopenharmony_ci subsystem, opcode, size); 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic void beiscsi_free_nemb_cmd(struct beiscsi_hba *phba, 29462306a36Sopenharmony_ci struct be_dma_mem *cmd, int rc) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci /* 29762306a36Sopenharmony_ci * If FW is busy the DMA buffer is saved with the tag. When the cmd 29862306a36Sopenharmony_ci * completes this buffer is freed. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci if (rc == -EBUSY) 30162306a36Sopenharmony_ci return; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, cmd->size, cmd->va, cmd->dma); 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic void __beiscsi_eq_delay_compl(struct beiscsi_hba *phba, unsigned int tag) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci struct be_dma_mem *tag_mem; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* status is ignored */ 31162306a36Sopenharmony_ci __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); 31262306a36Sopenharmony_ci tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; 31362306a36Sopenharmony_ci if (tag_mem->size) { 31462306a36Sopenharmony_ci dma_free_coherent(&phba->pcidev->dev, tag_mem->size, 31562306a36Sopenharmony_ci tag_mem->va, tag_mem->dma); 31662306a36Sopenharmony_ci tag_mem->size = 0; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ciint beiscsi_modify_eq_delay(struct beiscsi_hba *phba, 32162306a36Sopenharmony_ci struct be_set_eqd *set_eqd, int num) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct be_cmd_req_modify_eq_delay *req; 32462306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 32562306a36Sopenharmony_ci int i, rc; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_COMMON, 32862306a36Sopenharmony_ci OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); 32962306a36Sopenharmony_ci if (rc) 33062306a36Sopenharmony_ci return rc; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci req = nonemb_cmd.va; 33362306a36Sopenharmony_ci req->num_eq = cpu_to_le32(num); 33462306a36Sopenharmony_ci for (i = 0; i < num; i++) { 33562306a36Sopenharmony_ci req->delay[i].eq_id = cpu_to_le32(set_eqd[i].eq_id); 33662306a36Sopenharmony_ci req->delay[i].phase = 0; 33762306a36Sopenharmony_ci req->delay[i].delay_multiplier = 33862306a36Sopenharmony_ci cpu_to_le32(set_eqd[i].delay_multiplier); 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, __beiscsi_eq_delay_compl, 34262306a36Sopenharmony_ci NULL, 0); 34362306a36Sopenharmony_ci if (rc) { 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * Only free on failure. Async cmds are handled like -EBUSY 34662306a36Sopenharmony_ci * where it's handled for us. 34762306a36Sopenharmony_ci */ 34862306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci return rc; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/** 35462306a36Sopenharmony_ci * beiscsi_get_initiator_name - read initiator name from flash 35562306a36Sopenharmony_ci * @phba: device priv structure 35662306a36Sopenharmony_ci * @name: buffer pointer 35762306a36Sopenharmony_ci * @cfg: fetch user configured 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ciint beiscsi_get_initiator_name(struct beiscsi_hba *phba, char *name, bool cfg) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 36362306a36Sopenharmony_ci struct be_cmd_hba_name resp; 36462306a36Sopenharmony_ci struct be_cmd_hba_name *req; 36562306a36Sopenharmony_ci int rc; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI_INI, 36862306a36Sopenharmony_ci OPCODE_ISCSI_INI_CFG_GET_HBA_NAME, sizeof(resp)); 36962306a36Sopenharmony_ci if (rc) 37062306a36Sopenharmony_ci return rc; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci req = nonemb_cmd.va; 37362306a36Sopenharmony_ci if (cfg) 37462306a36Sopenharmony_ci req->hdr.version = 1; 37562306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, 37662306a36Sopenharmony_ci &resp, sizeof(resp)); 37762306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 37862306a36Sopenharmony_ci if (rc) { 37962306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 38062306a36Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 38162306a36Sopenharmony_ci "BS_%d : Initiator Name MBX Failed\n"); 38262306a36Sopenharmony_ci return rc; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci rc = sprintf(name, "%s\n", resp.initiator_name); 38562306a36Sopenharmony_ci return rc; 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ciunsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 39162306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 39262306a36Sopenharmony_ci struct be_cmd_get_all_if_id_req *req; 39362306a36Sopenharmony_ci struct be_cmd_get_all_if_id_req *pbe_allid; 39462306a36Sopenharmony_ci unsigned int tag; 39562306a36Sopenharmony_ci int status = 0; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (mutex_lock_interruptible(&ctrl->mbox_lock)) 39862306a36Sopenharmony_ci return -EINTR; 39962306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 40062306a36Sopenharmony_ci if (!wrb) { 40162306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 40262306a36Sopenharmony_ci return -ENOMEM; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci req = embedded_payload(wrb); 40662306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 40762306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 40862306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID, 40962306a36Sopenharmony_ci sizeof(*req)); 41062306a36Sopenharmony_ci be_mcc_notify(phba, tag); 41162306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); 41462306a36Sopenharmony_ci if (status) { 41562306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 41662306a36Sopenharmony_ci "BG_%d : %s failed: %d\n", __func__, status); 41762306a36Sopenharmony_ci return -EBUSY; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci pbe_allid = embedded_payload(wrb); 42162306a36Sopenharmony_ci /* we now support only one interface per function */ 42262306a36Sopenharmony_ci phba->interface_handle = pbe_allid->if_hndl_list[0]; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci return status; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci u32 len; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; 43262306a36Sopenharmony_ci while (len && !ip[len - 1]) 43362306a36Sopenharmony_ci len--; 43462306a36Sopenharmony_ci return (len == 0); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic int beiscsi_if_mod_gw(struct beiscsi_hba *phba, 43862306a36Sopenharmony_ci u32 action, u32 ip_type, u8 *gw) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct be_cmd_set_def_gateway_req *req; 44162306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 44262306a36Sopenharmony_ci int rt_val; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci rt_val = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI, 44562306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY, 44662306a36Sopenharmony_ci sizeof(*req)); 44762306a36Sopenharmony_ci if (rt_val) 44862306a36Sopenharmony_ci return rt_val; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci req = nonemb_cmd.va; 45162306a36Sopenharmony_ci req->action = action; 45262306a36Sopenharmony_ci req->ip_addr.ip_type = ip_type; 45362306a36Sopenharmony_ci memcpy(req->ip_addr.addr, gw, 45462306a36Sopenharmony_ci (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN); 45562306a36Sopenharmony_ci rt_val = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0); 45662306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rt_val); 45762306a36Sopenharmony_ci return rt_val; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ciint beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci struct be_cmd_get_def_gateway_resp gw_resp; 46362306a36Sopenharmony_ci int rt_val; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci memset(&gw_resp, 0, sizeof(gw_resp)); 46662306a36Sopenharmony_ci rt_val = beiscsi_if_get_gw(phba, ip_type, &gw_resp); 46762306a36Sopenharmony_ci if (rt_val) { 46862306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 46962306a36Sopenharmony_ci "BG_%d : Failed to Get Gateway Addr\n"); 47062306a36Sopenharmony_ci return rt_val; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci if (!beiscsi_if_zero_ip(gw_resp.ip_addr.addr, ip_type)) { 47462306a36Sopenharmony_ci rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type, 47562306a36Sopenharmony_ci gw_resp.ip_addr.addr); 47662306a36Sopenharmony_ci if (rt_val) { 47762306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 47862306a36Sopenharmony_ci "BG_%d : Failed to clear Gateway Addr Set\n"); 47962306a36Sopenharmony_ci return rt_val; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw); 48462306a36Sopenharmony_ci if (rt_val) 48562306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 48662306a36Sopenharmony_ci "BG_%d : Failed to Set Gateway Addr\n"); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci return rt_val; 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ciint beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type, 49262306a36Sopenharmony_ci struct be_cmd_get_def_gateway_resp *resp) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci struct be_cmd_get_def_gateway_req *req; 49562306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 49662306a36Sopenharmony_ci int rc; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI, 49962306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY, 50062306a36Sopenharmony_ci sizeof(*resp)); 50162306a36Sopenharmony_ci if (rc) 50262306a36Sopenharmony_ci return rc; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci req = nonemb_cmd.va; 50562306a36Sopenharmony_ci req->ip_type = ip_type; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, resp, 50862306a36Sopenharmony_ci sizeof(*resp)); 50962306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 51062306a36Sopenharmony_ci return rc; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic int 51462306a36Sopenharmony_cibeiscsi_if_clr_ip(struct beiscsi_hba *phba, 51562306a36Sopenharmony_ci struct be_cmd_get_if_info_resp *if_info) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct be_cmd_set_ip_addr_req *req; 51862306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 51962306a36Sopenharmony_ci int rc; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI, 52262306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, 52362306a36Sopenharmony_ci sizeof(*req)); 52462306a36Sopenharmony_ci if (rc) 52562306a36Sopenharmony_ci return rc; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci req = nonemb_cmd.va; 52862306a36Sopenharmony_ci req->ip_params.record_entry_count = 1; 52962306a36Sopenharmony_ci req->ip_params.ip_record.action = IP_ACTION_DEL; 53062306a36Sopenharmony_ci req->ip_params.ip_record.interface_hndl = 53162306a36Sopenharmony_ci phba->interface_handle; 53262306a36Sopenharmony_ci req->ip_params.ip_record.ip_addr.size_of_structure = 53362306a36Sopenharmony_ci sizeof(struct be_ip_addr_subnet_format); 53462306a36Sopenharmony_ci req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type; 53562306a36Sopenharmony_ci memcpy(req->ip_params.ip_record.ip_addr.addr, 53662306a36Sopenharmony_ci if_info->ip_addr.addr, 53762306a36Sopenharmony_ci sizeof(if_info->ip_addr.addr)); 53862306a36Sopenharmony_ci memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, 53962306a36Sopenharmony_ci if_info->ip_addr.subnet_mask, 54062306a36Sopenharmony_ci sizeof(if_info->ip_addr.subnet_mask)); 54162306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0); 54262306a36Sopenharmony_ci if (rc < 0 || req->ip_params.ip_record.status) { 54362306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 54462306a36Sopenharmony_ci "BG_%d : failed to clear IP: rc %d status %d\n", 54562306a36Sopenharmony_ci rc, req->ip_params.ip_record.status); 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 54862306a36Sopenharmony_ci return rc; 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic int 55262306a36Sopenharmony_cibeiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip, 55362306a36Sopenharmony_ci u8 *subnet, u32 ip_type) 55462306a36Sopenharmony_ci{ 55562306a36Sopenharmony_ci struct be_cmd_set_ip_addr_req *req; 55662306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 55762306a36Sopenharmony_ci uint32_t ip_len; 55862306a36Sopenharmony_ci int rc; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI, 56162306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, 56262306a36Sopenharmony_ci sizeof(*req)); 56362306a36Sopenharmony_ci if (rc) 56462306a36Sopenharmony_ci return rc; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci req = nonemb_cmd.va; 56762306a36Sopenharmony_ci req->ip_params.record_entry_count = 1; 56862306a36Sopenharmony_ci req->ip_params.ip_record.action = IP_ACTION_ADD; 56962306a36Sopenharmony_ci req->ip_params.ip_record.interface_hndl = 57062306a36Sopenharmony_ci phba->interface_handle; 57162306a36Sopenharmony_ci req->ip_params.ip_record.ip_addr.size_of_structure = 57262306a36Sopenharmony_ci sizeof(struct be_ip_addr_subnet_format); 57362306a36Sopenharmony_ci req->ip_params.ip_record.ip_addr.ip_type = ip_type; 57462306a36Sopenharmony_ci ip_len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; 57562306a36Sopenharmony_ci memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len); 57662306a36Sopenharmony_ci if (subnet) 57762306a36Sopenharmony_ci memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, 57862306a36Sopenharmony_ci subnet, ip_len); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0); 58162306a36Sopenharmony_ci /** 58262306a36Sopenharmony_ci * In some cases, host needs to look into individual record status 58362306a36Sopenharmony_ci * even though FW reported success for that IOCTL. 58462306a36Sopenharmony_ci */ 58562306a36Sopenharmony_ci if (rc < 0 || req->ip_params.ip_record.status) { 58662306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 58762306a36Sopenharmony_ci "BG_%d : failed to set IP: rc %d status %d\n", 58862306a36Sopenharmony_ci rc, req->ip_params.ip_record.status); 58962306a36Sopenharmony_ci if (req->ip_params.ip_record.status) 59062306a36Sopenharmony_ci rc = -EINVAL; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 59362306a36Sopenharmony_ci return rc; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ciint beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type, 59762306a36Sopenharmony_ci u8 *ip, u8 *subnet) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci struct be_cmd_get_if_info_resp *if_info; 60062306a36Sopenharmony_ci struct be_cmd_rel_dhcp_req *reldhcp; 60162306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 60262306a36Sopenharmony_ci int rc; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci rc = beiscsi_if_get_info(phba, ip_type, &if_info); 60562306a36Sopenharmony_ci if (rc) 60662306a36Sopenharmony_ci return rc; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci if (if_info->dhcp_state) { 60962306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, 61062306a36Sopenharmony_ci CMD_SUBSYSTEM_ISCSI, 61162306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, 61262306a36Sopenharmony_ci sizeof(*reldhcp)); 61362306a36Sopenharmony_ci if (rc) 61462306a36Sopenharmony_ci goto exit; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci reldhcp = nonemb_cmd.va; 61762306a36Sopenharmony_ci reldhcp->interface_hndl = phba->interface_handle; 61862306a36Sopenharmony_ci reldhcp->ip_type = ip_type; 61962306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0); 62062306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 62162306a36Sopenharmony_ci if (rc < 0) { 62262306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 62362306a36Sopenharmony_ci "BG_%d : failed to release existing DHCP: %d\n", 62462306a36Sopenharmony_ci rc); 62562306a36Sopenharmony_ci goto exit; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /* first delete any IP set */ 63062306a36Sopenharmony_ci if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { 63162306a36Sopenharmony_ci rc = beiscsi_if_clr_ip(phba, if_info); 63262306a36Sopenharmony_ci if (rc) 63362306a36Sopenharmony_ci goto exit; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* if ip == NULL then this is called just to release DHCP IP */ 63762306a36Sopenharmony_ci if (ip) 63862306a36Sopenharmony_ci rc = beiscsi_if_set_ip(phba, ip, subnet, ip_type); 63962306a36Sopenharmony_ciexit: 64062306a36Sopenharmony_ci kfree(if_info); 64162306a36Sopenharmony_ci return rc; 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ciint beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) 64562306a36Sopenharmony_ci{ 64662306a36Sopenharmony_ci struct be_cmd_get_def_gateway_resp gw_resp; 64762306a36Sopenharmony_ci struct be_cmd_get_if_info_resp *if_info; 64862306a36Sopenharmony_ci struct be_cmd_set_dhcp_req *dhcpreq; 64962306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 65062306a36Sopenharmony_ci u8 *gw; 65162306a36Sopenharmony_ci int rc; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci rc = beiscsi_if_get_info(phba, ip_type, &if_info); 65462306a36Sopenharmony_ci if (rc) 65562306a36Sopenharmony_ci return rc; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci if (if_info->dhcp_state) { 65862306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 65962306a36Sopenharmony_ci "BG_%d : DHCP Already Enabled\n"); 66062306a36Sopenharmony_ci goto exit; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci /* first delete any IP set */ 66462306a36Sopenharmony_ci if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { 66562306a36Sopenharmony_ci rc = beiscsi_if_clr_ip(phba, if_info); 66662306a36Sopenharmony_ci if (rc) 66762306a36Sopenharmony_ci goto exit; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* delete gateway settings if mode change is to DHCP */ 67162306a36Sopenharmony_ci memset(&gw_resp, 0, sizeof(gw_resp)); 67262306a36Sopenharmony_ci /* use ip_type provided in if_info */ 67362306a36Sopenharmony_ci rc = beiscsi_if_get_gw(phba, if_info->ip_addr.ip_type, &gw_resp); 67462306a36Sopenharmony_ci if (rc) { 67562306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 67662306a36Sopenharmony_ci "BG_%d : Failed to Get Gateway Addr\n"); 67762306a36Sopenharmony_ci goto exit; 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci gw = (u8 *)&gw_resp.ip_addr.addr; 68062306a36Sopenharmony_ci if (!beiscsi_if_zero_ip(gw, if_info->ip_addr.ip_type)) { 68162306a36Sopenharmony_ci rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, 68262306a36Sopenharmony_ci if_info->ip_addr.ip_type, gw); 68362306a36Sopenharmony_ci if (rc) { 68462306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 68562306a36Sopenharmony_ci "BG_%d : Failed to clear Gateway Addr Set\n"); 68662306a36Sopenharmony_ci goto exit; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI, 69162306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, 69262306a36Sopenharmony_ci sizeof(*dhcpreq)); 69362306a36Sopenharmony_ci if (rc) 69462306a36Sopenharmony_ci goto exit; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci dhcpreq = nonemb_cmd.va; 69762306a36Sopenharmony_ci dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */ 69862306a36Sopenharmony_ci dhcpreq->retry_count = 1; 69962306a36Sopenharmony_ci dhcpreq->interface_hndl = phba->interface_handle; 70062306a36Sopenharmony_ci dhcpreq->ip_type = ip_type; 70162306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, NULL, 0); 70262306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 70362306a36Sopenharmony_ciexit: 70462306a36Sopenharmony_ci kfree(if_info); 70562306a36Sopenharmony_ci return rc; 70662306a36Sopenharmony_ci} 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci/** 70962306a36Sopenharmony_ci * beiscsi_if_set_vlan()- Issue and wait for CMD completion 71062306a36Sopenharmony_ci * @phba: device private structure instance 71162306a36Sopenharmony_ci * @vlan_tag: VLAN tag 71262306a36Sopenharmony_ci * 71362306a36Sopenharmony_ci * Issue the MBX Cmd and wait for the completion of the 71462306a36Sopenharmony_ci * command. 71562306a36Sopenharmony_ci * 71662306a36Sopenharmony_ci * returns 71762306a36Sopenharmony_ci * Success: 0 71862306a36Sopenharmony_ci * Failure: Non-Xero Value 71962306a36Sopenharmony_ci **/ 72062306a36Sopenharmony_ciint beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci int rc; 72362306a36Sopenharmony_ci unsigned int tag; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci tag = be_cmd_set_vlan(phba, vlan_tag); 72662306a36Sopenharmony_ci if (!tag) { 72762306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 72862306a36Sopenharmony_ci (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), 72962306a36Sopenharmony_ci "BG_%d : VLAN Setting Failed\n"); 73062306a36Sopenharmony_ci return -EBUSY; 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); 73462306a36Sopenharmony_ci if (rc) { 73562306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 73662306a36Sopenharmony_ci (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), 73762306a36Sopenharmony_ci "BS_%d : VLAN MBX Cmd Failed\n"); 73862306a36Sopenharmony_ci return rc; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci return rc; 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ciint beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type, 74562306a36Sopenharmony_ci struct be_cmd_get_if_info_resp **if_info) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci struct be_cmd_get_if_info_req *req; 74862306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 74962306a36Sopenharmony_ci uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); 75062306a36Sopenharmony_ci int rc; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci rc = beiscsi_if_get_handle(phba); 75362306a36Sopenharmony_ci if (rc) 75462306a36Sopenharmony_ci return rc; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci do { 75762306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, 75862306a36Sopenharmony_ci CMD_SUBSYSTEM_ISCSI, 75962306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, 76062306a36Sopenharmony_ci ioctl_size); 76162306a36Sopenharmony_ci if (rc) 76262306a36Sopenharmony_ci return rc; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci req = nonemb_cmd.va; 76562306a36Sopenharmony_ci req->interface_hndl = phba->interface_handle; 76662306a36Sopenharmony_ci req->ip_type = ip_type; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci /* Allocate memory for if_info */ 76962306a36Sopenharmony_ci *if_info = kzalloc(ioctl_size, GFP_KERNEL); 77062306a36Sopenharmony_ci if (!*if_info) { 77162306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 77262306a36Sopenharmony_ci BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 77362306a36Sopenharmony_ci "BG_%d : Memory Allocation Failure\n"); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, 77662306a36Sopenharmony_ci -ENOMEM); 77762306a36Sopenharmony_ci return -ENOMEM; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, *if_info, 78162306a36Sopenharmony_ci ioctl_size); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci /* Check if the error is because of Insufficent_Buffer */ 78462306a36Sopenharmony_ci if (rc == -EAGAIN) { 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci /* Get the new memory size */ 78762306a36Sopenharmony_ci ioctl_size = ((struct be_cmd_resp_hdr *) 78862306a36Sopenharmony_ci nonemb_cmd.va)->actual_resp_len; 78962306a36Sopenharmony_ci ioctl_size += sizeof(struct be_cmd_req_hdr); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 79262306a36Sopenharmony_ci /* Free the virtual memory */ 79362306a36Sopenharmony_ci kfree(*if_info); 79462306a36Sopenharmony_ci } else { 79562306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 79662306a36Sopenharmony_ci break; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci } while (true); 79962306a36Sopenharmony_ci return rc; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ciint mgmt_get_nic_conf(struct beiscsi_hba *phba, 80362306a36Sopenharmony_ci struct be_cmd_get_nic_conf_resp *nic) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 80662306a36Sopenharmony_ci int rc; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci rc = beiscsi_prep_nemb_cmd(phba, &nonemb_cmd, CMD_SUBSYSTEM_ISCSI, 80962306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, 81062306a36Sopenharmony_ci sizeof(*nic)); 81162306a36Sopenharmony_ci if (rc) 81262306a36Sopenharmony_ci return rc; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci rc = beiscsi_exec_nemb_cmd(phba, &nonemb_cmd, NULL, nic, sizeof(*nic)); 81562306a36Sopenharmony_ci beiscsi_free_nemb_cmd(phba, &nonemb_cmd, rc); 81662306a36Sopenharmony_ci return rc; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_cistatic void beiscsi_boot_process_compl(struct beiscsi_hba *phba, 82062306a36Sopenharmony_ci unsigned int tag) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct be_cmd_get_boot_target_resp *boot_resp; 82362306a36Sopenharmony_ci struct be_cmd_resp_logout_fw_sess *logo_resp; 82462306a36Sopenharmony_ci struct be_cmd_get_session_resp *sess_resp; 82562306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 82662306a36Sopenharmony_ci struct boot_struct *bs; 82762306a36Sopenharmony_ci int boot_work, status; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci if (!test_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) { 83062306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 83162306a36Sopenharmony_ci "BG_%d : %s no boot work %lx\n", 83262306a36Sopenharmony_ci __func__, phba->state); 83362306a36Sopenharmony_ci return; 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci if (phba->boot_struct.tag != tag) { 83762306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 83862306a36Sopenharmony_ci "BG_%d : %s tag mismatch %d:%d\n", 83962306a36Sopenharmony_ci __func__, tag, phba->boot_struct.tag); 84062306a36Sopenharmony_ci return; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci bs = &phba->boot_struct; 84362306a36Sopenharmony_ci boot_work = 1; 84462306a36Sopenharmony_ci status = 0; 84562306a36Sopenharmony_ci switch (bs->action) { 84662306a36Sopenharmony_ci case BEISCSI_BOOT_REOPEN_SESS: 84762306a36Sopenharmony_ci status = __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); 84862306a36Sopenharmony_ci if (!status) 84962306a36Sopenharmony_ci bs->action = BEISCSI_BOOT_GET_SHANDLE; 85062306a36Sopenharmony_ci else 85162306a36Sopenharmony_ci bs->retry--; 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci case BEISCSI_BOOT_GET_SHANDLE: 85462306a36Sopenharmony_ci status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL); 85562306a36Sopenharmony_ci if (!status) { 85662306a36Sopenharmony_ci boot_resp = embedded_payload(wrb); 85762306a36Sopenharmony_ci bs->s_handle = boot_resp->boot_session_handle; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci if (bs->s_handle == BE_BOOT_INVALID_SHANDLE) { 86062306a36Sopenharmony_ci bs->action = BEISCSI_BOOT_REOPEN_SESS; 86162306a36Sopenharmony_ci bs->retry--; 86262306a36Sopenharmony_ci } else { 86362306a36Sopenharmony_ci bs->action = BEISCSI_BOOT_GET_SINFO; 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci break; 86662306a36Sopenharmony_ci case BEISCSI_BOOT_GET_SINFO: 86762306a36Sopenharmony_ci status = __beiscsi_mcc_compl_status(phba, tag, NULL, 86862306a36Sopenharmony_ci &bs->nonemb_cmd); 86962306a36Sopenharmony_ci if (!status) { 87062306a36Sopenharmony_ci sess_resp = bs->nonemb_cmd.va; 87162306a36Sopenharmony_ci memcpy(&bs->boot_sess, &sess_resp->session_info, 87262306a36Sopenharmony_ci sizeof(struct mgmt_session_info)); 87362306a36Sopenharmony_ci bs->action = BEISCSI_BOOT_LOGOUT_SESS; 87462306a36Sopenharmony_ci } else { 87562306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 87662306a36Sopenharmony_ci "BG_%d : get boot session info error : 0x%x\n", 87762306a36Sopenharmony_ci status); 87862306a36Sopenharmony_ci boot_work = 0; 87962306a36Sopenharmony_ci } 88062306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, bs->nonemb_cmd.size, 88162306a36Sopenharmony_ci bs->nonemb_cmd.va, bs->nonemb_cmd.dma); 88262306a36Sopenharmony_ci bs->nonemb_cmd.va = NULL; 88362306a36Sopenharmony_ci break; 88462306a36Sopenharmony_ci case BEISCSI_BOOT_LOGOUT_SESS: 88562306a36Sopenharmony_ci status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL); 88662306a36Sopenharmony_ci if (!status) { 88762306a36Sopenharmony_ci logo_resp = embedded_payload(wrb); 88862306a36Sopenharmony_ci if (logo_resp->session_status != BE_SESS_STATUS_CLOSE) { 88962306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 89062306a36Sopenharmony_ci "BG_%d : FW boot session logout error : 0x%x\n", 89162306a36Sopenharmony_ci logo_resp->session_status); 89262306a36Sopenharmony_ci } 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci /* continue to create boot_kset even if logout failed? */ 89562306a36Sopenharmony_ci bs->action = BEISCSI_BOOT_CREATE_KSET; 89662306a36Sopenharmony_ci break; 89762306a36Sopenharmony_ci default: 89862306a36Sopenharmony_ci break; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci /* clear the tag so no other completion matches this tag */ 90262306a36Sopenharmony_ci bs->tag = 0; 90362306a36Sopenharmony_ci if (!bs->retry) { 90462306a36Sopenharmony_ci boot_work = 0; 90562306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 90662306a36Sopenharmony_ci "BG_%d : failed to setup boot target: status %d action %d\n", 90762306a36Sopenharmony_ci status, bs->action); 90862306a36Sopenharmony_ci } 90962306a36Sopenharmony_ci if (!boot_work) { 91062306a36Sopenharmony_ci /* wait for next event to start boot_work */ 91162306a36Sopenharmony_ci clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state); 91262306a36Sopenharmony_ci return; 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci schedule_work(&phba->boot_work); 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci/** 91862306a36Sopenharmony_ci * beiscsi_boot_logout_sess()- Logout from boot FW session 91962306a36Sopenharmony_ci * @phba: Device priv structure instance 92062306a36Sopenharmony_ci * 92162306a36Sopenharmony_ci * return 92262306a36Sopenharmony_ci * the TAG used for MBOX Command 92362306a36Sopenharmony_ci * 92462306a36Sopenharmony_ci */ 92562306a36Sopenharmony_ciunsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 92862306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 92962306a36Sopenharmony_ci struct be_cmd_req_logout_fw_sess *req; 93062306a36Sopenharmony_ci unsigned int tag; 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 93362306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 93462306a36Sopenharmony_ci if (!wrb) { 93562306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 93662306a36Sopenharmony_ci return 0; 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci req = embedded_payload(wrb); 94062306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 94162306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 94262306a36Sopenharmony_ci OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET, 94362306a36Sopenharmony_ci sizeof(struct be_cmd_req_logout_fw_sess)); 94462306a36Sopenharmony_ci /* Use the session handle copied into boot_sess */ 94562306a36Sopenharmony_ci req->session_handle = phba->boot_struct.boot_sess.session_handle; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci phba->boot_struct.tag = tag; 94862306a36Sopenharmony_ci set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); 94962306a36Sopenharmony_ci ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci be_mcc_notify(phba, tag); 95262306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci return tag; 95562306a36Sopenharmony_ci} 95662306a36Sopenharmony_ci/** 95762306a36Sopenharmony_ci * beiscsi_boot_reopen_sess()- Reopen boot session 95862306a36Sopenharmony_ci * @phba: Device priv structure instance 95962306a36Sopenharmony_ci * 96062306a36Sopenharmony_ci * return 96162306a36Sopenharmony_ci * the TAG used for MBOX Command 96262306a36Sopenharmony_ci * 96362306a36Sopenharmony_ci **/ 96462306a36Sopenharmony_ciunsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 96762306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 96862306a36Sopenharmony_ci struct be_cmd_reopen_session_req *req; 96962306a36Sopenharmony_ci unsigned int tag; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 97262306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 97362306a36Sopenharmony_ci if (!wrb) { 97462306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 97562306a36Sopenharmony_ci return 0; 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci req = embedded_payload(wrb); 97962306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 98062306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 98162306a36Sopenharmony_ci OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS, 98262306a36Sopenharmony_ci sizeof(struct be_cmd_reopen_session_resp)); 98362306a36Sopenharmony_ci req->reopen_type = BE_REOPEN_BOOT_SESSIONS; 98462306a36Sopenharmony_ci req->session_handle = BE_BOOT_INVALID_SHANDLE; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci phba->boot_struct.tag = tag; 98762306a36Sopenharmony_ci set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); 98862306a36Sopenharmony_ci ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci be_mcc_notify(phba, tag); 99162306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 99262306a36Sopenharmony_ci return tag; 99362306a36Sopenharmony_ci} 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci/** 99762306a36Sopenharmony_ci * beiscsi_boot_get_sinfo()- Get boot session info 99862306a36Sopenharmony_ci * @phba: device priv structure instance 99962306a36Sopenharmony_ci * 100062306a36Sopenharmony_ci * Fetches the boot_struct.s_handle info from FW. 100162306a36Sopenharmony_ci * return 100262306a36Sopenharmony_ci * the TAG used for MBOX Command 100362306a36Sopenharmony_ci * 100462306a36Sopenharmony_ci **/ 100562306a36Sopenharmony_ciunsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) 100662306a36Sopenharmony_ci{ 100762306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 100862306a36Sopenharmony_ci struct be_cmd_get_session_req *req; 100962306a36Sopenharmony_ci struct be_dma_mem *nonemb_cmd; 101062306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 101162306a36Sopenharmony_ci struct be_sge *sge; 101262306a36Sopenharmony_ci unsigned int tag; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 101562306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 101662306a36Sopenharmony_ci if (!wrb) { 101762306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 101862306a36Sopenharmony_ci return 0; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci nonemb_cmd = &phba->boot_struct.nonemb_cmd; 102262306a36Sopenharmony_ci nonemb_cmd->size = sizeof(struct be_cmd_get_session_resp); 102362306a36Sopenharmony_ci nonemb_cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, 102462306a36Sopenharmony_ci nonemb_cmd->size, 102562306a36Sopenharmony_ci &nonemb_cmd->dma, 102662306a36Sopenharmony_ci GFP_KERNEL); 102762306a36Sopenharmony_ci if (!nonemb_cmd->va) { 102862306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 102962306a36Sopenharmony_ci return 0; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci req = nonemb_cmd->va; 103362306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 103462306a36Sopenharmony_ci sge = nonembedded_sgl(wrb); 103562306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); 103662306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 103762306a36Sopenharmony_ci OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, 103862306a36Sopenharmony_ci sizeof(struct be_cmd_get_session_resp)); 103962306a36Sopenharmony_ci req->session_handle = phba->boot_struct.s_handle; 104062306a36Sopenharmony_ci sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); 104162306a36Sopenharmony_ci sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); 104262306a36Sopenharmony_ci sge->len = cpu_to_le32(nonemb_cmd->size); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci phba->boot_struct.tag = tag; 104562306a36Sopenharmony_ci set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); 104662306a36Sopenharmony_ci ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci be_mcc_notify(phba, tag); 104962306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 105062306a36Sopenharmony_ci return tag; 105162306a36Sopenharmony_ci} 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ciunsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async) 105462306a36Sopenharmony_ci{ 105562306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 105662306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 105762306a36Sopenharmony_ci struct be_cmd_get_boot_target_req *req; 105862306a36Sopenharmony_ci unsigned int tag; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 106162306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 106262306a36Sopenharmony_ci if (!wrb) { 106362306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 106462306a36Sopenharmony_ci return 0; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci req = embedded_payload(wrb); 106862306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 106962306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 107062306a36Sopenharmony_ci OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, 107162306a36Sopenharmony_ci sizeof(struct be_cmd_get_boot_target_resp)); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci if (async) { 107462306a36Sopenharmony_ci phba->boot_struct.tag = tag; 107562306a36Sopenharmony_ci set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); 107662306a36Sopenharmony_ci ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; 107762306a36Sopenharmony_ci } 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci be_mcc_notify(phba, tag); 108062306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 108162306a36Sopenharmony_ci return tag; 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci/** 108562306a36Sopenharmony_ci * beiscsi_boot_get_shandle()- Get boot session handle 108662306a36Sopenharmony_ci * @phba: device priv structure instance 108762306a36Sopenharmony_ci * @s_handle: session handle returned for boot session. 108862306a36Sopenharmony_ci * 108962306a36Sopenharmony_ci * return 109062306a36Sopenharmony_ci * Success: 1 109162306a36Sopenharmony_ci * Failure: negative 109262306a36Sopenharmony_ci * 109362306a36Sopenharmony_ci **/ 109462306a36Sopenharmony_ciint beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle) 109562306a36Sopenharmony_ci{ 109662306a36Sopenharmony_ci struct be_cmd_get_boot_target_resp *boot_resp; 109762306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 109862306a36Sopenharmony_ci unsigned int tag; 109962306a36Sopenharmony_ci int rc; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci *s_handle = BE_BOOT_INVALID_SHANDLE; 110262306a36Sopenharmony_ci /* get configured boot session count and handle */ 110362306a36Sopenharmony_ci tag = __beiscsi_boot_get_shandle(phba, 0); 110462306a36Sopenharmony_ci if (!tag) { 110562306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 110662306a36Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, 110762306a36Sopenharmony_ci "BG_%d : Getting Boot Target Info Failed\n"); 110862306a36Sopenharmony_ci return -EAGAIN; 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); 111262306a36Sopenharmony_ci if (rc) { 111362306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 111462306a36Sopenharmony_ci BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, 111562306a36Sopenharmony_ci "BG_%d : MBX CMD get_boot_target Failed\n"); 111662306a36Sopenharmony_ci return -EBUSY; 111762306a36Sopenharmony_ci } 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci boot_resp = embedded_payload(wrb); 112062306a36Sopenharmony_ci /* check if there are any boot targets configured */ 112162306a36Sopenharmony_ci if (!boot_resp->boot_session_count) { 112262306a36Sopenharmony_ci __beiscsi_log(phba, KERN_INFO, 112362306a36Sopenharmony_ci "BG_%d : No boot targets configured\n"); 112462306a36Sopenharmony_ci return -ENXIO; 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci /* only if FW has logged in to the boot target, s_handle is valid */ 112862306a36Sopenharmony_ci *s_handle = boot_resp->boot_session_handle; 112962306a36Sopenharmony_ci return 1; 113062306a36Sopenharmony_ci} 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci/** 113362306a36Sopenharmony_ci * beiscsi_drvr_ver_disp()- Display the driver Name and Version 113462306a36Sopenharmony_ci * @dev: ptr to device not used. 113562306a36Sopenharmony_ci * @attr: device attribute, not used. 113662306a36Sopenharmony_ci * @buf: contains formatted text driver name and version 113762306a36Sopenharmony_ci * 113862306a36Sopenharmony_ci * return 113962306a36Sopenharmony_ci * size of the formatted string 114062306a36Sopenharmony_ci **/ 114162306a36Sopenharmony_cissize_t 114262306a36Sopenharmony_cibeiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr, 114362306a36Sopenharmony_ci char *buf) 114462306a36Sopenharmony_ci{ 114562306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, BE_NAME "\n"); 114662306a36Sopenharmony_ci} 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci/** 114962306a36Sopenharmony_ci * beiscsi_fw_ver_disp()- Display Firmware Version 115062306a36Sopenharmony_ci * @dev: ptr to device not used. 115162306a36Sopenharmony_ci * @attr: device attribute, not used. 115262306a36Sopenharmony_ci * @buf: contains formatted text Firmware version 115362306a36Sopenharmony_ci * 115462306a36Sopenharmony_ci * return 115562306a36Sopenharmony_ci * size of the formatted string 115662306a36Sopenharmony_ci **/ 115762306a36Sopenharmony_cissize_t 115862306a36Sopenharmony_cibeiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, 115962306a36Sopenharmony_ci char *buf) 116062306a36Sopenharmony_ci{ 116162306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 116262306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str); 116562306a36Sopenharmony_ci} 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci/** 116862306a36Sopenharmony_ci * beiscsi_active_session_disp()- Display Sessions Active 116962306a36Sopenharmony_ci * @dev: ptr to device not used. 117062306a36Sopenharmony_ci * @attr: device attribute, not used. 117162306a36Sopenharmony_ci * @buf: contains formatted text Session Count 117262306a36Sopenharmony_ci * 117362306a36Sopenharmony_ci * return 117462306a36Sopenharmony_ci * size of the formatted string 117562306a36Sopenharmony_ci **/ 117662306a36Sopenharmony_cissize_t 117762306a36Sopenharmony_cibeiscsi_active_session_disp(struct device *dev, struct device_attribute *attr, 117862306a36Sopenharmony_ci char *buf) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 118162306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 118262306a36Sopenharmony_ci uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 118562306a36Sopenharmony_ci if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { 118662306a36Sopenharmony_ci avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num); 118762306a36Sopenharmony_ci total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num); 118862306a36Sopenharmony_ci len += scnprintf(buf+len, PAGE_SIZE - len, 118962306a36Sopenharmony_ci "ULP%d : %d\n", ulp_num, 119062306a36Sopenharmony_ci (total_cids - avlbl_cids)); 119162306a36Sopenharmony_ci } else 119262306a36Sopenharmony_ci len += scnprintf(buf+len, PAGE_SIZE - len, 119362306a36Sopenharmony_ci "ULP%d : %d\n", ulp_num, 0); 119462306a36Sopenharmony_ci } 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci return len; 119762306a36Sopenharmony_ci} 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci/** 120062306a36Sopenharmony_ci * beiscsi_free_session_disp()- Display Avaliable Session 120162306a36Sopenharmony_ci * @dev: ptr to device not used. 120262306a36Sopenharmony_ci * @attr: device attribute, not used. 120362306a36Sopenharmony_ci * @buf: contains formatted text Session Count 120462306a36Sopenharmony_ci * 120562306a36Sopenharmony_ci * return 120662306a36Sopenharmony_ci * size of the formatted string 120762306a36Sopenharmony_ci **/ 120862306a36Sopenharmony_cissize_t 120962306a36Sopenharmony_cibeiscsi_free_session_disp(struct device *dev, struct device_attribute *attr, 121062306a36Sopenharmony_ci char *buf) 121162306a36Sopenharmony_ci{ 121262306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 121362306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 121462306a36Sopenharmony_ci uint16_t ulp_num, len = 0; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { 121762306a36Sopenharmony_ci if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) 121862306a36Sopenharmony_ci len += scnprintf(buf+len, PAGE_SIZE - len, 121962306a36Sopenharmony_ci "ULP%d : %d\n", ulp_num, 122062306a36Sopenharmony_ci BEISCSI_ULP_AVLBL_CID(phba, ulp_num)); 122162306a36Sopenharmony_ci else 122262306a36Sopenharmony_ci len += scnprintf(buf+len, PAGE_SIZE - len, 122362306a36Sopenharmony_ci "ULP%d : %d\n", ulp_num, 0); 122462306a36Sopenharmony_ci } 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci return len; 122762306a36Sopenharmony_ci} 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci/** 123062306a36Sopenharmony_ci * beiscsi_adap_family_disp()- Display adapter family. 123162306a36Sopenharmony_ci * @dev: ptr to device to get priv structure 123262306a36Sopenharmony_ci * @attr: device attribute, not used. 123362306a36Sopenharmony_ci * @buf: contains formatted text driver name and version 123462306a36Sopenharmony_ci * 123562306a36Sopenharmony_ci * return 123662306a36Sopenharmony_ci * size of the formatted string 123762306a36Sopenharmony_ci **/ 123862306a36Sopenharmony_cissize_t 123962306a36Sopenharmony_cibeiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, 124062306a36Sopenharmony_ci char *buf) 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci uint16_t dev_id = 0; 124362306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 124462306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci dev_id = phba->pcidev->device; 124762306a36Sopenharmony_ci switch (dev_id) { 124862306a36Sopenharmony_ci case BE_DEVICE_ID1: 124962306a36Sopenharmony_ci case OC_DEVICE_ID1: 125062306a36Sopenharmony_ci case OC_DEVICE_ID2: 125162306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, 125262306a36Sopenharmony_ci "Obsolete/Unsupported BE2 Adapter Family\n"); 125362306a36Sopenharmony_ci case BE_DEVICE_ID2: 125462306a36Sopenharmony_ci case OC_DEVICE_ID3: 125562306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n"); 125662306a36Sopenharmony_ci case OC_SKH_ID1: 125762306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n"); 125862306a36Sopenharmony_ci default: 125962306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, 126062306a36Sopenharmony_ci "Unknown Adapter Family: 0x%x\n", dev_id); 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci} 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci/** 126562306a36Sopenharmony_ci * beiscsi_phys_port_disp()- Display Physical Port Identifier 126662306a36Sopenharmony_ci * @dev: ptr to device not used. 126762306a36Sopenharmony_ci * @attr: device attribute, not used. 126862306a36Sopenharmony_ci * @buf: contains formatted text port identifier 126962306a36Sopenharmony_ci * 127062306a36Sopenharmony_ci * return 127162306a36Sopenharmony_ci * size of the formatted string 127262306a36Sopenharmony_ci **/ 127362306a36Sopenharmony_cissize_t 127462306a36Sopenharmony_cibeiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, 127562306a36Sopenharmony_ci char *buf) 127662306a36Sopenharmony_ci{ 127762306a36Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 127862306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "Port Identifier : %u\n", 128162306a36Sopenharmony_ci phba->fw_config.phys_port); 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_civoid beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, 128562306a36Sopenharmony_ci struct wrb_handle *pwrb_handle, 128662306a36Sopenharmony_ci struct be_mem_descriptor *mem_descr, 128762306a36Sopenharmony_ci struct hwi_wrb_context *pwrb_context) 128862306a36Sopenharmony_ci{ 128962306a36Sopenharmony_ci struct iscsi_wrb *pwrb = pwrb_handle->pwrb; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 129262306a36Sopenharmony_ci max_send_data_segment_length, pwrb, 129362306a36Sopenharmony_ci params->dw[offsetof(struct amap_beiscsi_offload_params, 129462306a36Sopenharmony_ci max_send_data_segment_length) / 32]); 129562306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb, 129662306a36Sopenharmony_ci BE_TGT_CTX_UPDT_CMD); 129762306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 129862306a36Sopenharmony_ci first_burst_length, 129962306a36Sopenharmony_ci pwrb, 130062306a36Sopenharmony_ci params->dw[offsetof(struct amap_beiscsi_offload_params, 130162306a36Sopenharmony_ci first_burst_length) / 32]); 130262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb, 130362306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 130462306a36Sopenharmony_ci erl) / 32] & OFFLD_PARAMS_ERL)); 130562306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb, 130662306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 130762306a36Sopenharmony_ci dde) / 32] & OFFLD_PARAMS_DDE) >> 2); 130862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb, 130962306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 131062306a36Sopenharmony_ci hde) / 32] & OFFLD_PARAMS_HDE) >> 3); 131162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb, 131262306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 131362306a36Sopenharmony_ci ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); 131462306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb, 131562306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 131662306a36Sopenharmony_ci imd) / 32] & OFFLD_PARAMS_IMD) >> 5); 131762306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn, 131862306a36Sopenharmony_ci pwrb, 131962306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 132062306a36Sopenharmony_ci exp_statsn) / 32] + 1)); 132162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx, 132262306a36Sopenharmony_ci pwrb, pwrb_handle->wrb_index); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 132562306a36Sopenharmony_ci max_burst_length, pwrb, params->dw[offsetof 132662306a36Sopenharmony_ci (struct amap_beiscsi_offload_params, 132762306a36Sopenharmony_ci max_burst_length) / 32]); 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, 133062306a36Sopenharmony_ci pwrb, pwrb_handle->wrb_index); 133162306a36Sopenharmony_ci if (pwrb_context->plast_wrb) 133262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 133362306a36Sopenharmony_ci ptr2nextwrb, 133462306a36Sopenharmony_ci pwrb_context->plast_wrb, 133562306a36Sopenharmony_ci pwrb_handle->wrb_index); 133662306a36Sopenharmony_ci pwrb_context->plast_wrb = pwrb; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 133962306a36Sopenharmony_ci session_state, pwrb, 0); 134062306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, 134162306a36Sopenharmony_ci pwrb, 1); 134262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq, 134362306a36Sopenharmony_ci pwrb, 0); 134462306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb, 134562306a36Sopenharmony_ci 0); 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci mem_descr += ISCSI_MEM_GLOBAL_HEADER; 134862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 134962306a36Sopenharmony_ci pad_buffer_addr_hi, pwrb, 135062306a36Sopenharmony_ci mem_descr->mem_array[0].bus_address.u.a32.address_hi); 135162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, 135262306a36Sopenharmony_ci pad_buffer_addr_lo, pwrb, 135362306a36Sopenharmony_ci mem_descr->mem_array[0].bus_address.u.a32.address_lo); 135462306a36Sopenharmony_ci} 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_civoid beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, 135762306a36Sopenharmony_ci struct wrb_handle *pwrb_handle, 135862306a36Sopenharmony_ci struct hwi_wrb_context *pwrb_context) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci struct iscsi_wrb *pwrb = pwrb_handle->pwrb; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 136362306a36Sopenharmony_ci max_burst_length, pwrb, params->dw[offsetof 136462306a36Sopenharmony_ci (struct amap_beiscsi_offload_params, 136562306a36Sopenharmony_ci max_burst_length) / 32]); 136662306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 136762306a36Sopenharmony_ci type, pwrb, 136862306a36Sopenharmony_ci BE_TGT_CTX_UPDT_CMD); 136962306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 137062306a36Sopenharmony_ci ptr2nextwrb, 137162306a36Sopenharmony_ci pwrb, pwrb_handle->wrb_index); 137262306a36Sopenharmony_ci if (pwrb_context->plast_wrb) 137362306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 137462306a36Sopenharmony_ci ptr2nextwrb, 137562306a36Sopenharmony_ci pwrb_context->plast_wrb, 137662306a36Sopenharmony_ci pwrb_handle->wrb_index); 137762306a36Sopenharmony_ci pwrb_context->plast_wrb = pwrb; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx, 138062306a36Sopenharmony_ci pwrb, pwrb_handle->wrb_index); 138162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 138262306a36Sopenharmony_ci max_send_data_segment_length, pwrb, 138362306a36Sopenharmony_ci params->dw[offsetof(struct amap_beiscsi_offload_params, 138462306a36Sopenharmony_ci max_send_data_segment_length) / 32]); 138562306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 138662306a36Sopenharmony_ci first_burst_length, pwrb, 138762306a36Sopenharmony_ci params->dw[offsetof(struct amap_beiscsi_offload_params, 138862306a36Sopenharmony_ci first_burst_length) / 32]); 138962306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 139062306a36Sopenharmony_ci max_recv_dataseg_len, pwrb, 139162306a36Sopenharmony_ci params->dw[offsetof(struct amap_beiscsi_offload_params, 139262306a36Sopenharmony_ci max_recv_data_segment_length) / 32]); 139362306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 139462306a36Sopenharmony_ci max_cxns, pwrb, BEISCSI_MAX_CXNS); 139562306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb, 139662306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 139762306a36Sopenharmony_ci erl) / 32] & OFFLD_PARAMS_ERL)); 139862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb, 139962306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 140062306a36Sopenharmony_ci dde) / 32] & OFFLD_PARAMS_DDE) >> 2); 140162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb, 140262306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 140362306a36Sopenharmony_ci hde) / 32] & OFFLD_PARAMS_HDE) >> 3); 140462306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 140562306a36Sopenharmony_ci ir2t, pwrb, 140662306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 140762306a36Sopenharmony_ci ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); 140862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb, 140962306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 141062306a36Sopenharmony_ci imd) / 32] & OFFLD_PARAMS_IMD) >> 5); 141162306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 141262306a36Sopenharmony_ci data_seq_inorder, 141362306a36Sopenharmony_ci pwrb, 141462306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 141562306a36Sopenharmony_ci data_seq_inorder) / 32] & 141662306a36Sopenharmony_ci OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6); 141762306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, 141862306a36Sopenharmony_ci pdu_seq_inorder, 141962306a36Sopenharmony_ci pwrb, 142062306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 142162306a36Sopenharmony_ci pdu_seq_inorder) / 32] & 142262306a36Sopenharmony_ci OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7); 142362306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t, 142462306a36Sopenharmony_ci pwrb, 142562306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 142662306a36Sopenharmony_ci max_r2t) / 32] & 142762306a36Sopenharmony_ci OFFLD_PARAMS_MAX_R2T) >> 8); 142862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn, 142962306a36Sopenharmony_ci pwrb, 143062306a36Sopenharmony_ci (params->dw[offsetof(struct amap_beiscsi_offload_params, 143162306a36Sopenharmony_ci exp_statsn) / 32] + 1)); 143262306a36Sopenharmony_ci} 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ciunsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba, 143562306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep) 143662306a36Sopenharmony_ci{ 143762306a36Sopenharmony_ci struct be_invalidate_connection_params_in *req; 143862306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 143962306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 144062306a36Sopenharmony_ci unsigned int tag = 0; 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 144362306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 144462306a36Sopenharmony_ci if (!wrb) { 144562306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 144662306a36Sopenharmony_ci return 0; 144762306a36Sopenharmony_ci } 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci req = embedded_payload(wrb); 145062306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(union be_invalidate_connection_params), 145162306a36Sopenharmony_ci true, 0); 145262306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, 145362306a36Sopenharmony_ci OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, 145462306a36Sopenharmony_ci sizeof(*req)); 145562306a36Sopenharmony_ci req->session_handle = beiscsi_ep->fw_handle; 145662306a36Sopenharmony_ci req->cid = beiscsi_ep->ep_cid; 145762306a36Sopenharmony_ci if (beiscsi_ep->conn) 145862306a36Sopenharmony_ci req->cleanup_type = BE_CLEANUP_TYPE_INVALIDATE; 145962306a36Sopenharmony_ci else 146062306a36Sopenharmony_ci req->cleanup_type = BE_CLEANUP_TYPE_ISSUE_TCP_RST; 146162306a36Sopenharmony_ci /** 146262306a36Sopenharmony_ci * 0 - non-persistent targets 146362306a36Sopenharmony_ci * 1 - save session info on flash 146462306a36Sopenharmony_ci */ 146562306a36Sopenharmony_ci req->save_cfg = 0; 146662306a36Sopenharmony_ci be_mcc_notify(phba, tag); 146762306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 146862306a36Sopenharmony_ci return tag; 146962306a36Sopenharmony_ci} 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ciunsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba, 147262306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep) 147362306a36Sopenharmony_ci{ 147462306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 147562306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 147662306a36Sopenharmony_ci struct be_tcp_upload_params_in *req; 147762306a36Sopenharmony_ci unsigned int tag; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 148062306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 148162306a36Sopenharmony_ci if (!wrb) { 148262306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 148362306a36Sopenharmony_ci return 0; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci req = embedded_payload(wrb); 148762306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, sizeof(union be_tcp_upload_params), true, 0); 148862306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, 148962306a36Sopenharmony_ci OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); 149062306a36Sopenharmony_ci req->id = beiscsi_ep->ep_cid; 149162306a36Sopenharmony_ci if (beiscsi_ep->conn) 149262306a36Sopenharmony_ci req->upload_type = BE_UPLOAD_TYPE_GRACEFUL; 149362306a36Sopenharmony_ci else 149462306a36Sopenharmony_ci req->upload_type = BE_UPLOAD_TYPE_ABORT; 149562306a36Sopenharmony_ci be_mcc_notify(phba, tag); 149662306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 149762306a36Sopenharmony_ci return tag; 149862306a36Sopenharmony_ci} 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ciint beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba, 150162306a36Sopenharmony_ci struct invldt_cmd_tbl *inv_tbl, 150262306a36Sopenharmony_ci unsigned int nents) 150362306a36Sopenharmony_ci{ 150462306a36Sopenharmony_ci struct be_ctrl_info *ctrl = &phba->ctrl; 150562306a36Sopenharmony_ci struct invldt_cmds_params_in *req; 150662306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 150762306a36Sopenharmony_ci struct be_mcc_wrb *wrb; 150862306a36Sopenharmony_ci unsigned int i, tag; 150962306a36Sopenharmony_ci struct be_sge *sge; 151062306a36Sopenharmony_ci int rc; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci if (!nents || nents > BE_INVLDT_CMD_TBL_SZ) 151362306a36Sopenharmony_ci return -EINVAL; 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci nonemb_cmd.size = sizeof(union be_invldt_cmds_params); 151662306a36Sopenharmony_ci nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev, 151762306a36Sopenharmony_ci nonemb_cmd.size, &nonemb_cmd.dma, 151862306a36Sopenharmony_ci GFP_KERNEL); 151962306a36Sopenharmony_ci if (!nonemb_cmd.va) { 152062306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, 152162306a36Sopenharmony_ci "BM_%d : invldt_cmds_params alloc failed\n"); 152262306a36Sopenharmony_ci return -ENOMEM; 152362306a36Sopenharmony_ci } 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci mutex_lock(&ctrl->mbox_lock); 152662306a36Sopenharmony_ci wrb = alloc_mcc_wrb(phba, &tag); 152762306a36Sopenharmony_ci if (!wrb) { 152862306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 152962306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size, 153062306a36Sopenharmony_ci nonemb_cmd.va, nonemb_cmd.dma); 153162306a36Sopenharmony_ci return -ENOMEM; 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci req = nonemb_cmd.va; 153562306a36Sopenharmony_ci be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false, 1); 153662306a36Sopenharmony_ci be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 153762306a36Sopenharmony_ci OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, 153862306a36Sopenharmony_ci sizeof(*req)); 153962306a36Sopenharmony_ci req->ref_handle = 0; 154062306a36Sopenharmony_ci req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; 154162306a36Sopenharmony_ci for (i = 0; i < nents; i++) { 154262306a36Sopenharmony_ci req->table[i].icd = inv_tbl[i].icd; 154362306a36Sopenharmony_ci req->table[i].cid = inv_tbl[i].cid; 154462306a36Sopenharmony_ci req->icd_count++; 154562306a36Sopenharmony_ci } 154662306a36Sopenharmony_ci sge = nonembedded_sgl(wrb); 154762306a36Sopenharmony_ci sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); 154862306a36Sopenharmony_ci sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd.dma)); 154962306a36Sopenharmony_ci sge->len = cpu_to_le32(nonemb_cmd.size); 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci be_mcc_notify(phba, tag); 155262306a36Sopenharmony_ci mutex_unlock(&ctrl->mbox_lock); 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); 155562306a36Sopenharmony_ci if (rc != -EBUSY) 155662306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size, 155762306a36Sopenharmony_ci nonemb_cmd.va, nonemb_cmd.dma); 155862306a36Sopenharmony_ci return rc; 155962306a36Sopenharmony_ci} 1560