}
}
-static int
-beiscsi_set_static_ip(struct Scsi_Host *shost,
- struct iscsi_iface_param_info *iface_param,
- void *data, uint32_t dt_len)
-{
- struct beiscsi_hba *phba = iscsi_host_priv(shost);
- struct iscsi_iface_param_info *iface_ip = NULL;
- struct iscsi_iface_param_info *iface_subnet = NULL;
- struct nlattr *nla;
- int ret;
-
-
- switch (iface_param->param) {
- case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
- nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
- if (nla)
- iface_ip = nla_data(nla);
-
- nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
- if (nla)
- iface_subnet = nla_data(nla);
- break;
- case ISCSI_NET_PARAM_IPV4_ADDR:
- iface_ip = iface_param;
- nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
- if (nla)
- iface_subnet = nla_data(nla);
- break;
- case ISCSI_NET_PARAM_IPV4_SUBNET:
- iface_subnet = iface_param;
- nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
- if (nla)
- iface_ip = nla_data(nla);
- break;
- default:
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
- "BS_%d : Unsupported param %d\n",
- iface_param->param);
- }
-
- if (!iface_ip || !iface_subnet) {
- beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
- "BS_%d : IP and Subnet Mask required\n");
- return -EINVAL;
- }
-
- ret = mgmt_set_ip(phba, iface_ip, iface_subnet,
- ISCSI_BOOTPROTO_STATIC);
-
- return ret;
-}
-
/**
* beiscsi_set_vlan_tag()- Set the VLAN TAG
* @shost: Scsi Host for the driver instance
static int
-beiscsi_set_ipv4(struct Scsi_Host *shost,
- struct iscsi_iface_param_info *iface_param,
- void *data, uint32_t dt_len)
+beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
+ struct iscsi_iface_param_info *info,
+ void *data, uint32_t dt_len)
{
struct beiscsi_hba *phba = iscsi_host_priv(shost);
+ u8 *ip = NULL, *subnet = NULL, *gw;
+ struct nlattr *nla;
int ret = 0;
/* Check the param */
- switch (iface_param->param) {
+ switch (info->param) {
case ISCSI_NET_PARAM_IFACE_ENABLE:
- if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
+ if (info->value[0] == ISCSI_IFACE_ENABLE)
ret = beiscsi_create_ipv4_iface(phba);
else {
iscsi_destroy_iface(phba->ipv4_iface);
}
break;
case ISCSI_NET_PARAM_IPV4_GW:
- ret = beiscsi_if_set_gw(phba, BE2_IPV4, iface_param->value);
+ gw = info->value;
+ ret = beiscsi_if_set_gw(phba, BE2_IPV4, gw);
break;
case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
- if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
- ret = mgmt_set_ip(phba, iface_param,
- NULL, ISCSI_BOOTPROTO_DHCP);
- else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
- ret = beiscsi_set_static_ip(shost, iface_param,
- data, dt_len);
+ if (info->value[0] == ISCSI_BOOTPROTO_DHCP)
+ ret = beiscsi_if_en_dhcp(phba, BE2_IPV4);
+ else if (info->value[0] == ISCSI_BOOTPROTO_STATIC)
+ /* release DHCP IP address */
+ ret = beiscsi_if_en_static(phba, BE2_IPV4, NULL, NULL);
else
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Invalid BOOTPROTO: %d\n",
- iface_param->value[0]);
+ info->value[0]);
break;
- case ISCSI_NET_PARAM_IPV4_SUBNET:
case ISCSI_NET_PARAM_IPV4_ADDR:
- ret = beiscsi_set_static_ip(shost, iface_param,
- data, dt_len);
+ ip = info->value;
+ nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
+ if (nla) {
+ info = nla_data(nla);
+ subnet = info->value;
+ }
+ ret = beiscsi_if_en_static(phba, BE2_IPV4, ip, subnet);
+ break;
+ case ISCSI_NET_PARAM_IPV4_SUBNET:
+ /*
+ * OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP
+ * and subnet both. Find IP to be applied for this subnet.
+ */
+ subnet = info->value;
+ nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
+ if (nla) {
+ info = nla_data(nla);
+ ip = info->value;
+ }
+ ret = beiscsi_if_en_static(phba, BE2_IPV4, ip, subnet);
break;
case ISCSI_NET_PARAM_VLAN_ENABLED:
case ISCSI_NET_PARAM_VLAN_TAG:
- ret = beiscsi_set_vlan_tag(shost, iface_param);
+ ret = beiscsi_set_vlan_tag(shost, info);
break;
default:
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Param %d not supported\n",
- iface_param->param);
+ info->param);
}
return ret;
}
static int
-beiscsi_set_ipv6(struct Scsi_Host *shost,
- struct iscsi_iface_param_info *iface_param,
- void *data, uint32_t dt_len)
+beiscsi_iface_config_ipv6(struct Scsi_Host *shost,
+ struct iscsi_iface_param_info *iface_param,
+ void *data, uint32_t dt_len)
{
struct beiscsi_hba *phba = iscsi_host_priv(shost);
int ret = 0;
}
break;
case ISCSI_NET_PARAM_IPV6_ADDR:
- ret = mgmt_set_ip(phba, iface_param, NULL,
- ISCSI_BOOTPROTO_STATIC);
+ ret = beiscsi_if_en_static(phba, BE2_IPV6,
+ iface_param->value, NULL);
break;
case ISCSI_NET_PARAM_VLAN_ENABLED:
case ISCSI_NET_PARAM_VLAN_TAG:
switch (iface_param->iface_type) {
case ISCSI_IFACE_TYPE_IPV4:
- ret = beiscsi_set_ipv4(shost, iface_param,
- data, dt_len);
+ ret = beiscsi_iface_config_ipv4(shost, iface_param,
+ data, dt_len);
break;
case ISCSI_IFACE_TYPE_IPV6:
- ret = beiscsi_set_ipv6(shost, iface_param,
- data, dt_len);
+ ret = beiscsi_iface_config_ipv6(shost, iface_param,
+ data, dt_len);
break;
default:
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
return 0;
}
-static int
-mgmt_static_ip_modify(struct beiscsi_hba *phba,
- struct be_cmd_get_if_info_resp *if_info,
- struct iscsi_iface_param_info *ip_param,
- struct iscsi_iface_param_info *subnet_param,
- uint32_t ip_action)
-{
- struct be_cmd_set_ip_addr_req *req;
- struct be_dma_mem nonemb_cmd;
- uint32_t ip_type;
- int rc;
-
- rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
- OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
- sizeof(*req));
- if (rc)
- return rc;
-
- ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
- BE2_IPV6 : BE2_IPV4 ;
-
- req = nonemb_cmd.va;
- req->ip_params.record_entry_count = 1;
- req->ip_params.ip_record.action = ip_action;
- req->ip_params.ip_record.interface_hndl =
- phba->interface_handle;
- req->ip_params.ip_record.ip_addr.size_of_structure =
- sizeof(struct be_ip_addr_subnet_format);
- req->ip_params.ip_record.ip_addr.ip_type = ip_type;
-
- if (ip_action == IP_ACTION_ADD) {
- memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value,
- sizeof(req->ip_params.ip_record.ip_addr.addr));
-
- if (subnet_param)
- memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
- subnet_param->value,
- sizeof(req->ip_params.ip_record.ip_addr.subnet_mask));
- } else {
- memcpy(req->ip_params.ip_record.ip_addr.addr,
- if_info->ip_addr.addr,
- sizeof(req->ip_params.ip_record.ip_addr.addr));
-
- memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
- if_info->ip_addr.subnet_mask,
- sizeof(req->ip_params.ip_record.ip_addr.subnet_mask));
- }
-
- rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
- if (rc < 0)
- beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
- "BG_%d : Failed to Modify existing IP Address\n");
- return rc;
-}
-
static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
u32 action, u32 ip_type, u8 *gw)
{
sizeof(*resp));
}
-int mgmt_set_ip(struct beiscsi_hba *phba,
- struct iscsi_iface_param_info *ip_param,
- struct iscsi_iface_param_info *subnet_param,
- uint32_t boot_proto)
+static int
+beiscsi_if_clr_ip(struct beiscsi_hba *phba,
+ struct be_cmd_get_if_info_resp *if_info)
{
- struct be_cmd_get_def_gateway_resp gtway_addr_set;
- struct be_cmd_get_if_info_resp *if_info;
- struct be_cmd_set_dhcp_req *dhcpreq;
- struct be_cmd_rel_dhcp_req *reldhcp;
+ struct be_cmd_set_ip_addr_req *req;
struct be_dma_mem nonemb_cmd;
- uint8_t *gtway_addr;
- uint32_t ip_type;
int rc;
- rc = mgmt_get_all_if_id(phba);
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
+ sizeof(*req));
if (rc)
return rc;
- ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
- BE2_IPV6 : BE2_IPV4 ;
+ req = nonemb_cmd.va;
+ req->ip_params.record_entry_count = 1;
+ req->ip_params.ip_record.action = IP_ACTION_DEL;
+ req->ip_params.ip_record.interface_hndl =
+ phba->interface_handle;
+ req->ip_params.ip_record.ip_addr.size_of_structure =
+ sizeof(struct be_ip_addr_subnet_format);
+ req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type;
+ memcpy(req->ip_params.ip_record.ip_addr.addr,
+ if_info->ip_addr.addr,
+ sizeof(if_info->ip_addr.addr));
+ memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
+ if_info->ip_addr.subnet_mask,
+ sizeof(if_info->ip_addr.subnet_mask));
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ if (rc < 0 || req->ip_params.ip_record.status) {
+ beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
+ "BG_%d : failed to clear IP: rc %d status %d\n",
+ rc, req->ip_params.ip_record.status);
+ }
+ return rc;
+}
- rc = mgmt_get_if_info(phba, ip_type, &if_info);
+static int
+beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,
+ u8 *subnet, u32 ip_type)
+{
+ struct be_cmd_set_ip_addr_req *req;
+ struct be_dma_mem nonemb_cmd;
+ uint32_t ip_len;
+ int rc;
+
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR,
+ sizeof(*req));
if (rc)
return rc;
- if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
- if (if_info->dhcp_state) {
- beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
- "BG_%d : DHCP Already Enabled\n");
- goto exit;
- }
- /* The ip_param->len is 1 in DHCP case. Setting
- proper IP len as this it is used while
- freeing the Static IP.
- */
- ip_param->len = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
- IP_V6_LEN : IP_V4_LEN;
-
- } else {
- if (if_info->dhcp_state) {
-
- memset(if_info, 0, sizeof(*if_info));
- rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
- OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
- sizeof(*reldhcp));
+ req = nonemb_cmd.va;
+ req->ip_params.record_entry_count = 1;
+ req->ip_params.ip_record.action = IP_ACTION_ADD;
+ req->ip_params.ip_record.interface_hndl =
+ phba->interface_handle;
+ req->ip_params.ip_record.ip_addr.size_of_structure =
+ sizeof(struct be_ip_addr_subnet_format);
+ req->ip_params.ip_record.ip_addr.ip_type = ip_type;
+ ip_len = ip_type == BE2_IPV4 ? IP_V4_LEN : IP_V6_LEN;
+ memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len);
+ if (subnet)
+ memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
+ subnet, ip_len);
- if (rc)
- goto exit;
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ /**
+ * In some cases, host needs to look into individual record status
+ * even though FW reported success for that IOCTL.
+ */
+ if (rc < 0 || req->ip_params.ip_record.status) {
+ __beiscsi_log(phba, KERN_ERR,
+ "BG_%d : failed to set IP: rc %d status %d\n",
+ rc, req->ip_params.ip_record.status);
+ if (req->ip_params.ip_record.status)
+ rc = -EINVAL;
+ }
+ return rc;
+}
- reldhcp = nonemb_cmd.va;
- reldhcp->interface_hndl = phba->interface_handle;
- reldhcp->ip_type = ip_type;
+int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
+ u8 *ip, u8 *subnet)
+{
+ struct be_cmd_get_if_info_resp *if_info;
+ struct be_cmd_rel_dhcp_req *reldhcp;
+ struct be_dma_mem nonemb_cmd;
+ int rc;
- rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
- if (rc < 0) {
- beiscsi_log(phba, KERN_WARNING,
- BEISCSI_LOG_CONFIG,
- "BG_%d : Failed to Delete existing dhcp\n");
- goto exit;
- }
- }
- }
+ rc = mgmt_get_if_info(phba, ip_type, &if_info);
+ if (rc)
+ return rc;
- /* Delete the Static IP Set */
- if (if_info->ip_addr.addr[0]) {
- rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
- IP_ACTION_DEL);
+ if (if_info->dhcp_state) {
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
+ sizeof(*reldhcp));
if (rc)
goto exit;
- }
- /* Delete the Gateway settings if mode change is to DHCP */
- if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
- memset(>way_addr_set, 0, sizeof(gtway_addr_set));
- rc = beiscsi_if_get_gw(phba, BE2_IPV4, >way_addr_set);
- if (rc) {
+ reldhcp = nonemb_cmd.va;
+ reldhcp->interface_hndl = phba->interface_handle;
+ reldhcp->ip_type = ip_type;
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ if (rc < 0) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
- "BG_%d : Failed to Get Gateway Addr\n");
+ "BG_%d : failed to release existing DHCP: %d\n",
+ rc);
goto exit;
}
+ }
- if (gtway_addr_set.ip_addr.addr[0]) {
- gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr;
- rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL,
- ip_type, gtway_addr);
+ /* first delete any old IP set */
+ rc = beiscsi_if_clr_ip(phba, if_info);
+ if (rc)
+ goto exit;
- if (rc) {
- beiscsi_log(phba, KERN_WARNING,
- BEISCSI_LOG_CONFIG,
- "BG_%d : Failed to clear Gateway Addr Set\n");
- goto exit;
- }
- }
+ /* if ip == NULL then this is called just to release DHCP IP */
+ if (ip)
+ rc = beiscsi_if_set_ip(phba, ip, subnet, ip_type);
+exit:
+ kfree(if_info);
+ return rc;
+}
+
+int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
+{
+ struct be_cmd_get_def_gateway_resp gw_resp;
+ struct be_cmd_get_if_info_resp *if_info;
+ struct be_cmd_set_dhcp_req *dhcpreq;
+ struct be_dma_mem nonemb_cmd;
+ u8 *gw;
+ int rc;
+
+ rc = mgmt_get_if_info(phba, ip_type, &if_info);
+ if (rc)
+ return rc;
+
+ if (if_info->dhcp_state) {
+ beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+ "BG_%d : DHCP Already Enabled\n");
+ goto exit;
}
- /* Set Adapter to DHCP/Static Mode */
- if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
- rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
+ /* first delete any old static IP set */
+ rc = beiscsi_if_clr_ip(phba, if_info);
+ if (rc)
+ goto exit;
+
+ /* delete gateway settings if mode change is to DHCP */
+ memset(&gw_resp, 0, sizeof(gw_resp));
+ /* use ip_type provided in if_info */
+ rc = beiscsi_if_get_gw(phba, if_info->ip_addr.ip_type, &gw_resp);
+ if (rc) {
+ beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+ "BG_%d : Failed to Get Gateway Addr\n");
+ goto exit;
+ }
+ gw = (u8 *)&gw_resp.ip_addr.addr;
+ rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL,
+ if_info->ip_addr.ip_type, gw);
+ if (rc) {
+ beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+ "BG_%d : Failed to clear Gateway Addr Set\n");
+ goto exit;
+ }
+
+ rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
sizeof(*dhcpreq));
- if (rc)
- goto exit;
-
- dhcpreq = nonemb_cmd.va;
- dhcpreq->flags = BLOCKING;
- dhcpreq->retry_count = 1;
- dhcpreq->interface_hndl = phba->interface_handle;
- dhcpreq->ip_type = BE2_DHCP_V4;
+ if (rc)
+ goto exit;
- rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
- } else {
- rc = mgmt_static_ip_modify(phba, if_info, ip_param,
- subnet_param, IP_ACTION_ADD);
- }
+ dhcpreq = nonemb_cmd.va;
+ dhcpreq->flags = BLOCKING;
+ dhcpreq->retry_count = 1;
+ dhcpreq->interface_hndl = phba->interface_handle;
+ dhcpreq->ip_type = ip_type;
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
exit:
kfree(if_info);