Commit 1f536d49 authored by Jayamohan Kallickal's avatar Jayamohan Kallickal Committed by James Bottomley

[SCSI] be2iscsi: Fix Insufficient Buffer Error returned in MBX Completion

When MBX_Cmd completion happens with error code Insufficient Buffer,
the MBX_Cmd is posted again with the new buffer size posted by FW.
Signed-off-by: default avatarJohn Soni Jose <sony.john-n@emulex.com>
Signed-off-by: default avatarJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent afb96058
...@@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, ...@@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
struct be_cmd_resp_hdr *ioctl_resp_hdr; struct be_cmd_resp_hdr *ioctl_resp_hdr;
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
if (beiscsi_error(phba)) if (beiscsi_error(phba)) {
free_mcc_tag(&phba->ctrl, tag);
return -EIO; return -EIO;
}
/* wait for the mccq completion */ /* wait for the mccq completion */
rc = wait_event_interruptible_timeout( rc = wait_event_interruptible_timeout(
...@@ -173,7 +175,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, ...@@ -173,7 +175,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
BEISCSI_LOG_INIT | BEISCSI_LOG_EH | BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
BEISCSI_LOG_CONFIG, BEISCSI_LOG_CONFIG,
"BC_%d : MBX Cmd Completion timed out\n"); "BC_%d : MBX Cmd Completion timed out\n");
rc = -EAGAIN; rc = -EBUSY;
/* decrement the mccq used count */ /* decrement the mccq used count */
atomic_dec(&phba->ctrl.mcc_obj.q.used); atomic_dec(&phba->ctrl.mcc_obj.q.used);
...@@ -212,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, ...@@ -212,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { if (status == MCC_STATUS_INSUFFICIENT_BUFFER) {
ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr;
if (ioctl_resp_hdr->response_length) beiscsi_log(phba, KERN_WARNING,
goto release_mcc_tag; BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
BEISCSI_LOG_CONFIG,
"BC_%d : Insufficent Buffer Error "
"Resp_Len : %d Actual_Resp_Len : %d\n",
ioctl_resp_hdr->response_length,
ioctl_resp_hdr->actual_resp_len);
rc = -EAGAIN;
goto release_mcc_tag;
} }
rc = -EAGAIN; rc = -EIO;
} }
release_mcc_tag: release_mcc_tag:
......
...@@ -271,13 +271,17 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) ...@@ -271,13 +271,17 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) void beiscsi_create_def_ifaces(struct beiscsi_hba *phba)
{ {
struct be_cmd_get_if_info_resp if_info; struct be_cmd_get_if_info_resp *if_info;
if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) {
beiscsi_create_ipv4_iface(phba); beiscsi_create_ipv4_iface(phba);
kfree(if_info);
}
if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) {
beiscsi_create_ipv6_iface(phba); beiscsi_create_ipv6_iface(phba);
kfree(if_info);
}
} }
void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
...@@ -518,59 +522,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, ...@@ -518,59 +522,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
struct iscsi_iface *iface, int param, struct iscsi_iface *iface, int param,
char *buf) char *buf)
{ {
struct be_cmd_get_if_info_resp if_info; struct be_cmd_get_if_info_resp *if_info;
int len, ip_type = BE2_IPV4; int len, ip_type = BE2_IPV4;
memset(&if_info, 0, sizeof(if_info));
if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
ip_type = BE2_IPV6; ip_type = BE2_IPV6;
len = mgmt_get_if_info(phba, ip_type, &if_info); len = mgmt_get_if_info(phba, ip_type, &if_info);
if (len) if (len) {
kfree(if_info);
return len; return len;
}
switch (param) { switch (param) {
case ISCSI_NET_PARAM_IPV4_ADDR: case ISCSI_NET_PARAM_IPV4_ADDR:
len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr); len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr);
break; break;
case ISCSI_NET_PARAM_IPV6_ADDR: case ISCSI_NET_PARAM_IPV6_ADDR:
len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr); len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr);
break; break;
case ISCSI_NET_PARAM_IPV4_BOOTPROTO: case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
if (!if_info.dhcp_state) if (!if_info->dhcp_state)
len = sprintf(buf, "static\n"); len = sprintf(buf, "static\n");
else else
len = sprintf(buf, "dhcp\n"); len = sprintf(buf, "dhcp\n");
break; break;
case ISCSI_NET_PARAM_IPV4_SUBNET: case ISCSI_NET_PARAM_IPV4_SUBNET:
len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask); len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask);
break; break;
case ISCSI_NET_PARAM_VLAN_ENABLED: case ISCSI_NET_PARAM_VLAN_ENABLED:
len = sprintf(buf, "%s\n", len = sprintf(buf, "%s\n",
(if_info.vlan_priority == BEISCSI_VLAN_DISABLE) (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
? "Disabled\n" : "Enabled\n"); ? "Disabled\n" : "Enabled\n");
break; break;
case ISCSI_NET_PARAM_VLAN_ID: case ISCSI_NET_PARAM_VLAN_ID:
if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
return -EINVAL; return -EINVAL;
else else
len = sprintf(buf, "%d\n", len = sprintf(buf, "%d\n",
(if_info.vlan_priority & (if_info->vlan_priority &
ISCSI_MAX_VLAN_ID)); ISCSI_MAX_VLAN_ID));
break; break;
case ISCSI_NET_PARAM_VLAN_PRIORITY: case ISCSI_NET_PARAM_VLAN_PRIORITY:
if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
return -EINVAL; return -EINVAL;
else else
len = sprintf(buf, "%d\n", len = sprintf(buf, "%d\n",
((if_info.vlan_priority >> 13) & ((if_info->vlan_priority >> 13) &
ISCSI_MAX_VLAN_PRIORITY)); ISCSI_MAX_VLAN_PRIORITY));
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
} }
kfree(if_info);
return len; return len;
} }
......
...@@ -824,11 +824,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, ...@@ -824,11 +824,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va);
if (rc) { if (rc) {
/* Check if the IOCTL needs to be re-issued */
if (rc == -EAGAIN)
return rc;
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); "BG_%d : mgmt_exec_nonemb_cmd Failed status\n");
rc = -EIO;
goto free_cmd; goto free_cmd;
} }
...@@ -937,7 +940,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -937,7 +940,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
uint32_t boot_proto) uint32_t boot_proto)
{ {
struct be_cmd_get_def_gateway_resp gtway_addr_set; struct be_cmd_get_def_gateway_resp gtway_addr_set;
struct be_cmd_get_if_info_resp if_info; struct be_cmd_get_if_info_resp *if_info;
struct be_cmd_set_dhcp_req *dhcpreq; struct be_cmd_set_dhcp_req *dhcpreq;
struct be_cmd_rel_dhcp_req *reldhcp; struct be_cmd_rel_dhcp_req *reldhcp;
struct be_dma_mem nonemb_cmd; struct be_dma_mem nonemb_cmd;
...@@ -948,16 +951,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -948,16 +951,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
if (mgmt_get_all_if_id(phba)) if (mgmt_get_all_if_id(phba))
return -EIO; return -EIO;
memset(&if_info, 0, sizeof(if_info));
ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
BE2_IPV6 : BE2_IPV4 ; BE2_IPV6 : BE2_IPV4 ;
rc = mgmt_get_if_info(phba, ip_type, &if_info); rc = mgmt_get_if_info(phba, ip_type, &if_info);
if (rc) if (rc) {
kfree(if_info);
return rc; return rc;
}
if (boot_proto == ISCSI_BOOTPROTO_DHCP) { if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
if (if_info.dhcp_state) { if (if_info->dhcp_state) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : DHCP Already Enabled\n"); "BG_%d : DHCP Already Enabled\n");
return 0; return 0;
...@@ -970,9 +974,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -970,9 +974,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
IP_V6_LEN : IP_V4_LEN; IP_V6_LEN : IP_V4_LEN;
} else { } else {
if (if_info.dhcp_state) { if (if_info->dhcp_state) {
memset(&if_info, 0, sizeof(if_info)); memset(if_info, 0, sizeof(*if_info));
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
sizeof(*reldhcp)); sizeof(*reldhcp));
...@@ -995,8 +999,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -995,8 +999,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
} }
/* Delete the Static IP Set */ /* Delete the Static IP Set */
if (if_info.ip_addr.addr[0]) { if (if_info->ip_addr.addr[0]) {
rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL, rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
IP_ACTION_DEL); IP_ACTION_DEL);
if (rc) if (rc)
return rc; return rc;
...@@ -1042,7 +1046,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, ...@@ -1042,7 +1046,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
} else { } else {
return mgmt_static_ip_modify(phba, &if_info, ip_param, return mgmt_static_ip_modify(phba, if_info, ip_param,
subnet_param, IP_ACTION_ADD); subnet_param, IP_ACTION_ADD);
} }
...@@ -1107,27 +1111,64 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, ...@@ -1107,27 +1111,64 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
} }
int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_if_info_resp *if_info) struct be_cmd_get_if_info_resp **if_info)
{ {
struct be_cmd_get_if_info_req *req; struct be_cmd_get_if_info_req *req;
struct be_dma_mem nonemb_cmd; struct be_dma_mem nonemb_cmd;
uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp);
int rc; int rc;
if (mgmt_get_all_if_id(phba)) if (mgmt_get_all_if_id(phba))
return -EIO; return -EIO;
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, do {
OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
sizeof(*if_info)); OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
if (rc) ioctl_size);
return rc; if (rc)
return rc;
req = nonemb_cmd.va; req = nonemb_cmd.va;
req->interface_hndl = phba->interface_handle; req->interface_hndl = phba->interface_handle;
req->ip_type = ip_type; req->ip_type = ip_type;
/* Allocate memory for if_info */
*if_info = kzalloc(ioctl_size, GFP_KERNEL);
if (!*if_info) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
"BG_%d : Memory Allocation Failure\n");
/* Free the DMA memory for the IOCTL issuing */
pci_free_consistent(phba->ctrl.pdev,
nonemb_cmd.size,
nonemb_cmd.va,
nonemb_cmd.dma);
return -ENOMEM;
}
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info, rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *if_info,
sizeof(*if_info)); ioctl_size);
/* Check if the error is because of Insufficent_Buffer */
if (rc == -EAGAIN) {
/* Get the new memory size */
ioctl_size = ((struct be_cmd_resp_hdr *)
nonemb_cmd.va)->actual_resp_len;
ioctl_size += sizeof(struct be_cmd_req_hdr);
/* Free the previous allocated DMA memory */
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va,
nonemb_cmd.dma);
/* Free the virtual memory */
kfree(*if_info);
} else
break;
} while (true);
return rc;
} }
int mgmt_get_nic_conf(struct beiscsi_hba *phba, int mgmt_get_nic_conf(struct beiscsi_hba *phba,
......
...@@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba, ...@@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba,
struct be_cmd_get_nic_conf_resp *mac); struct be_cmd_get_nic_conf_resp *mac);
int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_if_info_resp *if_info); struct be_cmd_get_if_info_resp **if_info);
int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_def_gateway_resp *gateway); struct be_cmd_get_def_gateway_resp *gateway);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment