162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of the Emulex Linux Device Driver for Enterprise iSCSI 462306a36Sopenharmony_ci * Host Bus Adapters. Refer to the README file included with this package 562306a36Sopenharmony_ci * for driver version and adapter compatibility. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2018 Broadcom. All Rights Reserved. 862306a36Sopenharmony_ci * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Contact Information: 1162306a36Sopenharmony_ci * linux-drivers@broadcom.com 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <scsi/libiscsi.h> 1562306a36Sopenharmony_ci#include <scsi/scsi_transport_iscsi.h> 1662306a36Sopenharmony_ci#include <scsi/scsi_transport.h> 1762306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 1862306a36Sopenharmony_ci#include <scsi/scsi_device.h> 1962306a36Sopenharmony_ci#include <scsi/scsi_host.h> 2062306a36Sopenharmony_ci#include <scsi/scsi_netlink.h> 2162306a36Sopenharmony_ci#include <net/netlink.h> 2262306a36Sopenharmony_ci#include <scsi/scsi.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "be_iscsi.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciextern struct iscsi_transport beiscsi_iscsi_transport; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/** 2962306a36Sopenharmony_ci * beiscsi_session_create - creates a new iscsi session 3062306a36Sopenharmony_ci * @ep: pointer to iscsi ep 3162306a36Sopenharmony_ci * @cmds_max: max commands supported 3262306a36Sopenharmony_ci * @qdepth: max queue depth supported 3362306a36Sopenharmony_ci * @initial_cmdsn: initial iscsi CMDSN 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_cistruct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, 3662306a36Sopenharmony_ci u16 cmds_max, 3762306a36Sopenharmony_ci u16 qdepth, 3862306a36Sopenharmony_ci u32 initial_cmdsn) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci struct Scsi_Host *shost; 4162306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep; 4262306a36Sopenharmony_ci struct iscsi_cls_session *cls_session; 4362306a36Sopenharmony_ci struct beiscsi_hba *phba; 4462306a36Sopenharmony_ci struct iscsi_session *sess; 4562306a36Sopenharmony_ci struct beiscsi_session *beiscsi_sess; 4662306a36Sopenharmony_ci struct beiscsi_io_task *io_task; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (!ep) { 5062306a36Sopenharmony_ci pr_err("beiscsi_session_create: invalid ep\n"); 5162306a36Sopenharmony_ci return NULL; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci beiscsi_ep = ep->dd_data; 5462306a36Sopenharmony_ci phba = beiscsi_ep->phba; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 5762306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 5862306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 5962306a36Sopenharmony_ci return NULL; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 6362306a36Sopenharmony_ci "BS_%d : In beiscsi_session_create\n"); 6462306a36Sopenharmony_ci if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { 6562306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 6662306a36Sopenharmony_ci "BS_%d : Cannot handle %d cmds." 6762306a36Sopenharmony_ci "Max cmds per session supported is %d. Using %d." 6862306a36Sopenharmony_ci "\n", cmds_max, 6962306a36Sopenharmony_ci beiscsi_ep->phba->params.wrbs_per_cxn, 7062306a36Sopenharmony_ci beiscsi_ep->phba->params.wrbs_per_cxn); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci shost = phba->shost; 7662306a36Sopenharmony_ci cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, 7762306a36Sopenharmony_ci shost, cmds_max, 7862306a36Sopenharmony_ci sizeof(*beiscsi_sess), 7962306a36Sopenharmony_ci sizeof(*io_task), 8062306a36Sopenharmony_ci initial_cmdsn, ISCSI_MAX_TARGET); 8162306a36Sopenharmony_ci if (!cls_session) 8262306a36Sopenharmony_ci return NULL; 8362306a36Sopenharmony_ci sess = cls_session->dd_data; 8462306a36Sopenharmony_ci beiscsi_sess = sess->dd_data; 8562306a36Sopenharmony_ci beiscsi_sess->bhs_pool = dma_pool_create("beiscsi_bhs_pool", 8662306a36Sopenharmony_ci &phba->pcidev->dev, 8762306a36Sopenharmony_ci sizeof(struct be_cmd_bhs), 8862306a36Sopenharmony_ci 64, 0); 8962306a36Sopenharmony_ci if (!beiscsi_sess->bhs_pool) 9062306a36Sopenharmony_ci goto destroy_sess; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci return cls_session; 9362306a36Sopenharmony_cidestroy_sess: 9462306a36Sopenharmony_ci iscsi_session_teardown(cls_session); 9562306a36Sopenharmony_ci return NULL; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/** 9962306a36Sopenharmony_ci * beiscsi_session_destroy - destroys iscsi session 10062306a36Sopenharmony_ci * @cls_session: pointer to iscsi cls session 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * Destroys iSCSI session instance and releases 10362306a36Sopenharmony_ci * resources allocated for it. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_civoid beiscsi_session_destroy(struct iscsi_cls_session *cls_session) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct iscsi_session *sess = cls_session->dd_data; 10862306a36Sopenharmony_ci struct beiscsi_session *beiscsi_sess = sess->dd_data; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci printk(KERN_INFO "In beiscsi_session_destroy\n"); 11162306a36Sopenharmony_ci dma_pool_destroy(beiscsi_sess->bhs_pool); 11262306a36Sopenharmony_ci iscsi_session_teardown(cls_session); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/** 11662306a36Sopenharmony_ci * beiscsi_session_fail(): Closing session with appropriate error 11762306a36Sopenharmony_ci * @cls_session: ptr to session 11862306a36Sopenharmony_ci **/ 11962306a36Sopenharmony_civoid beiscsi_session_fail(struct iscsi_cls_session *cls_session) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/** 12662306a36Sopenharmony_ci * beiscsi_conn_create - create an instance of iscsi connection 12762306a36Sopenharmony_ci * @cls_session: ptr to iscsi_cls_session 12862306a36Sopenharmony_ci * @cid: iscsi cid 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_cistruct iscsi_cls_conn * 13162306a36Sopenharmony_cibeiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct beiscsi_hba *phba; 13462306a36Sopenharmony_ci struct Scsi_Host *shost; 13562306a36Sopenharmony_ci struct iscsi_cls_conn *cls_conn; 13662306a36Sopenharmony_ci struct beiscsi_conn *beiscsi_conn; 13762306a36Sopenharmony_ci struct iscsi_conn *conn; 13862306a36Sopenharmony_ci struct iscsi_session *sess; 13962306a36Sopenharmony_ci struct beiscsi_session *beiscsi_sess; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci shost = iscsi_session_to_shost(cls_session); 14262306a36Sopenharmony_ci phba = iscsi_host_priv(shost); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 14562306a36Sopenharmony_ci "BS_%d : In beiscsi_conn_create ,cid" 14662306a36Sopenharmony_ci "from iscsi layer=%d\n", cid); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid); 14962306a36Sopenharmony_ci if (!cls_conn) 15062306a36Sopenharmony_ci return NULL; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci conn = cls_conn->dd_data; 15362306a36Sopenharmony_ci beiscsi_conn = conn->dd_data; 15462306a36Sopenharmony_ci beiscsi_conn->ep = NULL; 15562306a36Sopenharmony_ci beiscsi_conn->phba = phba; 15662306a36Sopenharmony_ci beiscsi_conn->conn = conn; 15762306a36Sopenharmony_ci sess = cls_session->dd_data; 15862306a36Sopenharmony_ci beiscsi_sess = sess->dd_data; 15962306a36Sopenharmony_ci beiscsi_conn->beiscsi_sess = beiscsi_sess; 16062306a36Sopenharmony_ci return cls_conn; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/** 16462306a36Sopenharmony_ci * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection 16562306a36Sopenharmony_ci * @cls_session: pointer to iscsi cls session 16662306a36Sopenharmony_ci * @cls_conn: pointer to iscsi cls conn 16762306a36Sopenharmony_ci * @transport_fd: EP handle(64 bit) 16862306a36Sopenharmony_ci * @is_leading: indicate if this is the session leading connection (MCS) 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * This function binds the TCP Conn with iSCSI Connection and Session. 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ciint beiscsi_conn_bind(struct iscsi_cls_session *cls_session, 17362306a36Sopenharmony_ci struct iscsi_cls_conn *cls_conn, 17462306a36Sopenharmony_ci u64 transport_fd, int is_leading) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct iscsi_conn *conn = cls_conn->dd_data; 17762306a36Sopenharmony_ci struct beiscsi_conn *beiscsi_conn = conn->dd_data; 17862306a36Sopenharmony_ci struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); 17962306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 18062306a36Sopenharmony_ci struct hwi_controller *phwi_ctrlr = phba->phwi_ctrlr; 18162306a36Sopenharmony_ci struct hwi_wrb_context *pwrb_context; 18262306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep; 18362306a36Sopenharmony_ci struct iscsi_endpoint *ep; 18462306a36Sopenharmony_ci uint16_t cri_index; 18562306a36Sopenharmony_ci int rc = 0; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci ep = iscsi_lookup_endpoint(transport_fd); 18862306a36Sopenharmony_ci if (!ep) 18962306a36Sopenharmony_ci return -EINVAL; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci beiscsi_ep = ep->dd_data; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) { 19462306a36Sopenharmony_ci rc = -EINVAL; 19562306a36Sopenharmony_ci goto put_ep; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (beiscsi_ep->phba != phba) { 19962306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 20062306a36Sopenharmony_ci "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n", 20162306a36Sopenharmony_ci beiscsi_ep->phba, phba); 20262306a36Sopenharmony_ci rc = -EEXIST; 20362306a36Sopenharmony_ci goto put_ep; 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); 20662306a36Sopenharmony_ci if (phba->conn_table[cri_index]) { 20762306a36Sopenharmony_ci if (beiscsi_conn != phba->conn_table[cri_index] || 20862306a36Sopenharmony_ci beiscsi_ep != phba->conn_table[cri_index]->ep) { 20962306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 21062306a36Sopenharmony_ci "BS_%d : conn_table not empty at %u: cid %u conn %p:%p\n", 21162306a36Sopenharmony_ci cri_index, 21262306a36Sopenharmony_ci beiscsi_ep->ep_cid, 21362306a36Sopenharmony_ci beiscsi_conn, 21462306a36Sopenharmony_ci phba->conn_table[cri_index]); 21562306a36Sopenharmony_ci rc = -EINVAL; 21662306a36Sopenharmony_ci goto put_ep; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; 22162306a36Sopenharmony_ci beiscsi_conn->ep = beiscsi_ep; 22262306a36Sopenharmony_ci beiscsi_ep->conn = beiscsi_conn; 22362306a36Sopenharmony_ci /** 22462306a36Sopenharmony_ci * Each connection is associated with a WRBQ kept in wrb_context. 22562306a36Sopenharmony_ci * Store doorbell offset for transmit path. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 22862306a36Sopenharmony_ci beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset; 22962306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 23062306a36Sopenharmony_ci "BS_%d : cid %d phba->conn_table[%u]=%p\n", 23162306a36Sopenharmony_ci beiscsi_ep->ep_cid, cri_index, beiscsi_conn); 23262306a36Sopenharmony_ci phba->conn_table[cri_index] = beiscsi_conn; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ciput_ep: 23562306a36Sopenharmony_ci iscsi_put_endpoint(ep); 23662306a36Sopenharmony_ci return rc; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci if (phba->ipv4_iface) 24262306a36Sopenharmony_ci return 0; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci phba->ipv4_iface = iscsi_create_iface(phba->shost, 24562306a36Sopenharmony_ci &beiscsi_iscsi_transport, 24662306a36Sopenharmony_ci ISCSI_IFACE_TYPE_IPV4, 24762306a36Sopenharmony_ci 0, 0); 24862306a36Sopenharmony_ci if (!phba->ipv4_iface) { 24962306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 25062306a36Sopenharmony_ci "BS_%d : Could not " 25162306a36Sopenharmony_ci "create default IPv4 address.\n"); 25262306a36Sopenharmony_ci return -ENODEV; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci return 0; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic int beiscsi_iface_create_ipv6(struct beiscsi_hba *phba) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci if (phba->ipv6_iface) 26162306a36Sopenharmony_ci return 0; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci phba->ipv6_iface = iscsi_create_iface(phba->shost, 26462306a36Sopenharmony_ci &beiscsi_iscsi_transport, 26562306a36Sopenharmony_ci ISCSI_IFACE_TYPE_IPV6, 26662306a36Sopenharmony_ci 0, 0); 26762306a36Sopenharmony_ci if (!phba->ipv6_iface) { 26862306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 26962306a36Sopenharmony_ci "BS_%d : Could not " 27062306a36Sopenharmony_ci "create default IPv6 address.\n"); 27162306a36Sopenharmony_ci return -ENODEV; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_civoid beiscsi_iface_create_default(struct beiscsi_hba *phba) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct be_cmd_get_if_info_resp *if_info; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) { 28262306a36Sopenharmony_ci beiscsi_iface_create_ipv4(phba); 28362306a36Sopenharmony_ci kfree(if_info); 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) { 28762306a36Sopenharmony_ci beiscsi_iface_create_ipv6(phba); 28862306a36Sopenharmony_ci kfree(if_info); 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_civoid beiscsi_iface_destroy_default(struct beiscsi_hba *phba) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci if (phba->ipv6_iface) { 29562306a36Sopenharmony_ci iscsi_destroy_iface(phba->ipv6_iface); 29662306a36Sopenharmony_ci phba->ipv6_iface = NULL; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci if (phba->ipv4_iface) { 29962306a36Sopenharmony_ci iscsi_destroy_iface(phba->ipv4_iface); 30062306a36Sopenharmony_ci phba->ipv4_iface = NULL; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci/** 30562306a36Sopenharmony_ci * beiscsi_iface_config_vlan()- Set the VLAN TAG 30662306a36Sopenharmony_ci * @shost: Scsi Host for the driver instance 30762306a36Sopenharmony_ci * @iface_param: Interface paramters 30862306a36Sopenharmony_ci * 30962306a36Sopenharmony_ci * Set the VLAN TAG for the adapter or disable 31062306a36Sopenharmony_ci * the VLAN config 31162306a36Sopenharmony_ci * 31262306a36Sopenharmony_ci * returns 31362306a36Sopenharmony_ci * Success: 0 31462306a36Sopenharmony_ci * Failure: Non-Zero Value 31562306a36Sopenharmony_ci **/ 31662306a36Sopenharmony_cistatic int 31762306a36Sopenharmony_cibeiscsi_iface_config_vlan(struct Scsi_Host *shost, 31862306a36Sopenharmony_ci struct iscsi_iface_param_info *iface_param) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 32162306a36Sopenharmony_ci int ret = -EPERM; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci switch (iface_param->param) { 32462306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 32562306a36Sopenharmony_ci ret = 0; 32662306a36Sopenharmony_ci if (iface_param->value[0] != ISCSI_VLAN_ENABLE) 32762306a36Sopenharmony_ci ret = beiscsi_if_set_vlan(phba, BEISCSI_VLAN_DISABLE); 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_TAG: 33062306a36Sopenharmony_ci ret = beiscsi_if_set_vlan(phba, 33162306a36Sopenharmony_ci *((uint16_t *)iface_param->value)); 33262306a36Sopenharmony_ci break; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci return ret; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic int 33962306a36Sopenharmony_cibeiscsi_iface_config_ipv4(struct Scsi_Host *shost, 34062306a36Sopenharmony_ci struct iscsi_iface_param_info *info, 34162306a36Sopenharmony_ci void *data, uint32_t dt_len) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 34462306a36Sopenharmony_ci u8 *ip = NULL, *subnet = NULL, *gw; 34562306a36Sopenharmony_ci struct nlattr *nla; 34662306a36Sopenharmony_ci int ret = -EPERM; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* Check the param */ 34962306a36Sopenharmony_ci switch (info->param) { 35062306a36Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 35162306a36Sopenharmony_ci if (info->value[0] == ISCSI_IFACE_ENABLE) 35262306a36Sopenharmony_ci ret = beiscsi_iface_create_ipv4(phba); 35362306a36Sopenharmony_ci else { 35462306a36Sopenharmony_ci iscsi_destroy_iface(phba->ipv4_iface); 35562306a36Sopenharmony_ci phba->ipv4_iface = NULL; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GW: 35962306a36Sopenharmony_ci gw = info->value; 36062306a36Sopenharmony_ci ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw); 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 36362306a36Sopenharmony_ci if (info->value[0] == ISCSI_BOOTPROTO_DHCP) 36462306a36Sopenharmony_ci ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4); 36562306a36Sopenharmony_ci else if (info->value[0] == ISCSI_BOOTPROTO_STATIC) 36662306a36Sopenharmony_ci /* release DHCP IP address */ 36762306a36Sopenharmony_ci ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, 36862306a36Sopenharmony_ci NULL, NULL); 36962306a36Sopenharmony_ci else 37062306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 37162306a36Sopenharmony_ci "BS_%d : Invalid BOOTPROTO: %d\n", 37262306a36Sopenharmony_ci info->value[0]); 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 37562306a36Sopenharmony_ci ip = info->value; 37662306a36Sopenharmony_ci nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET); 37762306a36Sopenharmony_ci if (nla) { 37862306a36Sopenharmony_ci info = nla_data(nla); 37962306a36Sopenharmony_ci subnet = info->value; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, 38262306a36Sopenharmony_ci ip, subnet); 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 38562306a36Sopenharmony_ci /* 38662306a36Sopenharmony_ci * OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP 38762306a36Sopenharmony_ci * and subnet both. Find IP to be applied for this subnet. 38862306a36Sopenharmony_ci */ 38962306a36Sopenharmony_ci subnet = info->value; 39062306a36Sopenharmony_ci nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR); 39162306a36Sopenharmony_ci if (nla) { 39262306a36Sopenharmony_ci info = nla_data(nla); 39362306a36Sopenharmony_ci ip = info->value; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, 39662306a36Sopenharmony_ci ip, subnet); 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci return ret; 40162306a36Sopenharmony_ci} 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic int 40462306a36Sopenharmony_cibeiscsi_iface_config_ipv6(struct Scsi_Host *shost, 40562306a36Sopenharmony_ci struct iscsi_iface_param_info *iface_param, 40662306a36Sopenharmony_ci void *data, uint32_t dt_len) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 40962306a36Sopenharmony_ci int ret = -EPERM; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci switch (iface_param->param) { 41262306a36Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 41362306a36Sopenharmony_ci if (iface_param->value[0] == ISCSI_IFACE_ENABLE) 41462306a36Sopenharmony_ci ret = beiscsi_iface_create_ipv6(phba); 41562306a36Sopenharmony_ci else { 41662306a36Sopenharmony_ci iscsi_destroy_iface(phba->ipv6_iface); 41762306a36Sopenharmony_ci phba->ipv6_iface = NULL; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 42162306a36Sopenharmony_ci ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6, 42262306a36Sopenharmony_ci iface_param->value, NULL); 42362306a36Sopenharmony_ci break; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci return ret; 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ciint beiscsi_iface_set_param(struct Scsi_Host *shost, 43062306a36Sopenharmony_ci void *data, uint32_t dt_len) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct iscsi_iface_param_info *iface_param = NULL; 43362306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 43462306a36Sopenharmony_ci struct nlattr *attrib; 43562306a36Sopenharmony_ci uint32_t rm_len = dt_len; 43662306a36Sopenharmony_ci int ret; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 43962306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 44062306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 44162306a36Sopenharmony_ci return -EBUSY; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci /* update interface_handle */ 44562306a36Sopenharmony_ci ret = beiscsi_if_get_handle(phba); 44662306a36Sopenharmony_ci if (ret) { 44762306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 44862306a36Sopenharmony_ci "BS_%d : Getting Interface Handle Failed\n"); 44962306a36Sopenharmony_ci return ret; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci nla_for_each_attr(attrib, data, dt_len, rm_len) { 45362306a36Sopenharmony_ci /* ignore nla_type as it is never used */ 45462306a36Sopenharmony_ci if (nla_len(attrib) < sizeof(*iface_param)) 45562306a36Sopenharmony_ci return -EINVAL; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci iface_param = nla_data(attrib); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (iface_param->param_type != ISCSI_NET_PARAM) 46062306a36Sopenharmony_ci continue; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* 46362306a36Sopenharmony_ci * BE2ISCSI only supports 1 interface 46462306a36Sopenharmony_ci */ 46562306a36Sopenharmony_ci if (iface_param->iface_num) { 46662306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 46762306a36Sopenharmony_ci "BS_%d : Invalid iface_num %d." 46862306a36Sopenharmony_ci "Only iface_num 0 is supported.\n", 46962306a36Sopenharmony_ci iface_param->iface_num); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci return -EINVAL; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 47562306a36Sopenharmony_ci "BS_%d : %s.0 set param %d", 47662306a36Sopenharmony_ci (iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ? 47762306a36Sopenharmony_ci "ipv4" : "ipv6", iface_param->param); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci ret = -EPERM; 48062306a36Sopenharmony_ci switch (iface_param->param) { 48162306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 48262306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_TAG: 48362306a36Sopenharmony_ci ret = beiscsi_iface_config_vlan(shost, iface_param); 48462306a36Sopenharmony_ci break; 48562306a36Sopenharmony_ci default: 48662306a36Sopenharmony_ci switch (iface_param->iface_type) { 48762306a36Sopenharmony_ci case ISCSI_IFACE_TYPE_IPV4: 48862306a36Sopenharmony_ci ret = beiscsi_iface_config_ipv4(shost, 48962306a36Sopenharmony_ci iface_param, 49062306a36Sopenharmony_ci data, dt_len); 49162306a36Sopenharmony_ci break; 49262306a36Sopenharmony_ci case ISCSI_IFACE_TYPE_IPV6: 49362306a36Sopenharmony_ci ret = beiscsi_iface_config_ipv6(shost, 49462306a36Sopenharmony_ci iface_param, 49562306a36Sopenharmony_ci data, dt_len); 49662306a36Sopenharmony_ci break; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if (ret == -EPERM) { 50162306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 50262306a36Sopenharmony_ci "BS_%d : %s.0 set param %d not permitted", 50362306a36Sopenharmony_ci (iface_param->iface_type == 50462306a36Sopenharmony_ci ISCSI_IFACE_TYPE_IPV4) ? "ipv4" : "ipv6", 50562306a36Sopenharmony_ci iface_param->param); 50662306a36Sopenharmony_ci ret = 0; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci if (ret) 50962306a36Sopenharmony_ci break; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci return ret; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cistatic int __beiscsi_iface_get_param(struct beiscsi_hba *phba, 51662306a36Sopenharmony_ci struct iscsi_iface *iface, 51762306a36Sopenharmony_ci int param, char *buf) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci struct be_cmd_get_if_info_resp *if_info; 52062306a36Sopenharmony_ci int len, ip_type = BEISCSI_IP_TYPE_V4; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) 52362306a36Sopenharmony_ci ip_type = BEISCSI_IP_TYPE_V6; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci len = beiscsi_if_get_info(phba, ip_type, &if_info); 52662306a36Sopenharmony_ci if (len) 52762306a36Sopenharmony_ci return len; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci switch (param) { 53062306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 53162306a36Sopenharmony_ci len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr); 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 53462306a36Sopenharmony_ci len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr); 53562306a36Sopenharmony_ci break; 53662306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 53762306a36Sopenharmony_ci if (!if_info->dhcp_state) 53862306a36Sopenharmony_ci len = sprintf(buf, "static\n"); 53962306a36Sopenharmony_ci else 54062306a36Sopenharmony_ci len = sprintf(buf, "dhcp\n"); 54162306a36Sopenharmony_ci break; 54262306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 54362306a36Sopenharmony_ci len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask); 54462306a36Sopenharmony_ci break; 54562306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 54662306a36Sopenharmony_ci len = sprintf(buf, "%s\n", 54762306a36Sopenharmony_ci (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ? 54862306a36Sopenharmony_ci "disable" : "enable"); 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ID: 55162306a36Sopenharmony_ci if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) 55262306a36Sopenharmony_ci len = -EINVAL; 55362306a36Sopenharmony_ci else 55462306a36Sopenharmony_ci len = sprintf(buf, "%d\n", 55562306a36Sopenharmony_ci (if_info->vlan_priority & 55662306a36Sopenharmony_ci ISCSI_MAX_VLAN_ID)); 55762306a36Sopenharmony_ci break; 55862306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_PRIORITY: 55962306a36Sopenharmony_ci if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) 56062306a36Sopenharmony_ci len = -EINVAL; 56162306a36Sopenharmony_ci else 56262306a36Sopenharmony_ci len = sprintf(buf, "%d\n", 56362306a36Sopenharmony_ci ((if_info->vlan_priority >> 13) & 56462306a36Sopenharmony_ci ISCSI_MAX_VLAN_PRIORITY)); 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci default: 56762306a36Sopenharmony_ci WARN_ON(1); 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci kfree(if_info); 57162306a36Sopenharmony_ci return len; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ciint beiscsi_iface_get_param(struct iscsi_iface *iface, 57562306a36Sopenharmony_ci enum iscsi_param_type param_type, 57662306a36Sopenharmony_ci int param, char *buf) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct Scsi_Host *shost = iscsi_iface_to_shost(iface); 57962306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 58062306a36Sopenharmony_ci struct be_cmd_get_def_gateway_resp gateway; 58162306a36Sopenharmony_ci int len = -EPERM; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (param_type != ISCSI_NET_PARAM) 58462306a36Sopenharmony_ci return 0; 58562306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 58662306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 58762306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 58862306a36Sopenharmony_ci return -EBUSY; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci switch (param) { 59262306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 59362306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 59462306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 59562306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 59662306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 59762306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ID: 59862306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_PRIORITY: 59962306a36Sopenharmony_ci len = __beiscsi_iface_get_param(phba, iface, param, buf); 60062306a36Sopenharmony_ci break; 60162306a36Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 60262306a36Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 60362306a36Sopenharmony_ci len = sprintf(buf, "%s\n", 60462306a36Sopenharmony_ci phba->ipv4_iface ? "enable" : "disable"); 60562306a36Sopenharmony_ci else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) 60662306a36Sopenharmony_ci len = sprintf(buf, "%s\n", 60762306a36Sopenharmony_ci phba->ipv6_iface ? "enable" : "disable"); 60862306a36Sopenharmony_ci break; 60962306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GW: 61062306a36Sopenharmony_ci memset(&gateway, 0, sizeof(gateway)); 61162306a36Sopenharmony_ci len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway); 61262306a36Sopenharmony_ci if (!len) 61362306a36Sopenharmony_ci len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr); 61462306a36Sopenharmony_ci break; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci return len; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci/** 62162306a36Sopenharmony_ci * beiscsi_ep_get_param - get the iscsi parameter 62262306a36Sopenharmony_ci * @ep: pointer to iscsi ep 62362306a36Sopenharmony_ci * @param: parameter type identifier 62462306a36Sopenharmony_ci * @buf: buffer pointer 62562306a36Sopenharmony_ci * 62662306a36Sopenharmony_ci * returns iscsi parameter 62762306a36Sopenharmony_ci */ 62862306a36Sopenharmony_ciint beiscsi_ep_get_param(struct iscsi_endpoint *ep, 62962306a36Sopenharmony_ci enum iscsi_param param, char *buf) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 63262306a36Sopenharmony_ci int len; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci beiscsi_log(beiscsi_ep->phba, KERN_INFO, 63562306a36Sopenharmony_ci BEISCSI_LOG_CONFIG, 63662306a36Sopenharmony_ci "BS_%d : In beiscsi_ep_get_param," 63762306a36Sopenharmony_ci " param= %d\n", param); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci switch (param) { 64062306a36Sopenharmony_ci case ISCSI_PARAM_CONN_PORT: 64162306a36Sopenharmony_ci len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); 64262306a36Sopenharmony_ci break; 64362306a36Sopenharmony_ci case ISCSI_PARAM_CONN_ADDRESS: 64462306a36Sopenharmony_ci if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4) 64562306a36Sopenharmony_ci len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); 64662306a36Sopenharmony_ci else 64762306a36Sopenharmony_ci len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); 64862306a36Sopenharmony_ci break; 64962306a36Sopenharmony_ci default: 65062306a36Sopenharmony_ci len = -EPERM; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci return len; 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ciint beiscsi_set_param(struct iscsi_cls_conn *cls_conn, 65662306a36Sopenharmony_ci enum iscsi_param param, char *buf, int buflen) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct iscsi_conn *conn = cls_conn->dd_data; 65962306a36Sopenharmony_ci struct iscsi_session *session = conn->session; 66062306a36Sopenharmony_ci struct beiscsi_hba *phba = NULL; 66162306a36Sopenharmony_ci int ret; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 66462306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 66562306a36Sopenharmony_ci "BS_%d : In beiscsi_conn_set_param," 66662306a36Sopenharmony_ci " param= %d\n", param); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci ret = iscsi_set_param(cls_conn, param, buf, buflen); 66962306a36Sopenharmony_ci if (ret) 67062306a36Sopenharmony_ci return ret; 67162306a36Sopenharmony_ci /* 67262306a36Sopenharmony_ci * If userspace tried to set the value to higher than we can 67362306a36Sopenharmony_ci * support override here. 67462306a36Sopenharmony_ci */ 67562306a36Sopenharmony_ci switch (param) { 67662306a36Sopenharmony_ci case ISCSI_PARAM_FIRST_BURST: 67762306a36Sopenharmony_ci if (session->first_burst > 8192) 67862306a36Sopenharmony_ci session->first_burst = 8192; 67962306a36Sopenharmony_ci break; 68062306a36Sopenharmony_ci case ISCSI_PARAM_MAX_RECV_DLENGTH: 68162306a36Sopenharmony_ci if (conn->max_recv_dlength > 65536) 68262306a36Sopenharmony_ci conn->max_recv_dlength = 65536; 68362306a36Sopenharmony_ci break; 68462306a36Sopenharmony_ci case ISCSI_PARAM_MAX_BURST: 68562306a36Sopenharmony_ci if (session->max_burst > 262144) 68662306a36Sopenharmony_ci session->max_burst = 262144; 68762306a36Sopenharmony_ci break; 68862306a36Sopenharmony_ci case ISCSI_PARAM_MAX_XMIT_DLENGTH: 68962306a36Sopenharmony_ci if (conn->max_xmit_dlength > 65536) 69062306a36Sopenharmony_ci conn->max_xmit_dlength = 65536; 69162306a36Sopenharmony_ci fallthrough; 69262306a36Sopenharmony_ci default: 69362306a36Sopenharmony_ci return 0; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci return 0; 69762306a36Sopenharmony_ci} 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci/** 70062306a36Sopenharmony_ci * beiscsi_get_port_state - Get the Port State 70162306a36Sopenharmony_ci * @shost : pointer to scsi_host structure 70262306a36Sopenharmony_ci * 70362306a36Sopenharmony_ci */ 70462306a36Sopenharmony_cistatic void beiscsi_get_port_state(struct Scsi_Host *shost) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 70762306a36Sopenharmony_ci struct iscsi_cls_host *ihost = shost->shost_data; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci ihost->port_state = test_bit(BEISCSI_HBA_LINK_UP, &phba->state) ? 71062306a36Sopenharmony_ci ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci/** 71462306a36Sopenharmony_ci * beiscsi_get_port_speed - Get the Port Speed from Adapter 71562306a36Sopenharmony_ci * @shost : pointer to scsi_host structure 71662306a36Sopenharmony_ci * 71762306a36Sopenharmony_ci */ 71862306a36Sopenharmony_cistatic void beiscsi_get_port_speed(struct Scsi_Host *shost) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 72162306a36Sopenharmony_ci struct iscsi_cls_host *ihost = shost->shost_data; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci switch (phba->port_speed) { 72462306a36Sopenharmony_ci case BE2ISCSI_LINK_SPEED_10MBPS: 72562306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_10MBPS; 72662306a36Sopenharmony_ci break; 72762306a36Sopenharmony_ci case BE2ISCSI_LINK_SPEED_100MBPS: 72862306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_100MBPS; 72962306a36Sopenharmony_ci break; 73062306a36Sopenharmony_ci case BE2ISCSI_LINK_SPEED_1GBPS: 73162306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_1GBPS; 73262306a36Sopenharmony_ci break; 73362306a36Sopenharmony_ci case BE2ISCSI_LINK_SPEED_10GBPS: 73462306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_10GBPS; 73562306a36Sopenharmony_ci break; 73662306a36Sopenharmony_ci case BE2ISCSI_LINK_SPEED_25GBPS: 73762306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_25GBPS; 73862306a36Sopenharmony_ci break; 73962306a36Sopenharmony_ci case BE2ISCSI_LINK_SPEED_40GBPS: 74062306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_40GBPS; 74162306a36Sopenharmony_ci break; 74262306a36Sopenharmony_ci default: 74362306a36Sopenharmony_ci ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci/** 74862306a36Sopenharmony_ci * beiscsi_get_host_param - get the iscsi parameter 74962306a36Sopenharmony_ci * @shost: pointer to scsi_host structure 75062306a36Sopenharmony_ci * @param: parameter type identifier 75162306a36Sopenharmony_ci * @buf: buffer pointer 75262306a36Sopenharmony_ci * 75362306a36Sopenharmony_ci */ 75462306a36Sopenharmony_ciint beiscsi_get_host_param(struct Scsi_Host *shost, 75562306a36Sopenharmony_ci enum iscsi_host_param param, char *buf) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci struct beiscsi_hba *phba = iscsi_host_priv(shost); 75862306a36Sopenharmony_ci int status = 0; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 76162306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 76262306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 76362306a36Sopenharmony_ci return 0; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 76662306a36Sopenharmony_ci "BS_%d : In beiscsi_get_host_param, param = %d\n", param); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci switch (param) { 76962306a36Sopenharmony_ci case ISCSI_HOST_PARAM_HWADDRESS: 77062306a36Sopenharmony_ci status = beiscsi_get_macaddr(buf, phba); 77162306a36Sopenharmony_ci if (status < 0) { 77262306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 77362306a36Sopenharmony_ci "BS_%d : beiscsi_get_macaddr Failed\n"); 77462306a36Sopenharmony_ci return 0; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci break; 77762306a36Sopenharmony_ci case ISCSI_HOST_PARAM_INITIATOR_NAME: 77862306a36Sopenharmony_ci /* try fetching user configured name first */ 77962306a36Sopenharmony_ci status = beiscsi_get_initiator_name(phba, buf, true); 78062306a36Sopenharmony_ci if (status < 0) { 78162306a36Sopenharmony_ci status = beiscsi_get_initiator_name(phba, buf, false); 78262306a36Sopenharmony_ci if (status < 0) { 78362306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 78462306a36Sopenharmony_ci "BS_%d : Retrieving Initiator Name Failed\n"); 78562306a36Sopenharmony_ci status = 0; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci break; 78962306a36Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_STATE: 79062306a36Sopenharmony_ci beiscsi_get_port_state(shost); 79162306a36Sopenharmony_ci status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost)); 79262306a36Sopenharmony_ci break; 79362306a36Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_SPEED: 79462306a36Sopenharmony_ci beiscsi_get_port_speed(shost); 79562306a36Sopenharmony_ci status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost)); 79662306a36Sopenharmony_ci break; 79762306a36Sopenharmony_ci default: 79862306a36Sopenharmony_ci return iscsi_host_get_param(shost, param, buf); 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci return status; 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ciint beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct be_cmd_get_nic_conf_resp resp; 80662306a36Sopenharmony_ci int rc; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci if (phba->mac_addr_set) 80962306a36Sopenharmony_ci return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci memset(&resp, 0, sizeof(resp)); 81262306a36Sopenharmony_ci rc = mgmt_get_nic_conf(phba, &resp); 81362306a36Sopenharmony_ci if (rc) 81462306a36Sopenharmony_ci return rc; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci phba->mac_addr_set = true; 81762306a36Sopenharmony_ci memcpy(phba->mac_address, resp.mac_address, ETH_ALEN); 81862306a36Sopenharmony_ci return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci/** 82262306a36Sopenharmony_ci * beiscsi_conn_get_stats - get the iscsi stats 82362306a36Sopenharmony_ci * @cls_conn: pointer to iscsi cls conn 82462306a36Sopenharmony_ci * @stats: pointer to iscsi_stats structure 82562306a36Sopenharmony_ci * 82662306a36Sopenharmony_ci * returns iscsi stats 82762306a36Sopenharmony_ci */ 82862306a36Sopenharmony_civoid beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, 82962306a36Sopenharmony_ci struct iscsi_stats *stats) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci struct iscsi_conn *conn = cls_conn->dd_data; 83262306a36Sopenharmony_ci struct beiscsi_hba *phba = NULL; 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 83562306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 83662306a36Sopenharmony_ci "BS_%d : In beiscsi_conn_get_stats\n"); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci stats->txdata_octets = conn->txdata_octets; 83962306a36Sopenharmony_ci stats->rxdata_octets = conn->rxdata_octets; 84062306a36Sopenharmony_ci stats->dataout_pdus = conn->dataout_pdus_cnt; 84162306a36Sopenharmony_ci stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; 84262306a36Sopenharmony_ci stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; 84362306a36Sopenharmony_ci stats->datain_pdus = conn->datain_pdus_cnt; 84462306a36Sopenharmony_ci stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; 84562306a36Sopenharmony_ci stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; 84662306a36Sopenharmony_ci stats->r2t_pdus = conn->r2t_pdus_cnt; 84762306a36Sopenharmony_ci stats->digest_err = 0; 84862306a36Sopenharmony_ci stats->timeout_err = 0; 84962306a36Sopenharmony_ci stats->custom_length = 1; 85062306a36Sopenharmony_ci strcpy(stats->custom[0].desc, "eh_abort_cnt"); 85162306a36Sopenharmony_ci stats->custom[0].value = conn->eh_abort_cnt; 85262306a36Sopenharmony_ci} 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci/** 85562306a36Sopenharmony_ci * beiscsi_set_params_for_offld - get the parameters for offload 85662306a36Sopenharmony_ci * @beiscsi_conn: pointer to beiscsi_conn 85762306a36Sopenharmony_ci * @params: pointer to offload_params structure 85862306a36Sopenharmony_ci */ 85962306a36Sopenharmony_cistatic void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, 86062306a36Sopenharmony_ci struct beiscsi_offload_params *params) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci struct iscsi_conn *conn = beiscsi_conn->conn; 86362306a36Sopenharmony_ci struct iscsi_session *session = conn->session; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length, 86662306a36Sopenharmony_ci params, session->max_burst); 86762306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, 86862306a36Sopenharmony_ci max_send_data_segment_length, params, 86962306a36Sopenharmony_ci conn->max_xmit_dlength); 87062306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length, 87162306a36Sopenharmony_ci params, session->first_burst); 87262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params, 87362306a36Sopenharmony_ci session->erl); 87462306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params, 87562306a36Sopenharmony_ci conn->datadgst_en); 87662306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params, 87762306a36Sopenharmony_ci conn->hdrdgst_en); 87862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params, 87962306a36Sopenharmony_ci session->initial_r2t_en); 88062306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params, 88162306a36Sopenharmony_ci session->imm_data_en); 88262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, 88362306a36Sopenharmony_ci data_seq_inorder, params, 88462306a36Sopenharmony_ci session->dataseq_inorder_en); 88562306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, 88662306a36Sopenharmony_ci pdu_seq_inorder, params, 88762306a36Sopenharmony_ci session->pdu_inorder_en); 88862306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params, 88962306a36Sopenharmony_ci session->max_r2t); 89062306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, 89162306a36Sopenharmony_ci (conn->exp_statsn - 1)); 89262306a36Sopenharmony_ci AMAP_SET_BITS(struct amap_beiscsi_offload_params, 89362306a36Sopenharmony_ci max_recv_data_segment_length, params, 89462306a36Sopenharmony_ci conn->max_recv_dlength); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci/** 89962306a36Sopenharmony_ci * beiscsi_conn_start - offload of session to chip 90062306a36Sopenharmony_ci * @cls_conn: pointer to beiscsi_conn 90162306a36Sopenharmony_ci */ 90262306a36Sopenharmony_ciint beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci struct iscsi_conn *conn = cls_conn->dd_data; 90562306a36Sopenharmony_ci struct beiscsi_conn *beiscsi_conn = conn->dd_data; 90662306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep; 90762306a36Sopenharmony_ci struct beiscsi_offload_params params; 90862306a36Sopenharmony_ci struct beiscsi_hba *phba; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 91362306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 91462306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 91562306a36Sopenharmony_ci return -EBUSY; 91662306a36Sopenharmony_ci } 91762306a36Sopenharmony_ci beiscsi_log(beiscsi_conn->phba, KERN_INFO, BEISCSI_LOG_CONFIG, 91862306a36Sopenharmony_ci "BS_%d : In beiscsi_conn_start\n"); 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); 92162306a36Sopenharmony_ci beiscsi_ep = beiscsi_conn->ep; 92262306a36Sopenharmony_ci if (!beiscsi_ep) 92362306a36Sopenharmony_ci beiscsi_log(beiscsi_conn->phba, KERN_ERR, 92462306a36Sopenharmony_ci BEISCSI_LOG_CONFIG, 92562306a36Sopenharmony_ci "BS_%d : In beiscsi_conn_start , no beiscsi_ep\n"); 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci beiscsi_conn->login_in_progress = 0; 92862306a36Sopenharmony_ci beiscsi_set_params_for_offld(beiscsi_conn, ¶ms); 92962306a36Sopenharmony_ci beiscsi_offload_connection(beiscsi_conn, ¶ms); 93062306a36Sopenharmony_ci iscsi_conn_start(cls_conn); 93162306a36Sopenharmony_ci return 0; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci/** 93562306a36Sopenharmony_ci * beiscsi_get_cid - Allocate a cid 93662306a36Sopenharmony_ci * @phba: The phba instance 93762306a36Sopenharmony_ci */ 93862306a36Sopenharmony_cistatic int beiscsi_get_cid(struct beiscsi_hba *phba) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1; 94162306a36Sopenharmony_ci unsigned short cid, cid_from_ulp; 94262306a36Sopenharmony_ci struct ulp_cid_info *cid_info; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* Find the ULP which has more CID available */ 94562306a36Sopenharmony_ci cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ? 94662306a36Sopenharmony_ci BEISCSI_ULP0_AVLBL_CID(phba) : 0; 94762306a36Sopenharmony_ci cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ? 94862306a36Sopenharmony_ci BEISCSI_ULP1_AVLBL_CID(phba) : 0; 94962306a36Sopenharmony_ci cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ? 95062306a36Sopenharmony_ci BEISCSI_ULP0 : BEISCSI_ULP1; 95162306a36Sopenharmony_ci /** 95262306a36Sopenharmony_ci * If iSCSI protocol is loaded only on ULP 0, and when cid_avlbl_ulp 95362306a36Sopenharmony_ci * is ZERO for both, ULP 1 is returned. 95462306a36Sopenharmony_ci * Check if ULP is loaded before getting new CID. 95562306a36Sopenharmony_ci */ 95662306a36Sopenharmony_ci if (!test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) 95762306a36Sopenharmony_ci return BE_INVALID_CID; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci cid_info = phba->cid_array_info[cid_from_ulp]; 96062306a36Sopenharmony_ci cid = cid_info->cid_array[cid_info->cid_alloc]; 96162306a36Sopenharmony_ci if (!cid_info->avlbl_cids || cid == BE_INVALID_CID) { 96262306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 96362306a36Sopenharmony_ci "BS_%d : failed to get cid: available %u:%u\n", 96462306a36Sopenharmony_ci cid_info->avlbl_cids, cid_info->cid_free); 96562306a36Sopenharmony_ci return BE_INVALID_CID; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci /* empty the slot */ 96862306a36Sopenharmony_ci cid_info->cid_array[cid_info->cid_alloc++] = BE_INVALID_CID; 96962306a36Sopenharmony_ci if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(phba, cid_from_ulp)) 97062306a36Sopenharmony_ci cid_info->cid_alloc = 0; 97162306a36Sopenharmony_ci cid_info->avlbl_cids--; 97262306a36Sopenharmony_ci return cid; 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci/** 97662306a36Sopenharmony_ci * beiscsi_put_cid - Free the cid 97762306a36Sopenharmony_ci * @phba: The phba for which the cid is being freed 97862306a36Sopenharmony_ci * @cid: The cid to free 97962306a36Sopenharmony_ci */ 98062306a36Sopenharmony_cistatic void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) 98162306a36Sopenharmony_ci{ 98262306a36Sopenharmony_ci uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); 98362306a36Sopenharmony_ci struct hwi_wrb_context *pwrb_context; 98462306a36Sopenharmony_ci struct hwi_controller *phwi_ctrlr; 98562306a36Sopenharmony_ci struct ulp_cid_info *cid_info; 98662306a36Sopenharmony_ci uint16_t cid_post_ulp; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci phwi_ctrlr = phba->phwi_ctrlr; 98962306a36Sopenharmony_ci pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 99062306a36Sopenharmony_ci cid_post_ulp = pwrb_context->ulp_num; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci cid_info = phba->cid_array_info[cid_post_ulp]; 99362306a36Sopenharmony_ci /* fill only in empty slot */ 99462306a36Sopenharmony_ci if (cid_info->cid_array[cid_info->cid_free] != BE_INVALID_CID) { 99562306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 99662306a36Sopenharmony_ci "BS_%d : failed to put cid %u: available %u:%u\n", 99762306a36Sopenharmony_ci cid, cid_info->avlbl_cids, cid_info->cid_free); 99862306a36Sopenharmony_ci return; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci cid_info->cid_array[cid_info->cid_free++] = cid; 100162306a36Sopenharmony_ci if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp)) 100262306a36Sopenharmony_ci cid_info->cid_free = 0; 100362306a36Sopenharmony_ci cid_info->avlbl_cids++; 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci/** 100762306a36Sopenharmony_ci * beiscsi_free_ep - free endpoint 100862306a36Sopenharmony_ci * @beiscsi_ep: pointer to device endpoint struct 100962306a36Sopenharmony_ci */ 101062306a36Sopenharmony_cistatic void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) 101162306a36Sopenharmony_ci{ 101262306a36Sopenharmony_ci struct beiscsi_hba *phba = beiscsi_ep->phba; 101362306a36Sopenharmony_ci struct beiscsi_conn *beiscsi_conn; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci beiscsi_put_cid(phba, beiscsi_ep->ep_cid); 101662306a36Sopenharmony_ci beiscsi_ep->phba = NULL; 101762306a36Sopenharmony_ci /* clear this to track freeing in beiscsi_ep_disconnect */ 101862306a36Sopenharmony_ci phba->ep_array[BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid)] = NULL; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci /** 102162306a36Sopenharmony_ci * Check if any connection resource allocated by driver 102262306a36Sopenharmony_ci * is to be freed.This case occurs when target redirection 102362306a36Sopenharmony_ci * or connection retry is done. 102462306a36Sopenharmony_ci **/ 102562306a36Sopenharmony_ci if (!beiscsi_ep->conn) 102662306a36Sopenharmony_ci return; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci beiscsi_conn = beiscsi_ep->conn; 102962306a36Sopenharmony_ci /** 103062306a36Sopenharmony_ci * Break ep->conn link here so that completions after 103162306a36Sopenharmony_ci * this are ignored. 103262306a36Sopenharmony_ci */ 103362306a36Sopenharmony_ci beiscsi_ep->conn = NULL; 103462306a36Sopenharmony_ci if (beiscsi_conn->login_in_progress) { 103562306a36Sopenharmony_ci beiscsi_free_mgmt_task_handles(beiscsi_conn, 103662306a36Sopenharmony_ci beiscsi_conn->task); 103762306a36Sopenharmony_ci beiscsi_conn->login_in_progress = 0; 103862306a36Sopenharmony_ci } 103962306a36Sopenharmony_ci} 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci/** 104262306a36Sopenharmony_ci * beiscsi_open_conn - Ask FW to open a TCP connection 104362306a36Sopenharmony_ci * @ep: pointer to device endpoint struct 104462306a36Sopenharmony_ci * @src_addr: The source IP address 104562306a36Sopenharmony_ci * @dst_addr: The Destination IP address 104662306a36Sopenharmony_ci * @non_blocking: blocking or non-blocking call 104762306a36Sopenharmony_ci * 104862306a36Sopenharmony_ci * Asks the FW to open a TCP connection 104962306a36Sopenharmony_ci */ 105062306a36Sopenharmony_cistatic int beiscsi_open_conn(struct iscsi_endpoint *ep, 105162306a36Sopenharmony_ci struct sockaddr *src_addr, 105262306a36Sopenharmony_ci struct sockaddr *dst_addr, int non_blocking) 105362306a36Sopenharmony_ci{ 105462306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 105562306a36Sopenharmony_ci struct beiscsi_hba *phba = beiscsi_ep->phba; 105662306a36Sopenharmony_ci struct tcp_connect_and_offload_out *ptcpcnct_out; 105762306a36Sopenharmony_ci struct be_dma_mem nonemb_cmd; 105862306a36Sopenharmony_ci unsigned int tag, req_memsize; 105962306a36Sopenharmony_ci int ret = -ENOMEM; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 106262306a36Sopenharmony_ci "BS_%d : In beiscsi_open_conn\n"); 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci beiscsi_ep->ep_cid = beiscsi_get_cid(phba); 106562306a36Sopenharmony_ci if (beiscsi_ep->ep_cid == BE_INVALID_CID) { 106662306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 106762306a36Sopenharmony_ci "BS_%d : No free cid available\n"); 106862306a36Sopenharmony_ci return ret; 106962306a36Sopenharmony_ci } 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 107262306a36Sopenharmony_ci "BS_%d : In beiscsi_open_conn, ep_cid=%d\n", 107362306a36Sopenharmony_ci beiscsi_ep->ep_cid); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci phba->ep_array[BE_GET_CRI_FROM_CID 107662306a36Sopenharmony_ci (beiscsi_ep->ep_cid)] = ep; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci beiscsi_ep->cid_vld = 0; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci if (is_chip_be2_be3r(phba)) 108162306a36Sopenharmony_ci req_memsize = sizeof(struct tcp_connect_and_offload_in); 108262306a36Sopenharmony_ci else 108362306a36Sopenharmony_ci req_memsize = sizeof(struct tcp_connect_and_offload_in_v1); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev, 108662306a36Sopenharmony_ci req_memsize, 108762306a36Sopenharmony_ci &nonemb_cmd.dma, GFP_KERNEL); 108862306a36Sopenharmony_ci if (nonemb_cmd.va == NULL) { 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 109162306a36Sopenharmony_ci "BS_%d : Failed to allocate memory for" 109262306a36Sopenharmony_ci " mgmt_open_connection\n"); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci beiscsi_free_ep(beiscsi_ep); 109562306a36Sopenharmony_ci return -ENOMEM; 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci nonemb_cmd.size = req_memsize; 109862306a36Sopenharmony_ci memset(nonemb_cmd.va, 0, nonemb_cmd.size); 109962306a36Sopenharmony_ci tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); 110062306a36Sopenharmony_ci if (!tag) { 110162306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 110262306a36Sopenharmony_ci "BS_%d : mgmt_open_connection Failed for cid=%d\n", 110362306a36Sopenharmony_ci beiscsi_ep->ep_cid); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size, 110662306a36Sopenharmony_ci nonemb_cmd.va, nonemb_cmd.dma); 110762306a36Sopenharmony_ci beiscsi_free_ep(beiscsi_ep); 110862306a36Sopenharmony_ci return -EAGAIN; 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); 111262306a36Sopenharmony_ci if (ret) { 111362306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, 111462306a36Sopenharmony_ci BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 111562306a36Sopenharmony_ci "BS_%d : mgmt_open_connection Failed"); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci if (ret != -EBUSY) 111862306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, 111962306a36Sopenharmony_ci nonemb_cmd.size, nonemb_cmd.va, 112062306a36Sopenharmony_ci nonemb_cmd.dma); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci beiscsi_free_ep(beiscsi_ep); 112362306a36Sopenharmony_ci return ret; 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va; 112762306a36Sopenharmony_ci beiscsi_ep = ep->dd_data; 112862306a36Sopenharmony_ci beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; 112962306a36Sopenharmony_ci beiscsi_ep->cid_vld = 1; 113062306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 113162306a36Sopenharmony_ci "BS_%d : mgmt_open_connection Success\n"); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size, 113462306a36Sopenharmony_ci nonemb_cmd.va, nonemb_cmd.dma); 113562306a36Sopenharmony_ci return 0; 113662306a36Sopenharmony_ci} 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci/** 113962306a36Sopenharmony_ci * beiscsi_ep_connect - Ask chip to create TCP Conn 114062306a36Sopenharmony_ci * @shost: Pointer to scsi_host structure 114162306a36Sopenharmony_ci * @dst_addr: The IP address of Target 114262306a36Sopenharmony_ci * @non_blocking: blocking or non-blocking call 114362306a36Sopenharmony_ci * 114462306a36Sopenharmony_ci * This routines first asks chip to create a connection and then allocates an EP 114562306a36Sopenharmony_ci */ 114662306a36Sopenharmony_cistruct iscsi_endpoint * 114762306a36Sopenharmony_cibeiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, 114862306a36Sopenharmony_ci int non_blocking) 114962306a36Sopenharmony_ci{ 115062306a36Sopenharmony_ci struct beiscsi_hba *phba; 115162306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep; 115262306a36Sopenharmony_ci struct iscsi_endpoint *ep; 115362306a36Sopenharmony_ci int ret; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci if (!shost) { 115662306a36Sopenharmony_ci ret = -ENXIO; 115762306a36Sopenharmony_ci pr_err("beiscsi_ep_connect shost is NULL\n"); 115862306a36Sopenharmony_ci return ERR_PTR(ret); 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci phba = iscsi_host_priv(shost); 116262306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 116362306a36Sopenharmony_ci ret = -EIO; 116462306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 116562306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 116662306a36Sopenharmony_ci return ERR_PTR(ret); 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ci if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) { 116962306a36Sopenharmony_ci ret = -EBUSY; 117062306a36Sopenharmony_ci beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 117162306a36Sopenharmony_ci "BS_%d : The Adapter Port state is Down!!!\n"); 117262306a36Sopenharmony_ci return ERR_PTR(ret); 117362306a36Sopenharmony_ci } 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); 117662306a36Sopenharmony_ci if (!ep) { 117762306a36Sopenharmony_ci ret = -ENOMEM; 117862306a36Sopenharmony_ci return ERR_PTR(ret); 117962306a36Sopenharmony_ci } 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci beiscsi_ep = ep->dd_data; 118262306a36Sopenharmony_ci beiscsi_ep->phba = phba; 118362306a36Sopenharmony_ci beiscsi_ep->openiscsi_ep = ep; 118462306a36Sopenharmony_ci ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking); 118562306a36Sopenharmony_ci if (ret) { 118662306a36Sopenharmony_ci beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 118762306a36Sopenharmony_ci "BS_%d : Failed in beiscsi_open_conn\n"); 118862306a36Sopenharmony_ci goto free_ep; 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci return ep; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cifree_ep: 119462306a36Sopenharmony_ci iscsi_destroy_endpoint(ep); 119562306a36Sopenharmony_ci return ERR_PTR(ret); 119662306a36Sopenharmony_ci} 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci/** 119962306a36Sopenharmony_ci * beiscsi_ep_poll - Poll to see if connection is established 120062306a36Sopenharmony_ci * @ep: endpoint to be used 120162306a36Sopenharmony_ci * @timeout_ms: timeout specified in millisecs 120262306a36Sopenharmony_ci * 120362306a36Sopenharmony_ci * Poll to see if TCP connection established 120462306a36Sopenharmony_ci */ 120562306a36Sopenharmony_ciint beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) 120662306a36Sopenharmony_ci{ 120762306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci beiscsi_log(beiscsi_ep->phba, KERN_INFO, BEISCSI_LOG_CONFIG, 121062306a36Sopenharmony_ci "BS_%d : In beiscsi_ep_poll\n"); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci if (beiscsi_ep->cid_vld == 1) 121362306a36Sopenharmony_ci return 1; 121462306a36Sopenharmony_ci else 121562306a36Sopenharmony_ci return 0; 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci/** 121962306a36Sopenharmony_ci * beiscsi_flush_cq()- Flush the CQ created. 122062306a36Sopenharmony_ci * @phba: ptr device priv structure. 122162306a36Sopenharmony_ci * 122262306a36Sopenharmony_ci * Before the connection resource are freed flush 122362306a36Sopenharmony_ci * all the CQ enteries 122462306a36Sopenharmony_ci **/ 122562306a36Sopenharmony_cistatic void beiscsi_flush_cq(struct beiscsi_hba *phba) 122662306a36Sopenharmony_ci{ 122762306a36Sopenharmony_ci uint16_t i; 122862306a36Sopenharmony_ci struct be_eq_obj *pbe_eq; 122962306a36Sopenharmony_ci struct hwi_controller *phwi_ctrlr; 123062306a36Sopenharmony_ci struct hwi_context_memory *phwi_context; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci phwi_ctrlr = phba->phwi_ctrlr; 123362306a36Sopenharmony_ci phwi_context = phwi_ctrlr->phwi_ctxt; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci for (i = 0; i < phba->num_cpus; i++) { 123662306a36Sopenharmony_ci pbe_eq = &phwi_context->be_eq[i]; 123762306a36Sopenharmony_ci irq_poll_disable(&pbe_eq->iopoll); 123862306a36Sopenharmony_ci beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); 123962306a36Sopenharmony_ci irq_poll_enable(&pbe_eq->iopoll); 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci/** 124462306a36Sopenharmony_ci * beiscsi_conn_close - Invalidate and upload connection 124562306a36Sopenharmony_ci * @beiscsi_ep: pointer to device endpoint struct 124662306a36Sopenharmony_ci * 124762306a36Sopenharmony_ci * Returns 0 on success, -1 on failure. 124862306a36Sopenharmony_ci */ 124962306a36Sopenharmony_cistatic int beiscsi_conn_close(struct beiscsi_endpoint *beiscsi_ep) 125062306a36Sopenharmony_ci{ 125162306a36Sopenharmony_ci struct beiscsi_hba *phba = beiscsi_ep->phba; 125262306a36Sopenharmony_ci unsigned int tag, attempts; 125362306a36Sopenharmony_ci int ret; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci /** 125662306a36Sopenharmony_ci * Without successfully invalidating and uploading connection 125762306a36Sopenharmony_ci * driver can't reuse the CID so attempt more than once. 125862306a36Sopenharmony_ci */ 125962306a36Sopenharmony_ci attempts = 0; 126062306a36Sopenharmony_ci while (attempts++ < 3) { 126162306a36Sopenharmony_ci tag = beiscsi_invalidate_cxn(phba, beiscsi_ep); 126262306a36Sopenharmony_ci if (tag) { 126362306a36Sopenharmony_ci ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); 126462306a36Sopenharmony_ci if (!ret) 126562306a36Sopenharmony_ci break; 126662306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 126762306a36Sopenharmony_ci "BS_%d : invalidate conn failed cid %d\n", 126862306a36Sopenharmony_ci beiscsi_ep->ep_cid); 126962306a36Sopenharmony_ci } 127062306a36Sopenharmony_ci } 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci /* wait for all completions to arrive, then process them */ 127362306a36Sopenharmony_ci msleep(250); 127462306a36Sopenharmony_ci /* flush CQ entries */ 127562306a36Sopenharmony_ci beiscsi_flush_cq(phba); 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci if (attempts > 3) 127862306a36Sopenharmony_ci return -1; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci attempts = 0; 128162306a36Sopenharmony_ci while (attempts++ < 3) { 128262306a36Sopenharmony_ci tag = beiscsi_upload_cxn(phba, beiscsi_ep); 128362306a36Sopenharmony_ci if (tag) { 128462306a36Sopenharmony_ci ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); 128562306a36Sopenharmony_ci if (!ret) 128662306a36Sopenharmony_ci break; 128762306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 128862306a36Sopenharmony_ci "BS_%d : upload conn failed cid %d\n", 128962306a36Sopenharmony_ci beiscsi_ep->ep_cid); 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci } 129262306a36Sopenharmony_ci if (attempts > 3) 129362306a36Sopenharmony_ci return -1; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci return 0; 129662306a36Sopenharmony_ci} 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci/** 129962306a36Sopenharmony_ci * beiscsi_ep_disconnect - Tears down the TCP connection 130062306a36Sopenharmony_ci * @ep: endpoint to be used 130162306a36Sopenharmony_ci * 130262306a36Sopenharmony_ci * Tears down the TCP connection 130362306a36Sopenharmony_ci */ 130462306a36Sopenharmony_civoid beiscsi_ep_disconnect(struct iscsi_endpoint *ep) 130562306a36Sopenharmony_ci{ 130662306a36Sopenharmony_ci struct beiscsi_endpoint *beiscsi_ep; 130762306a36Sopenharmony_ci struct beiscsi_hba *phba; 130862306a36Sopenharmony_ci uint16_t cri_index; 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci beiscsi_ep = ep->dd_data; 131162306a36Sopenharmony_ci phba = beiscsi_ep->phba; 131262306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 131362306a36Sopenharmony_ci "BS_%d : In beiscsi_ep_disconnect for ep_cid = %u\n", 131462306a36Sopenharmony_ci beiscsi_ep->ep_cid); 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); 131762306a36Sopenharmony_ci if (!phba->ep_array[cri_index]) { 131862306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 131962306a36Sopenharmony_ci "BS_%d : ep_array at %u cid %u empty\n", 132062306a36Sopenharmony_ci cri_index, 132162306a36Sopenharmony_ci beiscsi_ep->ep_cid); 132262306a36Sopenharmony_ci return; 132362306a36Sopenharmony_ci } 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci if (!beiscsi_hba_is_online(phba)) { 132662306a36Sopenharmony_ci beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 132762306a36Sopenharmony_ci "BS_%d : HBA in error 0x%lx\n", phba->state); 132862306a36Sopenharmony_ci } else { 132962306a36Sopenharmony_ci /** 133062306a36Sopenharmony_ci * Make CID available even if close fails. 133162306a36Sopenharmony_ci * If not freed, FW might fail open using the CID. 133262306a36Sopenharmony_ci */ 133362306a36Sopenharmony_ci if (beiscsi_conn_close(beiscsi_ep) < 0) 133462306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 133562306a36Sopenharmony_ci "BS_%d : close conn failed cid %d\n", 133662306a36Sopenharmony_ci beiscsi_ep->ep_cid); 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci beiscsi_free_ep(beiscsi_ep); 134062306a36Sopenharmony_ci if (!phba->conn_table[cri_index]) 134162306a36Sopenharmony_ci __beiscsi_log(phba, KERN_ERR, 134262306a36Sopenharmony_ci "BS_%d : conn_table empty at %u: cid %u\n", 134362306a36Sopenharmony_ci cri_index, beiscsi_ep->ep_cid); 134462306a36Sopenharmony_ci phba->conn_table[cri_index] = NULL; 134562306a36Sopenharmony_ci iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ciumode_t beiscsi_attr_is_visible(int param_type, int param) 134962306a36Sopenharmony_ci{ 135062306a36Sopenharmony_ci switch (param_type) { 135162306a36Sopenharmony_ci case ISCSI_NET_PARAM: 135262306a36Sopenharmony_ci switch (param) { 135362306a36Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 135462306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 135562306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 135662306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 135762306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GW: 135862306a36Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 135962306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ID: 136062306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_PRIORITY: 136162306a36Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 136262306a36Sopenharmony_ci return S_IRUGO; 136362306a36Sopenharmony_ci default: 136462306a36Sopenharmony_ci return 0; 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci case ISCSI_HOST_PARAM: 136762306a36Sopenharmony_ci switch (param) { 136862306a36Sopenharmony_ci case ISCSI_HOST_PARAM_HWADDRESS: 136962306a36Sopenharmony_ci case ISCSI_HOST_PARAM_INITIATOR_NAME: 137062306a36Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_STATE: 137162306a36Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_SPEED: 137262306a36Sopenharmony_ci return S_IRUGO; 137362306a36Sopenharmony_ci default: 137462306a36Sopenharmony_ci return 0; 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci case ISCSI_PARAM: 137762306a36Sopenharmony_ci switch (param) { 137862306a36Sopenharmony_ci case ISCSI_PARAM_MAX_RECV_DLENGTH: 137962306a36Sopenharmony_ci case ISCSI_PARAM_MAX_XMIT_DLENGTH: 138062306a36Sopenharmony_ci case ISCSI_PARAM_HDRDGST_EN: 138162306a36Sopenharmony_ci case ISCSI_PARAM_DATADGST_EN: 138262306a36Sopenharmony_ci case ISCSI_PARAM_CONN_ADDRESS: 138362306a36Sopenharmony_ci case ISCSI_PARAM_CONN_PORT: 138462306a36Sopenharmony_ci case ISCSI_PARAM_EXP_STATSN: 138562306a36Sopenharmony_ci case ISCSI_PARAM_PERSISTENT_ADDRESS: 138662306a36Sopenharmony_ci case ISCSI_PARAM_PERSISTENT_PORT: 138762306a36Sopenharmony_ci case ISCSI_PARAM_PING_TMO: 138862306a36Sopenharmony_ci case ISCSI_PARAM_RECV_TMO: 138962306a36Sopenharmony_ci case ISCSI_PARAM_INITIAL_R2T_EN: 139062306a36Sopenharmony_ci case ISCSI_PARAM_MAX_R2T: 139162306a36Sopenharmony_ci case ISCSI_PARAM_IMM_DATA_EN: 139262306a36Sopenharmony_ci case ISCSI_PARAM_FIRST_BURST: 139362306a36Sopenharmony_ci case ISCSI_PARAM_MAX_BURST: 139462306a36Sopenharmony_ci case ISCSI_PARAM_PDU_INORDER_EN: 139562306a36Sopenharmony_ci case ISCSI_PARAM_DATASEQ_INORDER_EN: 139662306a36Sopenharmony_ci case ISCSI_PARAM_ERL: 139762306a36Sopenharmony_ci case ISCSI_PARAM_TARGET_NAME: 139862306a36Sopenharmony_ci case ISCSI_PARAM_TPGT: 139962306a36Sopenharmony_ci case ISCSI_PARAM_USERNAME: 140062306a36Sopenharmony_ci case ISCSI_PARAM_PASSWORD: 140162306a36Sopenharmony_ci case ISCSI_PARAM_USERNAME_IN: 140262306a36Sopenharmony_ci case ISCSI_PARAM_PASSWORD_IN: 140362306a36Sopenharmony_ci case ISCSI_PARAM_FAST_ABORT: 140462306a36Sopenharmony_ci case ISCSI_PARAM_ABORT_TMO: 140562306a36Sopenharmony_ci case ISCSI_PARAM_LU_RESET_TMO: 140662306a36Sopenharmony_ci case ISCSI_PARAM_IFACE_NAME: 140762306a36Sopenharmony_ci case ISCSI_PARAM_INITIATOR_NAME: 140862306a36Sopenharmony_ci return S_IRUGO; 140962306a36Sopenharmony_ci default: 141062306a36Sopenharmony_ci return 0; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci } 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci return 0; 141562306a36Sopenharmony_ci} 1416