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 | |
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')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 20 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 37 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 83 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 2 |
4 files changed, 99 insertions, 43 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cc37a4e5ce45..fce298ba4b41 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
@@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
158 | struct be_cmd_resp_hdr *ioctl_resp_hdr; | 158 | struct be_cmd_resp_hdr *ioctl_resp_hdr; |
159 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 159 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
160 | 160 | ||
161 | if (beiscsi_error(phba)) | 161 | if (beiscsi_error(phba)) { |
162 | free_mcc_tag(&phba->ctrl, tag); | ||
162 | return -EIO; | 163 | return -EIO; |
164 | } | ||
163 | 165 | ||
164 | /* wait for the mccq completion */ | 166 | /* wait for the mccq completion */ |
165 | rc = wait_event_interruptible_timeout( | 167 | rc = wait_event_interruptible_timeout( |
@@ -173,7 +175,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
173 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | | 175 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | |
174 | BEISCSI_LOG_CONFIG, | 176 | BEISCSI_LOG_CONFIG, |
175 | "BC_%d : MBX Cmd Completion timed out\n"); | 177 | "BC_%d : MBX Cmd Completion timed out\n"); |
176 | rc = -EAGAIN; | 178 | rc = -EBUSY; |
177 | 179 | ||
178 | /* decrement the mccq used count */ | 180 | /* decrement the mccq used count */ |
179 | atomic_dec(&phba->ctrl.mcc_obj.q.used); | 181 | atomic_dec(&phba->ctrl.mcc_obj.q.used); |
@@ -212,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
212 | 214 | ||
213 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { | 215 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { |
214 | ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; | 216 | ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; |
215 | if (ioctl_resp_hdr->response_length) | 217 | beiscsi_log(phba, KERN_WARNING, |
216 | goto release_mcc_tag; | 218 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | |
219 | BEISCSI_LOG_CONFIG, | ||
220 | "BC_%d : Insufficent Buffer Error " | ||
221 | "Resp_Len : %d Actual_Resp_Len : %d\n", | ||
222 | ioctl_resp_hdr->response_length, | ||
223 | ioctl_resp_hdr->actual_resp_len); | ||
224 | |||
225 | rc = -EAGAIN; | ||
226 | goto release_mcc_tag; | ||
217 | } | 227 | } |
218 | rc = -EAGAIN; | 228 | rc = -EIO; |
219 | } | 229 | } |
220 | 230 | ||
221 | release_mcc_tag: | 231 | release_mcc_tag: |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index a7cd92c3c383..e82ab8124958 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -271,13 +271,17 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) | |||
271 | 271 | ||
272 | void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) | 272 | void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) |
273 | { | 273 | { |
274 | struct be_cmd_get_if_info_resp if_info; | 274 | struct be_cmd_get_if_info_resp *if_info; |
275 | 275 | ||
276 | if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) | 276 | if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) { |
277 | beiscsi_create_ipv4_iface(phba); | 277 | beiscsi_create_ipv4_iface(phba); |
278 | kfree(if_info); | ||
279 | } | ||
278 | 280 | ||
279 | if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) | 281 | if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) { |
280 | beiscsi_create_ipv6_iface(phba); | 282 | beiscsi_create_ipv6_iface(phba); |
283 | kfree(if_info); | ||
284 | } | ||
281 | } | 285 | } |
282 | 286 | ||
283 | void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) | 287 | void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) |
@@ -518,59 +522,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, | |||
518 | struct iscsi_iface *iface, int param, | 522 | struct iscsi_iface *iface, int param, |
519 | char *buf) | 523 | char *buf) |
520 | { | 524 | { |
521 | struct be_cmd_get_if_info_resp if_info; | 525 | struct be_cmd_get_if_info_resp *if_info; |
522 | int len, ip_type = BE2_IPV4; | 526 | int len, ip_type = BE2_IPV4; |
523 | 527 | ||
524 | memset(&if_info, 0, sizeof(if_info)); | ||
525 | |||
526 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) | 528 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) |
527 | ip_type = BE2_IPV6; | 529 | ip_type = BE2_IPV6; |
528 | 530 | ||
529 | len = mgmt_get_if_info(phba, ip_type, &if_info); | 531 | len = mgmt_get_if_info(phba, ip_type, &if_info); |
530 | if (len) | 532 | if (len) { |
533 | kfree(if_info); | ||
531 | return len; | 534 | return len; |
535 | } | ||
532 | 536 | ||
533 | switch (param) { | 537 | switch (param) { |
534 | case ISCSI_NET_PARAM_IPV4_ADDR: | 538 | case ISCSI_NET_PARAM_IPV4_ADDR: |
535 | len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr); | 539 | len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr); |
536 | break; | 540 | break; |
537 | case ISCSI_NET_PARAM_IPV6_ADDR: | 541 | case ISCSI_NET_PARAM_IPV6_ADDR: |
538 | len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr); | 542 | len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr); |
539 | break; | 543 | break; |
540 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: | 544 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: |
541 | if (!if_info.dhcp_state) | 545 | if (!if_info->dhcp_state) |
542 | len = sprintf(buf, "static\n"); | 546 | len = sprintf(buf, "static\n"); |
543 | else | 547 | else |
544 | len = sprintf(buf, "dhcp\n"); | 548 | len = sprintf(buf, "dhcp\n"); |
545 | break; | 549 | break; |
546 | case ISCSI_NET_PARAM_IPV4_SUBNET: | 550 | case ISCSI_NET_PARAM_IPV4_SUBNET: |
547 | len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask); | 551 | len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask); |
548 | break; | 552 | break; |
549 | case ISCSI_NET_PARAM_VLAN_ENABLED: | 553 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
550 | len = sprintf(buf, "%s\n", | 554 | len = sprintf(buf, "%s\n", |
551 | (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) | 555 | (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
552 | ? "Disabled\n" : "Enabled\n"); | 556 | ? "Disabled\n" : "Enabled\n"); |
553 | break; | 557 | break; |
554 | case ISCSI_NET_PARAM_VLAN_ID: | 558 | case ISCSI_NET_PARAM_VLAN_ID: |
555 | if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) | 559 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
556 | return -EINVAL; | 560 | return -EINVAL; |
557 | else | 561 | else |
558 | len = sprintf(buf, "%d\n", | 562 | len = sprintf(buf, "%d\n", |
559 | (if_info.vlan_priority & | 563 | (if_info->vlan_priority & |
560 | ISCSI_MAX_VLAN_ID)); | 564 | ISCSI_MAX_VLAN_ID)); |
561 | break; | 565 | break; |
562 | case ISCSI_NET_PARAM_VLAN_PRIORITY: | 566 | case ISCSI_NET_PARAM_VLAN_PRIORITY: |
563 | if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) | 567 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
564 | return -EINVAL; | 568 | return -EINVAL; |
565 | else | 569 | else |
566 | len = sprintf(buf, "%d\n", | 570 | len = sprintf(buf, "%d\n", |
567 | ((if_info.vlan_priority >> 13) & | 571 | ((if_info->vlan_priority >> 13) & |
568 | ISCSI_MAX_VLAN_PRIORITY)); | 572 | ISCSI_MAX_VLAN_PRIORITY)); |
569 | break; | 573 | break; |
570 | default: | 574 | default: |
571 | WARN_ON(1); | 575 | WARN_ON(1); |
572 | } | 576 | } |
573 | 577 | ||
578 | kfree(if_info); | ||
574 | return len; | 579 | return len; |
575 | } | 580 | } |
576 | 581 | ||
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, |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 645e144622c9..01b8c97284c0 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba, | |||
294 | struct be_cmd_get_nic_conf_resp *mac); | 294 | struct be_cmd_get_nic_conf_resp *mac); |
295 | 295 | ||
296 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | 296 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, |
297 | struct be_cmd_get_if_info_resp *if_info); | 297 | struct be_cmd_get_if_info_resp **if_info); |
298 | 298 | ||
299 | int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, | 299 | int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, |
300 | struct be_cmd_get_def_gateway_resp *gateway); | 300 | struct be_cmd_get_def_gateway_resp *gateway); |