mirror of https://gitee.com/openkylin/linux.git
[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: John Soni Jose <sony.john-n@emulex.com> Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
afb9605844
commit
1f536d49cb
|
@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
|
|||
struct be_cmd_resp_hdr *ioctl_resp_hdr;
|
||||
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;
|
||||
}
|
||||
|
||||
/* wait for the mccq completion */
|
||||
rc = wait_event_interruptible_timeout(
|
||||
|
@ -173,7 +175,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
|
|||
BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
|
||||
BEISCSI_LOG_CONFIG,
|
||||
"BC_%d : MBX Cmd Completion timed out\n");
|
||||
rc = -EAGAIN;
|
||||
rc = -EBUSY;
|
||||
|
||||
/* decrement the mccq used count */
|
||||
atomic_dec(&phba->ctrl.mcc_obj.q.used);
|
||||
|
@ -212,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
|
|||
|
||||
if (status == MCC_STATUS_INSUFFICIENT_BUFFER) {
|
||||
ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr;
|
||||
if (ioctl_resp_hdr->response_length)
|
||||
goto release_mcc_tag;
|
||||
beiscsi_log(phba, KERN_WARNING,
|
||||
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:
|
||||
|
|
|
@ -271,13 +271,17 @@ static int beiscsi_create_ipv6_iface(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);
|
||||
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);
|
||||
kfree(if_info);
|
||||
}
|
||||
}
|
||||
|
||||
void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
|
||||
|
@ -518,59 +522,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
|
|||
struct iscsi_iface *iface, int param,
|
||||
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;
|
||||
|
||||
memset(&if_info, 0, sizeof(if_info));
|
||||
|
||||
if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
|
||||
ip_type = BE2_IPV6;
|
||||
|
||||
len = mgmt_get_if_info(phba, ip_type, &if_info);
|
||||
if (len)
|
||||
if (len) {
|
||||
kfree(if_info);
|
||||
return len;
|
||||
}
|
||||
|
||||
switch (param) {
|
||||
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;
|
||||
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;
|
||||
case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
|
||||
if (!if_info.dhcp_state)
|
||||
if (!if_info->dhcp_state)
|
||||
len = sprintf(buf, "static\n");
|
||||
else
|
||||
len = sprintf(buf, "dhcp\n");
|
||||
break;
|
||||
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;
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
len = sprintf(buf, "%s\n",
|
||||
(if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
(if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
? "Disabled\n" : "Enabled\n");
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_ID:
|
||||
if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
return -EINVAL;
|
||||
else
|
||||
len = sprintf(buf, "%d\n",
|
||||
(if_info.vlan_priority &
|
||||
(if_info->vlan_priority &
|
||||
ISCSI_MAX_VLAN_ID));
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_PRIORITY:
|
||||
if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
return -EINVAL;
|
||||
else
|
||||
len = sprintf(buf, "%d\n",
|
||||
((if_info.vlan_priority >> 13) &
|
||||
((if_info->vlan_priority >> 13) &
|
||||
ISCSI_MAX_VLAN_PRIORITY));
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
kfree(if_info);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
@ -824,11 +824,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
|
|||
|
||||
rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va);
|
||||
if (rc) {
|
||||
/* Check if the IOCTL needs to be re-issued */
|
||||
if (rc == -EAGAIN)
|
||||
return rc;
|
||||
|
||||
beiscsi_log(phba, KERN_ERR,
|
||||
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
|
||||
"BG_%d : mgmt_exec_nonemb_cmd Failed status\n");
|
||||
|
||||
rc = -EIO;
|
||||
goto free_cmd;
|
||||
}
|
||||
|
||||
|
@ -937,7 +940,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
|
|||
uint32_t boot_proto)
|
||||
{
|
||||
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_rel_dhcp_req *reldhcp;
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
|
@ -948,16 +951,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
|
|||
if (mgmt_get_all_if_id(phba))
|
||||
return -EIO;
|
||||
|
||||
memset(&if_info, 0, sizeof(if_info));
|
||||
ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
|
||||
BE2_IPV6 : BE2_IPV4 ;
|
||||
|
||||
rc = mgmt_get_if_info(phba, ip_type, &if_info);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
kfree(if_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (boot_proto == ISCSI_BOOTPROTO_DHCP) {
|
||||
if (if_info.dhcp_state) {
|
||||
if (if_info->dhcp_state) {
|
||||
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
|
||||
"BG_%d : DHCP Already Enabled\n");
|
||||
return 0;
|
||||
|
@ -970,9 +974,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
|
|||
IP_V6_LEN : IP_V4_LEN;
|
||||
|
||||
} 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,
|
||||
OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR,
|
||||
sizeof(*reldhcp));
|
||||
|
@ -995,8 +999,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
|
|||
}
|
||||
|
||||
/* Delete the Static IP Set */
|
||||
if (if_info.ip_addr.addr[0]) {
|
||||
rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL,
|
||||
if (if_info->ip_addr.addr[0]) {
|
||||
rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
|
||||
IP_ACTION_DEL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -1042,7 +1046,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
|
|||
|
||||
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
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_dma_mem nonemb_cmd;
|
||||
uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp);
|
||||
int rc;
|
||||
|
||||
if (mgmt_get_all_if_id(phba))
|
||||
return -EIO;
|
||||
|
||||
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
|
||||
OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
|
||||
sizeof(*if_info));
|
||||
if (rc)
|
||||
return rc;
|
||||
do {
|
||||
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
|
||||
OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO,
|
||||
ioctl_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req = nonemb_cmd.va;
|
||||
req->interface_hndl = phba->interface_handle;
|
||||
req->ip_type = ip_type;
|
||||
req = nonemb_cmd.va;
|
||||
req->interface_hndl = phba->interface_handle;
|
||||
req->ip_type = ip_type;
|
||||
|
||||
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info,
|
||||
sizeof(*if_info));
|
||||
/* 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;
|
||||
}
|
||||
|
||||
rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *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,
|
||||
|
|
|
@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba,
|
|||
struct be_cmd_get_nic_conf_resp *mac);
|
||||
|
||||
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,
|
||||
struct be_cmd_get_def_gateway_resp *gateway);
|
||||
|
|
Loading…
Reference in New Issue