diff options
author | Jayamohan Kallickal <jayamohank@gmail.com> | 2013-09-28 18:35:56 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-10-25 04:58:09 -0400 |
commit | 1f536d49cba96fa2f1ac47d267ff5d30a586e04c (patch) | |
tree | c99efd8a86561281c3d683d1b2d99bb562c58f7a /drivers/scsi/be2iscsi/be_mgmt.c | |
parent | afb9605844d117276532aabc5087e9fc3c0a08d2 (diff) |
[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>
Diffstat (limited to 'drivers/scsi/be2iscsi/be_mgmt.c')
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 83 |
1 files changed, 62 insertions, 21 deletions
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index befeace18257..1f2b546a3fc4 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -824,11 +824,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, | |||
824 | 824 | ||
825 | rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); | 825 | rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); |
826 | if (rc) { | 826 | if (rc) { |
827 | /* Check if the IOCTL needs to be re-issued */ | ||
828 | if (rc == -EAGAIN) | ||
829 | return rc; | ||
830 | |||
827 | beiscsi_log(phba, KERN_ERR, | 831 | beiscsi_log(phba, KERN_ERR, |
828 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 832 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
829 | "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); | 833 | "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); |
830 | 834 | ||
831 | rc = -EIO; | ||
832 | goto free_cmd; | 835 | goto free_cmd; |
833 | } | 836 | } |
834 | 837 | ||
@@ -937,7 +940,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
937 | uint32_t boot_proto) | 940 | uint32_t boot_proto) |
938 | { | 941 | { |
939 | struct be_cmd_get_def_gateway_resp gtway_addr_set; | 942 | struct be_cmd_get_def_gateway_resp gtway_addr_set; |
940 | struct be_cmd_get_if_info_resp if_info; | 943 | struct be_cmd_get_if_info_resp *if_info; |
941 | struct be_cmd_set_dhcp_req *dhcpreq; | 944 | struct be_cmd_set_dhcp_req *dhcpreq; |
942 | struct be_cmd_rel_dhcp_req *reldhcp; | 945 | struct be_cmd_rel_dhcp_req *reldhcp; |
943 | struct be_dma_mem nonemb_cmd; | 946 | struct be_dma_mem nonemb_cmd; |
@@ -948,16 +951,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
948 | if (mgmt_get_all_if_id(phba)) | 951 | if (mgmt_get_all_if_id(phba)) |
949 | return -EIO; | 952 | return -EIO; |
950 | 953 | ||
951 | memset(&if_info, 0, sizeof(if_info)); | ||
952 | ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | 954 | ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? |
953 | BE2_IPV6 : BE2_IPV4 ; | 955 | BE2_IPV6 : BE2_IPV4 ; |
954 | 956 | ||
955 | rc = mgmt_get_if_info(phba, ip_type, &if_info); | 957 | rc = mgmt_get_if_info(phba, ip_type, &if_info); |
956 | if (rc) | 958 | if (rc) { |
959 | kfree(if_info); | ||
957 | return rc; | 960 | return rc; |
961 | } | ||
958 | 962 | ||
959 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | 963 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { |
960 | if (if_info.dhcp_state) { | 964 | if (if_info->dhcp_state) { |
961 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 965 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
962 | "BG_%d : DHCP Already Enabled\n"); | 966 | "BG_%d : DHCP Already Enabled\n"); |
963 | return 0; | 967 | return 0; |
@@ -970,9 +974,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
970 | IP_V6_LEN : IP_V4_LEN; | 974 | IP_V6_LEN : IP_V4_LEN; |
971 | 975 | ||
972 | } else { | 976 | } else { |
973 | if (if_info.dhcp_state) { | 977 | if (if_info->dhcp_state) { |
974 | 978 | ||
975 | memset(&if_info, 0, sizeof(if_info)); | 979 | memset(if_info, 0, sizeof(*if_info)); |
976 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 980 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
977 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, | 981 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, |
978 | sizeof(*reldhcp)); | 982 | sizeof(*reldhcp)); |
@@ -995,8 +999,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
995 | } | 999 | } |
996 | 1000 | ||
997 | /* Delete the Static IP Set */ | 1001 | /* Delete the Static IP Set */ |
998 | if (if_info.ip_addr.addr[0]) { | 1002 | if (if_info->ip_addr.addr[0]) { |
999 | rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL, | 1003 | rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL, |
1000 | IP_ACTION_DEL); | 1004 | IP_ACTION_DEL); |
1001 | if (rc) | 1005 | if (rc) |
1002 | return rc; | 1006 | return rc; |
@@ -1042,7 +1046,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
1042 | 1046 | ||
1043 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | 1047 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
1044 | } else { | 1048 | } else { |
1045 | return mgmt_static_ip_modify(phba, &if_info, ip_param, | 1049 | return mgmt_static_ip_modify(phba, if_info, ip_param, |
1046 | subnet_param, IP_ACTION_ADD); | 1050 | subnet_param, IP_ACTION_ADD); |
1047 | } | 1051 | } |
1048 | 1052 | ||
@@ -1107,27 +1111,64 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, | |||
1107 | } | 1111 | } |
1108 | 1112 | ||
1109 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | 1113 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, |
1110 | struct be_cmd_get_if_info_resp *if_info) | 1114 | struct be_cmd_get_if_info_resp **if_info) |
1111 | { | 1115 | { |
1112 | struct be_cmd_get_if_info_req *req; | 1116 | struct be_cmd_get_if_info_req *req; |
1113 | struct be_dma_mem nonemb_cmd; | 1117 | struct be_dma_mem nonemb_cmd; |
1118 | uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); | ||
1114 | int rc; | 1119 | int rc; |
1115 | 1120 | ||
1116 | if (mgmt_get_all_if_id(phba)) | 1121 | if (mgmt_get_all_if_id(phba)) |
1117 | return -EIO; | 1122 | return -EIO; |
1118 | 1123 | ||
1119 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 1124 | do { |
1120 | OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, | 1125 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
1121 | sizeof(*if_info)); | 1126 | OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, |
1122 | if (rc) | 1127 | ioctl_size); |
1123 | return rc; | 1128 | if (rc) |
1129 | return rc; | ||
1124 | 1130 | ||
1125 | req = nonemb_cmd.va; | 1131 | req = nonemb_cmd.va; |
1126 | req->interface_hndl = phba->interface_handle; | 1132 | req->interface_hndl = phba->interface_handle; |
1127 | req->ip_type = ip_type; | 1133 | req->ip_type = ip_type; |
1134 | |||
1135 | /* Allocate memory for if_info */ | ||
1136 | *if_info = kzalloc(ioctl_size, GFP_KERNEL); | ||
1137 | if (!*if_info) { | ||
1138 | beiscsi_log(phba, KERN_ERR, | ||
1139 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
1140 | "BG_%d : Memory Allocation Failure\n"); | ||
1141 | |||
1142 | /* Free the DMA memory for the IOCTL issuing */ | ||
1143 | pci_free_consistent(phba->ctrl.pdev, | ||
1144 | nonemb_cmd.size, | ||
1145 | nonemb_cmd.va, | ||
1146 | nonemb_cmd.dma); | ||
1147 | return -ENOMEM; | ||
1148 | } | ||
1128 | 1149 | ||
1129 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info, | 1150 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *if_info, |
1130 | sizeof(*if_info)); | 1151 | ioctl_size); |
1152 | |||
1153 | /* Check if the error is because of Insufficent_Buffer */ | ||
1154 | if (rc == -EAGAIN) { | ||
1155 | |||
1156 | /* Get the new memory size */ | ||
1157 | ioctl_size = ((struct be_cmd_resp_hdr *) | ||
1158 | nonemb_cmd.va)->actual_resp_len; | ||
1159 | ioctl_size += sizeof(struct be_cmd_req_hdr); | ||
1160 | |||
1161 | /* Free the previous allocated DMA memory */ | ||
1162 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
1163 | nonemb_cmd.va, | ||
1164 | nonemb_cmd.dma); | ||
1165 | |||
1166 | /* Free the virtual memory */ | ||
1167 | kfree(*if_info); | ||
1168 | } else | ||
1169 | break; | ||
1170 | } while (true); | ||
1171 | return rc; | ||
1131 | } | 1172 | } |
1132 | 1173 | ||
1133 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, | 1174 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, |