diff options
41 files changed, 1516 insertions, 365 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index d4ed8e98edf7..280c9b5ad9e3 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
| @@ -122,14 +122,6 @@ config ISCSI_IBFT_FIND | |||
| 122 | is necessary for iSCSI Boot Firmware Table Attributes module to work | 122 | is necessary for iSCSI Boot Firmware Table Attributes module to work |
| 123 | properly. | 123 | properly. |
| 124 | 124 | ||
| 125 | config ISCSI_BOOT_SYSFS | ||
| 126 | tristate "iSCSI Boot Sysfs Interface" | ||
| 127 | default n | ||
| 128 | help | ||
| 129 | This option enables support for exposing iSCSI boot information | ||
| 130 | via sysfs to userspace. If you wish to export this information, | ||
| 131 | say Y. Otherwise, say N. | ||
| 132 | |||
| 133 | config ISCSI_IBFT | 125 | config ISCSI_IBFT |
| 134 | tristate "iSCSI Boot Firmware Table Attributes module" | 126 | tristate "iSCSI Boot Firmware Table Attributes module" |
| 135 | select ISCSI_BOOT_SYSFS | 127 | select ISCSI_BOOT_SYSFS |
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 5fe7e1662922..1c3c17343dbe 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile | |||
| @@ -10,5 +10,4 @@ obj-$(CONFIG_DCDBAS) += dcdbas.o | |||
| 10 | obj-$(CONFIG_DMIID) += dmi-id.o | 10 | obj-$(CONFIG_DMIID) += dmi-id.o |
| 11 | obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o | 11 | obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o |
| 12 | obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o | 12 | obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o |
| 13 | obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o | ||
| 14 | obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o | 13 | obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index b8f1719d7c02..c425681a1503 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -8049,7 +8049,7 @@ union loginfo_type { | |||
| 8049 | code_desc = ir_code_str[sas_loginfo.dw.code]; | 8049 | code_desc = ir_code_str[sas_loginfo.dw.code]; |
| 8050 | if (sas_loginfo.dw.subcode >= | 8050 | if (sas_loginfo.dw.subcode >= |
| 8051 | ARRAY_SIZE(raid_sub_code_str)) | 8051 | ARRAY_SIZE(raid_sub_code_str)) |
| 8052 | break; | 8052 | break; |
| 8053 | if (sas_loginfo.dw.code == 0) | 8053 | if (sas_loginfo.dw.code == 0) |
| 8054 | sub_code_desc = | 8054 | sub_code_desc = |
| 8055 | raid_sub_code_str[sas_loginfo.dw.subcode]; | 8055 | raid_sub_code_str[sas_loginfo.dw.subcode]; |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 6466231f338b..bbf91aec64f5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -370,6 +370,14 @@ config ISCSI_TCP | |||
| 370 | 370 | ||
| 371 | http://open-iscsi.org | 371 | http://open-iscsi.org |
| 372 | 372 | ||
| 373 | config ISCSI_BOOT_SYSFS | ||
| 374 | tristate "iSCSI Boot Sysfs Interface" | ||
| 375 | default n | ||
| 376 | help | ||
| 377 | This option enables support for exposing iSCSI boot information | ||
| 378 | via sysfs to userspace. If you wish to export this information, | ||
| 379 | say Y. Otherwise, say N. | ||
| 380 | |||
| 373 | source "drivers/scsi/cxgb3i/Kconfig" | 381 | source "drivers/scsi/cxgb3i/Kconfig" |
| 374 | source "drivers/scsi/bnx2i/Kconfig" | 382 | source "drivers/scsi/bnx2i/Kconfig" |
| 375 | source "drivers/scsi/be2iscsi/Kconfig" | 383 | source "drivers/scsi/be2iscsi/Kconfig" |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2a3fca2eca6a..2703c6ec5e36 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
| @@ -42,6 +42,7 @@ obj-$(CONFIG_FCOE) += fcoe/ | |||
| 42 | obj-$(CONFIG_FCOE_FNIC) += fnic/ | 42 | obj-$(CONFIG_FCOE_FNIC) += fnic/ |
| 43 | obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o | 43 | obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o |
| 44 | obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o | 44 | obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o |
| 45 | obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o | ||
| 45 | obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o | 46 | obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o |
| 46 | obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o | 47 | obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o |
| 47 | obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o | 48 | obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o |
diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig index 84c275fb9f6b..ceaca32e788d 100644 --- a/drivers/scsi/be2iscsi/Kconfig +++ b/drivers/scsi/be2iscsi/Kconfig | |||
| @@ -2,6 +2,7 @@ config BE2ISCSI | |||
| 2 | tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" | 2 | tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" |
| 3 | depends on PCI && SCSI && NET | 3 | depends on PCI && SCSI && NET |
| 4 | select SCSI_ISCSI_ATTRS | 4 | select SCSI_ISCSI_ATTRS |
| 5 | select ISCSI_BOOT_SYSFS | ||
| 5 | 6 | ||
| 6 | help | 7 | help |
| 7 | This driver implements the iSCSI functionality for ServerEngines' | 8 | This driver implements the iSCSI functionality for ServerEngines' |
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 40641d0845f4..5218de4ab35a 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
| @@ -162,6 +162,13 @@ struct be_mcc_mailbox { | |||
| 162 | #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 | 162 | #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 |
| 163 | #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 | 163 | #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 |
| 164 | #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 | 164 | #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 |
| 165 | #define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14 | ||
| 166 | #define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17 | ||
| 167 | #define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21 | ||
| 168 | #define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22 | ||
| 169 | #define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23 | ||
| 170 | #define OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID 24 | ||
| 171 | #define OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO 25 | ||
| 165 | #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 | 172 | #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 |
| 166 | #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 | 173 | #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 |
| 167 | #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 | 174 | #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 |
| @@ -237,11 +244,109 @@ struct be_cmd_resp_eq_create { | |||
| 237 | u16 rsvd0; /* sword */ | 244 | u16 rsvd0; /* sword */ |
| 238 | } __packed; | 245 | } __packed; |
| 239 | 246 | ||
| 247 | struct mgmt_chap_format { | ||
| 248 | u32 flags; | ||
| 249 | u8 intr_chap_name[256]; | ||
| 250 | u8 intr_secret[16]; | ||
| 251 | u8 target_chap_name[256]; | ||
| 252 | u8 target_secret[16]; | ||
| 253 | u16 intr_chap_name_length; | ||
| 254 | u16 intr_secret_length; | ||
| 255 | u16 target_chap_name_length; | ||
| 256 | u16 target_secret_length; | ||
| 257 | } __packed; | ||
| 258 | |||
| 259 | struct mgmt_auth_method_format { | ||
| 260 | u8 auth_method_type; | ||
| 261 | u8 padding[3]; | ||
| 262 | struct mgmt_chap_format chap; | ||
| 263 | } __packed; | ||
| 264 | |||
| 265 | struct mgmt_conn_login_options { | ||
| 266 | u8 flags; | ||
| 267 | u8 header_digest; | ||
| 268 | u8 data_digest; | ||
| 269 | u8 rsvd0; | ||
| 270 | u32 max_recv_datasegment_len_ini; | ||
| 271 | u32 max_recv_datasegment_len_tgt; | ||
| 272 | u32 tcp_mss; | ||
| 273 | u32 tcp_window_size; | ||
| 274 | struct mgmt_auth_method_format auth_data; | ||
| 275 | } __packed; | ||
| 276 | |||
| 277 | struct ip_address_format { | ||
| 278 | u16 size_of_structure; | ||
| 279 | u8 reserved; | ||
| 280 | u8 ip_type; | ||
| 281 | u8 ip_address[16]; | ||
| 282 | u32 rsvd0; | ||
| 283 | } __packed; | ||
| 284 | |||
| 285 | struct mgmt_conn_info { | ||
| 286 | u32 connection_handle; | ||
| 287 | u32 connection_status; | ||
| 288 | u16 src_port; | ||
| 289 | u16 dest_port; | ||
| 290 | u16 dest_port_redirected; | ||
| 291 | u16 cid; | ||
| 292 | u32 estimated_throughput; | ||
| 293 | struct ip_address_format src_ipaddr; | ||
| 294 | struct ip_address_format dest_ipaddr; | ||
| 295 | struct ip_address_format dest_ipaddr_redirected; | ||
| 296 | struct mgmt_conn_login_options negotiated_login_options; | ||
| 297 | } __packed; | ||
| 298 | |||
| 299 | struct mgmt_session_login_options { | ||
| 300 | u8 flags; | ||
| 301 | u8 error_recovery_level; | ||
| 302 | u16 rsvd0; | ||
| 303 | u32 first_burst_length; | ||
| 304 | u32 max_burst_length; | ||
| 305 | u16 max_connections; | ||
| 306 | u16 max_outstanding_r2t; | ||
| 307 | u16 default_time2wait; | ||
| 308 | u16 default_time2retain; | ||
| 309 | } __packed; | ||
| 310 | |||
| 311 | struct mgmt_session_info { | ||
| 312 | u32 session_handle; | ||
| 313 | u32 status; | ||
| 314 | u8 isid[6]; | ||
| 315 | u16 tsih; | ||
| 316 | u32 session_flags; | ||
| 317 | u16 conn_count; | ||
| 318 | u16 pad; | ||
| 319 | u8 target_name[224]; | ||
| 320 | u8 initiator_iscsiname[224]; | ||
| 321 | struct mgmt_session_login_options negotiated_login_options; | ||
| 322 | struct mgmt_conn_info conn_list[1]; | ||
| 323 | } __packed; | ||
| 324 | |||
| 325 | struct be_cmd_req_get_session { | ||
| 326 | struct be_cmd_req_hdr hdr; | ||
| 327 | u32 session_handle; | ||
| 328 | } __packed; | ||
| 329 | |||
| 330 | struct be_cmd_resp_get_session { | ||
| 331 | struct be_cmd_resp_hdr hdr; | ||
| 332 | struct mgmt_session_info session_info; | ||
| 333 | } __packed; | ||
| 334 | |||
| 240 | struct mac_addr { | 335 | struct mac_addr { |
| 241 | u16 size_of_struct; | 336 | u16 size_of_struct; |
| 242 | u8 addr[ETH_ALEN]; | 337 | u8 addr[ETH_ALEN]; |
| 243 | } __packed; | 338 | } __packed; |
| 244 | 339 | ||
| 340 | struct be_cmd_req_get_boot_target { | ||
| 341 | struct be_cmd_req_hdr hdr; | ||
| 342 | } __packed; | ||
| 343 | |||
| 344 | struct be_cmd_resp_get_boot_target { | ||
| 345 | struct be_cmd_resp_hdr hdr; | ||
| 346 | u32 boot_session_count; | ||
| 347 | int boot_session_handle; | ||
| 348 | }; | ||
| 349 | |||
| 245 | struct be_cmd_req_mac_query { | 350 | struct be_cmd_req_mac_query { |
| 246 | struct be_cmd_req_hdr hdr; | 351 | struct be_cmd_req_hdr hdr; |
| 247 | u8 type; | 352 | u8 type; |
| @@ -426,6 +531,11 @@ int be_poll_mcc(struct be_ctrl_info *ctrl); | |||
| 426 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | 531 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, |
| 427 | struct beiscsi_hba *phba); | 532 | struct beiscsi_hba *phba); |
| 428 | unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); | 533 | unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); |
| 534 | unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba); | ||
| 535 | unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, | ||
| 536 | u32 boot_session_handle, | ||
| 537 | struct be_dma_mem *nonemb_cmd); | ||
| 538 | |||
| 429 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); | 539 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); |
| 430 | /*ISCSI Functuions */ | 540 | /*ISCSI Functuions */ |
| 431 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | 541 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); |
| @@ -601,14 +711,6 @@ struct be_eq_delay_params_in { | |||
| 601 | struct eq_delay delay[8]; | 711 | struct eq_delay delay[8]; |
| 602 | } __packed; | 712 | } __packed; |
| 603 | 713 | ||
| 604 | struct ip_address_format { | ||
| 605 | u16 size_of_structure; | ||
| 606 | u8 reserved; | ||
| 607 | u8 ip_type; | ||
| 608 | u8 ip_address[16]; | ||
| 609 | u32 rsvd0; | ||
| 610 | } __packed; | ||
| 611 | |||
| 612 | struct tcp_connect_and_offload_in { | 714 | struct tcp_connect_and_offload_in { |
| 613 | struct be_cmd_req_hdr hdr; | 715 | struct be_cmd_req_hdr hdr; |
| 614 | struct ip_address_format ip_address; | 716 | struct ip_address_format ip_address; |
| @@ -688,18 +790,29 @@ struct be_fw_cfg { | |||
| 688 | u32 function_caps; | 790 | u32 function_caps; |
| 689 | } __packed; | 791 | } __packed; |
| 690 | 792 | ||
| 691 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 | 793 | struct be_all_if_id { |
| 692 | #define ISCSI_OPCODE_SCSI_DATA_OUT 5 | 794 | struct be_cmd_req_hdr hdr; |
| 795 | u32 if_count; | ||
| 796 | u32 if_hndl_list[1]; | ||
| 797 | } __packed; | ||
| 798 | |||
| 799 | #define ISCSI_OPCODE_SCSI_DATA_OUT 5 | ||
| 800 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | ||
| 801 | #define OPCODE_COMMON_ISCSI_CLEANUP 59 | ||
| 802 | #define OPCODE_COMMON_TCP_UPLOAD 56 | ||
| 693 | #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 | 803 | #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 |
| 694 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 | ||
| 695 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | ||
| 696 | #define OPCODE_COMMON_ISCSI_CLEANUP 59 | ||
| 697 | #define OPCODE_COMMON_TCP_UPLOAD 56 | ||
| 698 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 | 804 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 |
| 699 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | 805 | #define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME 6 |
| 700 | #define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 | 806 | #define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME 7 |
| 701 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 | 807 | #define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION 14 |
| 808 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 | ||
| 702 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 | 809 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 |
| 810 | #define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 | ||
| 811 | |||
| 812 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | ||
| 813 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 | ||
| 814 | #define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 | ||
| 815 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 | ||
| 703 | 816 | ||
| 704 | #define INI_WR_CMD 1 /* Initiator write command */ | 817 | #define INI_WR_CMD 1 /* Initiator write command */ |
| 705 | #define INI_TMF_CMD 2 /* Initiator TMF command */ | 818 | #define INI_TMF_CMD 2 /* Initiator TMF command */ |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 6d63e7b312cf..7d4d2275573c 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
| @@ -300,40 +300,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
| 300 | enum iscsi_host_param param, char *buf) | 300 | enum iscsi_host_param param, char *buf) |
| 301 | { | 301 | { |
| 302 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 302 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); |
| 303 | struct be_cmd_resp_get_mac_addr *resp; | ||
| 304 | struct be_mcc_wrb *wrb; | ||
| 305 | unsigned int tag, wrb_num; | ||
| 306 | int len = 0; | 303 | int len = 0; |
| 307 | unsigned short status, extd_status; | 304 | int status; |
| 308 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
| 309 | 305 | ||
| 310 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); | 306 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); |
| 311 | switch (param) { | 307 | switch (param) { |
| 312 | case ISCSI_HOST_PARAM_HWADDRESS: | 308 | case ISCSI_HOST_PARAM_HWADDRESS: |
| 313 | tag = be_cmd_get_mac_addr(phba); | 309 | status = beiscsi_get_macaddr(buf, phba); |
| 314 | if (!tag) { | 310 | if (status < 0) { |
| 315 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | 311 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); |
| 316 | return -EAGAIN; | 312 | return status; |
| 317 | } else | ||
| 318 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
| 319 | phba->ctrl.mcc_numtag[tag]); | ||
| 320 | |||
| 321 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
| 322 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
| 323 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
| 324 | if (status || extd_status) { | ||
| 325 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
| 326 | " status = %d extd_status = %d\n", | ||
| 327 | status, extd_status); | ||
| 328 | free_mcc_tag(&phba->ctrl, tag); | ||
| 329 | return -EAGAIN; | ||
| 330 | } else { | ||
| 331 | wrb = queue_get_wrb(mccq, wrb_num); | ||
| 332 | free_mcc_tag(&phba->ctrl, tag); | ||
| 333 | resp = embedded_payload(wrb); | ||
| 334 | memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | ||
| 335 | len = sysfs_format_mac(buf, phba->mac_address, | ||
| 336 | ETH_ALEN); | ||
| 337 | } | 313 | } |
| 338 | break; | 314 | break; |
| 339 | default: | 315 | default: |
| @@ -342,6 +318,48 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
| 342 | return len; | 318 | return len; |
| 343 | } | 319 | } |
| 344 | 320 | ||
| 321 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) | ||
| 322 | { | ||
| 323 | struct be_cmd_resp_get_mac_addr *resp; | ||
| 324 | struct be_mcc_wrb *wrb; | ||
| 325 | unsigned int tag, wrb_num; | ||
| 326 | unsigned short status, extd_status; | ||
| 327 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
| 328 | int rc; | ||
| 329 | |||
| 330 | if (phba->read_mac_address) | ||
| 331 | return sysfs_format_mac(buf, phba->mac_address, | ||
| 332 | ETH_ALEN); | ||
| 333 | |||
| 334 | tag = be_cmd_get_mac_addr(phba); | ||
| 335 | if (!tag) { | ||
| 336 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | ||
| 337 | return -EBUSY; | ||
| 338 | } else | ||
| 339 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
| 340 | phba->ctrl.mcc_numtag[tag]); | ||
| 341 | |||
| 342 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
| 343 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
| 344 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
| 345 | if (status || extd_status) { | ||
| 346 | SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr" | ||
| 347 | " status = %d extd_status = %d\n", | ||
| 348 | status, extd_status); | ||
| 349 | free_mcc_tag(&phba->ctrl, tag); | ||
| 350 | return -EAGAIN; | ||
| 351 | } | ||
| 352 | wrb = queue_get_wrb(mccq, wrb_num); | ||
| 353 | free_mcc_tag(&phba->ctrl, tag); | ||
| 354 | resp = embedded_payload(wrb); | ||
| 355 | memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | ||
| 356 | rc = sysfs_format_mac(buf, phba->mac_address, | ||
| 357 | ETH_ALEN); | ||
| 358 | phba->read_mac_address = 1; | ||
| 359 | return rc; | ||
| 360 | } | ||
| 361 | |||
| 362 | |||
| 345 | /** | 363 | /** |
| 346 | * beiscsi_conn_get_stats - get the iscsi stats | 364 | * beiscsi_conn_get_stats - get the iscsi stats |
| 347 | * @cls_conn: pointer to iscsi cls conn | 365 | * @cls_conn: pointer to iscsi cls conn |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 870cdb2a73e4..8950a702b9f4 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h | |||
| @@ -54,6 +54,8 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
| 54 | int beiscsi_get_host_param(struct Scsi_Host *shost, | 54 | int beiscsi_get_host_param(struct Scsi_Host *shost, |
| 55 | enum iscsi_host_param param, char *buf); | 55 | enum iscsi_host_param param, char *buf); |
| 56 | 56 | ||
| 57 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba); | ||
| 58 | |||
| 57 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | 59 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, |
| 58 | enum iscsi_param param, char *buf, int buflen); | 60 | enum iscsi_param param, char *buf, int buflen); |
| 59 | 61 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7436c5ad5697..8220bde6c04c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/semaphore.h> | 28 | #include <linux/semaphore.h> |
| 29 | #include <linux/iscsi_boot_sysfs.h> | ||
| 29 | 30 | ||
| 30 | #include <scsi/libiscsi.h> | 31 | #include <scsi/libiscsi.h> |
| 31 | #include <scsi/scsi_transport_iscsi.h> | 32 | #include <scsi/scsi_transport_iscsi.h> |
| @@ -211,6 +212,218 @@ unlock: | |||
| 211 | return rc; | 212 | return rc; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 215 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) | ||
| 216 | { | ||
| 217 | struct beiscsi_hba *phba = data; | ||
| 218 | char *str = buf; | ||
| 219 | int rc; | ||
| 220 | |||
| 221 | switch (type) { | ||
| 222 | case ISCSI_BOOT_TGT_NAME: | ||
| 223 | rc = sprintf(buf, "%.*s\n", | ||
| 224 | (int)strlen(phba->boot_sess.target_name), | ||
| 225 | (char *)&phba->boot_sess.target_name); | ||
| 226 | break; | ||
| 227 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 228 | if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) | ||
| 229 | rc = sprintf(buf, "%pI4\n", | ||
| 230 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 231 | dest_ipaddr.ip_address); | ||
| 232 | else | ||
| 233 | rc = sprintf(str, "%pI6\n", | ||
| 234 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 235 | dest_ipaddr.ip_address); | ||
| 236 | break; | ||
| 237 | case ISCSI_BOOT_TGT_PORT: | ||
| 238 | rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. | ||
| 239 | dest_port); | ||
| 240 | break; | ||
| 241 | |||
| 242 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 243 | rc = sprintf(str, "%.*s\n", | ||
| 244 | phba->boot_sess.conn_list[0]. | ||
| 245 | negotiated_login_options.auth_data.chap. | ||
| 246 | target_chap_name_length, | ||
| 247 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 248 | negotiated_login_options.auth_data.chap. | ||
| 249 | target_chap_name); | ||
| 250 | break; | ||
| 251 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 252 | rc = sprintf(str, "%.*s\n", | ||
| 253 | phba->boot_sess.conn_list[0]. | ||
| 254 | negotiated_login_options.auth_data.chap. | ||
| 255 | target_secret_length, | ||
| 256 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 257 | negotiated_login_options.auth_data.chap. | ||
| 258 | target_secret); | ||
| 259 | |||
| 260 | break; | ||
| 261 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 262 | rc = sprintf(str, "%.*s\n", | ||
| 263 | phba->boot_sess.conn_list[0]. | ||
| 264 | negotiated_login_options.auth_data.chap. | ||
| 265 | intr_chap_name_length, | ||
| 266 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 267 | negotiated_login_options.auth_data.chap. | ||
| 268 | intr_chap_name); | ||
| 269 | |||
| 270 | break; | ||
| 271 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 272 | rc = sprintf(str, "%.*s\n", | ||
| 273 | phba->boot_sess.conn_list[0]. | ||
| 274 | negotiated_login_options.auth_data.chap. | ||
| 275 | intr_secret_length, | ||
| 276 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 277 | negotiated_login_options.auth_data.chap. | ||
| 278 | intr_secret); | ||
| 279 | break; | ||
| 280 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 281 | rc = sprintf(str, "2\n"); | ||
| 282 | break; | ||
| 283 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 284 | rc = sprintf(str, "0\n"); | ||
| 285 | break; | ||
| 286 | default: | ||
| 287 | rc = -ENOSYS; | ||
| 288 | break; | ||
| 289 | } | ||
| 290 | return rc; | ||
| 291 | } | ||
| 292 | |||
| 293 | static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) | ||
| 294 | { | ||
| 295 | struct beiscsi_hba *phba = data; | ||
| 296 | char *str = buf; | ||
| 297 | int rc; | ||
| 298 | |||
| 299 | switch (type) { | ||
| 300 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
| 301 | rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); | ||
| 302 | break; | ||
| 303 | default: | ||
| 304 | rc = -ENOSYS; | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | return rc; | ||
| 308 | } | ||
| 309 | |||
| 310 | static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) | ||
| 311 | { | ||
| 312 | struct beiscsi_hba *phba = data; | ||
| 313 | char *str = buf; | ||
| 314 | int rc; | ||
| 315 | |||
| 316 | switch (type) { | ||
| 317 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 318 | rc = sprintf(str, "2\n"); | ||
| 319 | break; | ||
| 320 | case ISCSI_BOOT_ETH_INDEX: | ||
| 321 | rc = sprintf(str, "0\n"); | ||
| 322 | break; | ||
| 323 | case ISCSI_BOOT_ETH_MAC: | ||
| 324 | rc = beiscsi_get_macaddr(buf, phba); | ||
| 325 | if (rc < 0) { | ||
| 326 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); | ||
| 327 | return rc; | ||
| 328 | } | ||
| 329 | break; | ||
| 330 | default: | ||
| 331 | rc = -ENOSYS; | ||
| 332 | break; | ||
| 333 | } | ||
| 334 | return rc; | ||
| 335 | } | ||
| 336 | |||
| 337 | |||
| 338 | static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type) | ||
| 339 | { | ||
| 340 | int rc; | ||
| 341 | |||
| 342 | switch (type) { | ||
| 343 | case ISCSI_BOOT_TGT_NAME: | ||
| 344 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 345 | case ISCSI_BOOT_TGT_PORT: | ||
| 346 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 347 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 348 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 349 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 350 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 351 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 352 | rc = S_IRUGO; | ||
| 353 | break; | ||
| 354 | default: | ||
| 355 | rc = 0; | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | return rc; | ||
| 359 | } | ||
| 360 | |||
| 361 | static mode_t beiscsi_ini_get_attr_visibility(void *data, int type) | ||
| 362 | { | ||
| 363 | int rc; | ||
| 364 | |||
| 365 | switch (type) { | ||
| 366 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
| 367 | rc = S_IRUGO; | ||
| 368 | break; | ||
| 369 | default: | ||
| 370 | rc = 0; | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | return rc; | ||
| 374 | } | ||
| 375 | |||
| 376 | |||
| 377 | static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) | ||
| 378 | { | ||
| 379 | int rc; | ||
| 380 | |||
| 381 | switch (type) { | ||
| 382 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 383 | case ISCSI_BOOT_ETH_MAC: | ||
| 384 | case ISCSI_BOOT_ETH_INDEX: | ||
| 385 | rc = S_IRUGO; | ||
| 386 | break; | ||
| 387 | default: | ||
| 388 | rc = 0; | ||
| 389 | break; | ||
| 390 | } | ||
| 391 | return rc; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) | ||
| 395 | { | ||
| 396 | struct iscsi_boot_kobj *boot_kobj; | ||
| 397 | |||
| 398 | phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); | ||
| 399 | if (!phba->boot_kset) | ||
| 400 | return -ENOMEM; | ||
| 401 | |||
| 402 | /* get boot info using mgmt cmd */ | ||
| 403 | boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, | ||
| 404 | beiscsi_show_boot_tgt_info, | ||
| 405 | beiscsi_tgt_get_attr_visibility); | ||
| 406 | if (!boot_kobj) | ||
| 407 | goto free_kset; | ||
| 408 | |||
| 409 | boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, | ||
| 410 | beiscsi_show_boot_ini_info, | ||
| 411 | beiscsi_ini_get_attr_visibility); | ||
| 412 | if (!boot_kobj) | ||
| 413 | goto free_kset; | ||
| 414 | |||
| 415 | boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, | ||
| 416 | beiscsi_show_boot_eth_info, | ||
| 417 | beiscsi_eth_get_attr_visibility); | ||
| 418 | if (!boot_kobj) | ||
| 419 | goto free_kset; | ||
| 420 | return 0; | ||
| 421 | |||
| 422 | free_kset: | ||
| 423 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
| 424 | return -ENOMEM; | ||
| 425 | } | ||
| 426 | |||
| 214 | /*------------------- PCI Driver operations and data ----------------- */ | 427 | /*------------------- PCI Driver operations and data ----------------- */ |
| 215 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | 428 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { |
| 216 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 429 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
| @@ -268,6 +481,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | |||
| 268 | 481 | ||
| 269 | if (iscsi_host_add(shost, &phba->pcidev->dev)) | 482 | if (iscsi_host_add(shost, &phba->pcidev->dev)) |
| 270 | goto free_devices; | 483 | goto free_devices; |
| 484 | |||
| 485 | if (beiscsi_setup_boot_info(phba)) | ||
| 486 | /* | ||
| 487 | * log error but continue, because we may not be using | ||
| 488 | * iscsi boot. | ||
| 489 | */ | ||
| 490 | shost_printk(KERN_ERR, phba->shost, "Could not set up " | ||
| 491 | "iSCSI boot info."); | ||
| 492 | |||
| 271 | return phba; | 493 | return phba; |
| 272 | 494 | ||
| 273 | free_devices: | 495 | free_devices: |
| @@ -3279,6 +3501,89 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) | |||
| 3279 | "In hwi_disable_intr, Already Disabled\n"); | 3501 | "In hwi_disable_intr, Already Disabled\n"); |
| 3280 | } | 3502 | } |
| 3281 | 3503 | ||
| 3504 | static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | ||
| 3505 | { | ||
| 3506 | struct be_cmd_resp_get_boot_target *boot_resp; | ||
| 3507 | struct be_cmd_resp_get_session *session_resp; | ||
| 3508 | struct be_mcc_wrb *wrb; | ||
| 3509 | struct be_dma_mem nonemb_cmd; | ||
| 3510 | unsigned int tag, wrb_num; | ||
| 3511 | unsigned short status, extd_status; | ||
| 3512 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
| 3513 | |||
| 3514 | tag = beiscsi_get_boot_target(phba); | ||
| 3515 | if (!tag) { | ||
| 3516 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | ||
| 3517 | return -EAGAIN; | ||
| 3518 | } else | ||
| 3519 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
| 3520 | phba->ctrl.mcc_numtag[tag]); | ||
| 3521 | |||
| 3522 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
| 3523 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
| 3524 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
| 3525 | if (status || extd_status) { | ||
| 3526 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
| 3527 | " status = %d extd_status = %d\n", | ||
| 3528 | status, extd_status); | ||
| 3529 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3530 | return -EBUSY; | ||
| 3531 | } | ||
| 3532 | wrb = queue_get_wrb(mccq, wrb_num); | ||
| 3533 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3534 | boot_resp = embedded_payload(wrb); | ||
| 3535 | |||
| 3536 | if (boot_resp->boot_session_handle < 0) { | ||
| 3537 | printk(KERN_ERR "No Boot Session for this pci_func," | ||
| 3538 | "session Hndl = %d\n", boot_resp->boot_session_handle); | ||
| 3539 | return -ENXIO; | ||
| 3540 | } | ||
| 3541 | |||
| 3542 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | ||
| 3543 | sizeof(*session_resp), | ||
| 3544 | &nonemb_cmd.dma); | ||
| 3545 | if (nonemb_cmd.va == NULL) { | ||
| 3546 | SE_DEBUG(DBG_LVL_1, | ||
| 3547 | "Failed to allocate memory for" | ||
| 3548 | "beiscsi_get_session_info\n"); | ||
| 3549 | return -ENOMEM; | ||
| 3550 | } | ||
| 3551 | |||
| 3552 | memset(nonemb_cmd.va, 0, sizeof(*session_resp)); | ||
| 3553 | tag = beiscsi_get_session_info(phba, | ||
| 3554 | boot_resp->boot_session_handle, &nonemb_cmd); | ||
| 3555 | if (!tag) { | ||
| 3556 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" | ||
| 3557 | " Failed\n"); | ||
| 3558 | goto boot_freemem; | ||
| 3559 | } else | ||
| 3560 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
| 3561 | phba->ctrl.mcc_numtag[tag]); | ||
| 3562 | |||
| 3563 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
| 3564 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
| 3565 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
| 3566 | if (status || extd_status) { | ||
| 3567 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed" | ||
| 3568 | " status = %d extd_status = %d\n", | ||
| 3569 | status, extd_status); | ||
| 3570 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3571 | goto boot_freemem; | ||
| 3572 | } | ||
| 3573 | wrb = queue_get_wrb(mccq, wrb_num); | ||
| 3574 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3575 | session_resp = nonemb_cmd.va ; | ||
| 3576 | memcpy(&phba->boot_sess, &session_resp->session_info, | ||
| 3577 | sizeof(struct mgmt_session_info)); | ||
| 3578 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
| 3579 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 3580 | return 0; | ||
| 3581 | boot_freemem: | ||
| 3582 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
| 3583 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 3584 | return -ENOMEM; | ||
| 3585 | } | ||
| 3586 | |||
| 3282 | static int beiscsi_init_port(struct beiscsi_hba *phba) | 3587 | static int beiscsi_init_port(struct beiscsi_hba *phba) |
| 3283 | { | 3588 | { |
| 3284 | int ret; | 3589 | int ret; |
| @@ -3841,6 +4146,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
| 3841 | iscsi_host_remove(phba->shost); | 4146 | iscsi_host_remove(phba->shost); |
| 3842 | pci_dev_put(phba->pcidev); | 4147 | pci_dev_put(phba->pcidev); |
| 3843 | iscsi_host_free(phba->shost); | 4148 | iscsi_host_free(phba->shost); |
| 4149 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
| 3844 | } | 4150 | } |
| 3845 | 4151 | ||
| 3846 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) | 4152 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) |
| @@ -3996,6 +4302,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
| 3996 | goto free_blkenbld; | 4302 | goto free_blkenbld; |
| 3997 | } | 4303 | } |
| 3998 | hwi_enable_intr(phba); | 4304 | hwi_enable_intr(phba); |
| 4305 | ret = beiscsi_get_boot_info(phba); | ||
| 4306 | if (ret < 0) { | ||
| 4307 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
| 4308 | "No Boot Devices !!!!!\n"); | ||
| 4309 | } | ||
| 3999 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); | 4310 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); |
| 4000 | return 0; | 4311 | return 0; |
| 4001 | 4312 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c643bb3736fc..90eb74f6bcab 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #include "be.h" | 36 | #include "be.h" |
| 37 | #define DRV_NAME "be2iscsi" | 37 | #define DRV_NAME "be2iscsi" |
| 38 | #define BUILD_STR "2.0.527.0" | 38 | #define BUILD_STR "2.0.549.0" |
| 39 | #define BE_NAME "ServerEngines BladeEngine2" \ | 39 | #define BE_NAME "ServerEngines BladeEngine2" \ |
| 40 | "Linux iSCSI Driver version" BUILD_STR | 40 | "Linux iSCSI Driver version" BUILD_STR |
| 41 | #define DRV_DESC BE_NAME " " "Driver" | 41 | #define DRV_DESC BE_NAME " " "Driver" |
| @@ -63,7 +63,7 @@ | |||
| 63 | #define BEISCSI_SGLIST_ELEMENTS 30 | 63 | #define BEISCSI_SGLIST_ELEMENTS 30 |
| 64 | 64 | ||
| 65 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | 65 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ |
| 66 | #define BEISCSI_MAX_SECTORS 256 /* scsi_host->max_sectors */ | 66 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ |
| 67 | 67 | ||
| 68 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ | 68 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ |
| 69 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ | 69 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ |
| @@ -312,6 +312,7 @@ struct beiscsi_hba { | |||
| 312 | struct list_head hba_queue; | 312 | struct list_head hba_queue; |
| 313 | unsigned short *cid_array; | 313 | unsigned short *cid_array; |
| 314 | struct iscsi_endpoint **ep_array; | 314 | struct iscsi_endpoint **ep_array; |
| 315 | struct iscsi_boot_kset *boot_kset; | ||
| 315 | struct Scsi_Host *shost; | 316 | struct Scsi_Host *shost; |
| 316 | struct { | 317 | struct { |
| 317 | /** | 318 | /** |
| @@ -342,6 +343,8 @@ struct beiscsi_hba { | |||
| 342 | struct work_struct work_cqs; /* The work being queued */ | 343 | struct work_struct work_cqs; /* The work being queued */ |
| 343 | struct be_ctrl_info ctrl; | 344 | struct be_ctrl_info ctrl; |
| 344 | unsigned int generation; | 345 | unsigned int generation; |
| 346 | unsigned int read_mac_address; | ||
| 347 | struct mgmt_session_info boot_sess; | ||
| 345 | struct invalidate_command_table inv_tbl[128]; | 348 | struct invalidate_command_table inv_tbl[128]; |
| 346 | 349 | ||
| 347 | }; | 350 | }; |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 3f3fab91a7d1..26350e470bcc 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
| @@ -20,6 +20,77 @@ | |||
| 20 | 20 | ||
| 21 | #include "be_mgmt.h" | 21 | #include "be_mgmt.h" |
| 22 | #include "be_iscsi.h" | 22 | #include "be_iscsi.h" |
| 23 | #include <scsi/scsi_transport_iscsi.h> | ||
| 24 | |||
| 25 | unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) | ||
| 26 | { | ||
| 27 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 28 | struct be_mcc_wrb *wrb; | ||
| 29 | struct be_cmd_req_get_mac_addr *req; | ||
| 30 | unsigned int tag = 0; | ||
| 31 | |||
| 32 | SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); | ||
| 33 | spin_lock(&ctrl->mbox_lock); | ||
| 34 | tag = alloc_mcc_tag(phba); | ||
| 35 | if (!tag) { | ||
| 36 | spin_unlock(&ctrl->mbox_lock); | ||
| 37 | return tag; | ||
| 38 | } | ||
| 39 | |||
| 40 | wrb = wrb_from_mccq(phba); | ||
| 41 | req = embedded_payload(wrb); | ||
| 42 | wrb->tag0 |= tag; | ||
| 43 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 44 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 45 | OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, | ||
| 46 | sizeof(*req)); | ||
| 47 | |||
| 48 | be_mcc_notify(phba); | ||
| 49 | spin_unlock(&ctrl->mbox_lock); | ||
| 50 | return tag; | ||
| 51 | } | ||
| 52 | |||
| 53 | unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, | ||
| 54 | u32 boot_session_handle, | ||
| 55 | struct be_dma_mem *nonemb_cmd) | ||
| 56 | { | ||
| 57 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 58 | struct be_mcc_wrb *wrb; | ||
| 59 | unsigned int tag = 0; | ||
| 60 | struct be_cmd_req_get_session *req; | ||
| 61 | struct be_cmd_resp_get_session *resp; | ||
| 62 | struct be_sge *sge; | ||
| 63 | |||
| 64 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n"); | ||
| 65 | spin_lock(&ctrl->mbox_lock); | ||
| 66 | tag = alloc_mcc_tag(phba); | ||
| 67 | if (!tag) { | ||
| 68 | spin_unlock(&ctrl->mbox_lock); | ||
| 69 | return tag; | ||
| 70 | } | ||
| 71 | |||
| 72 | nonemb_cmd->size = sizeof(*resp); | ||
| 73 | req = nonemb_cmd->va; | ||
| 74 | memset(req, 0, sizeof(*req)); | ||
| 75 | wrb = wrb_from_mccq(phba); | ||
| 76 | sge = nonembedded_sgl(wrb); | ||
| 77 | wrb->tag0 |= tag; | ||
| 78 | |||
| 79 | |||
| 80 | wrb->tag0 |= tag; | ||
| 81 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
| 82 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 83 | OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, | ||
| 84 | sizeof(*resp)); | ||
| 85 | req->session_handle = boot_session_handle; | ||
| 86 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
| 87 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
| 88 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
| 89 | |||
| 90 | be_mcc_notify(phba); | ||
| 91 | spin_unlock(&ctrl->mbox_lock); | ||
| 92 | return tag; | ||
| 93 | } | ||
| 23 | 94 | ||
| 24 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, | 95 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, |
| 25 | struct beiscsi_hba *phba) | 96 | struct beiscsi_hba *phba) |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bd96cecaa619..9f75a6d519a2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
| @@ -433,6 +433,9 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, | |||
| 433 | { | 433 | { |
| 434 | switch (tgt->action) { | 434 | switch (tgt->action) { |
| 435 | case IBMVFC_TGT_ACTION_DEL_RPORT: | 435 | case IBMVFC_TGT_ACTION_DEL_RPORT: |
| 436 | if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) | ||
| 437 | tgt->action = action; | ||
| 438 | case IBMVFC_TGT_ACTION_DELETED_RPORT: | ||
| 436 | break; | 439 | break; |
| 437 | default: | 440 | default: |
| 438 | if (action == IBMVFC_TGT_ACTION_DEL_RPORT) | 441 | if (action == IBMVFC_TGT_ACTION_DEL_RPORT) |
| @@ -2036,95 +2039,108 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) | |||
| 2036 | } | 2039 | } |
| 2037 | 2040 | ||
| 2038 | /** | 2041 | /** |
| 2039 | * ibmvfc_abort_task_set - Abort outstanding commands to the device | 2042 | * ibmvfc_match_rport - Match function for specified remote port |
| 2040 | * @sdev: scsi device to abort commands | 2043 | * @evt: ibmvfc event struct |
| 2041 | * | 2044 | * @device: device to match (rport) |
| 2042 | * This sends an Abort Task Set to the VIOS for the specified device. This does | ||
| 2043 | * NOT send any cancel to the VIOS. That must be done separately. | ||
| 2044 | * | 2045 | * |
| 2045 | * Returns: | 2046 | * Returns: |
| 2046 | * 0 on success / other on failure | 2047 | * 1 if event matches rport / 0 if event does not match rport |
| 2047 | **/ | 2048 | **/ |
| 2048 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) | 2049 | static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) |
| 2049 | { | 2050 | { |
| 2050 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2051 | struct fc_rport *cmd_rport; |
| 2051 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | ||
| 2052 | struct ibmvfc_cmd *tmf; | ||
| 2053 | struct ibmvfc_event *evt, *found_evt; | ||
| 2054 | union ibmvfc_iu rsp_iu; | ||
| 2055 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
| 2056 | int rsp_rc = -EBUSY; | ||
| 2057 | unsigned long flags; | ||
| 2058 | int rsp_code = 0; | ||
| 2059 | 2052 | ||
| 2060 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2053 | if (evt->cmnd) { |
| 2061 | found_evt = NULL; | 2054 | cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); |
| 2062 | list_for_each_entry(evt, &vhost->sent, queue) { | 2055 | if (cmd_rport == rport) |
| 2063 | if (evt->cmnd && evt->cmnd->device == sdev) { | 2056 | return 1; |
| 2064 | found_evt = evt; | ||
| 2065 | break; | ||
| 2066 | } | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | if (!found_evt) { | ||
| 2070 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
| 2071 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
| 2072 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 2073 | return 0; | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | if (vhost->state == IBMVFC_ACTIVE) { | ||
| 2077 | evt = ibmvfc_get_event(vhost); | ||
| 2078 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
| 2079 | |||
| 2080 | tmf = &evt->iu.cmd; | ||
| 2081 | memset(tmf, 0, sizeof(*tmf)); | ||
| 2082 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); | ||
| 2083 | tmf->resp.len = sizeof(tmf->rsp); | ||
| 2084 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; | ||
| 2085 | tmf->payload_len = sizeof(tmf->iu); | ||
| 2086 | tmf->resp_len = sizeof(tmf->rsp); | ||
| 2087 | tmf->cancel_key = (unsigned long)sdev->hostdata; | ||
| 2088 | tmf->tgt_scsi_id = rport->port_id; | ||
| 2089 | int_to_scsilun(sdev->lun, &tmf->iu.lun); | ||
| 2090 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); | ||
| 2091 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; | ||
| 2092 | evt->sync_iu = &rsp_iu; | ||
| 2093 | |||
| 2094 | init_completion(&evt->comp); | ||
| 2095 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
| 2096 | } | 2057 | } |
| 2058 | return 0; | ||
| 2059 | } | ||
| 2097 | 2060 | ||
| 2098 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2061 | /** |
| 2062 | * ibmvfc_match_target - Match function for specified target | ||
| 2063 | * @evt: ibmvfc event struct | ||
| 2064 | * @device: device to match (starget) | ||
| 2065 | * | ||
| 2066 | * Returns: | ||
| 2067 | * 1 if event matches starget / 0 if event does not match starget | ||
| 2068 | **/ | ||
| 2069 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | ||
| 2070 | { | ||
| 2071 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | ||
| 2072 | return 1; | ||
| 2073 | return 0; | ||
| 2074 | } | ||
| 2099 | 2075 | ||
| 2100 | if (rsp_rc != 0) { | 2076 | /** |
| 2101 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | 2077 | * ibmvfc_match_lun - Match function for specified LUN |
| 2102 | return -EIO; | 2078 | * @evt: ibmvfc event struct |
| 2103 | } | 2079 | * @device: device to match (sdev) |
| 2080 | * | ||
| 2081 | * Returns: | ||
| 2082 | * 1 if event matches sdev / 0 if event does not match sdev | ||
| 2083 | **/ | ||
| 2084 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
| 2085 | { | ||
| 2086 | if (evt->cmnd && evt->cmnd->device == device) | ||
| 2087 | return 1; | ||
| 2088 | return 0; | ||
| 2089 | } | ||
| 2104 | 2090 | ||
| 2105 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | 2091 | /** |
| 2106 | wait_for_completion(&evt->comp); | 2092 | * ibmvfc_wait_for_ops - Wait for ops to complete |
| 2093 | * @vhost: ibmvfc host struct | ||
| 2094 | * @device: device to match (starget or sdev) | ||
| 2095 | * @match: match function | ||
| 2096 | * | ||
| 2097 | * Returns: | ||
| 2098 | * SUCCESS / FAILED | ||
| 2099 | **/ | ||
| 2100 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | ||
| 2101 | int (*match) (struct ibmvfc_event *, void *)) | ||
| 2102 | { | ||
| 2103 | struct ibmvfc_event *evt; | ||
| 2104 | DECLARE_COMPLETION_ONSTACK(comp); | ||
| 2105 | int wait; | ||
| 2106 | unsigned long flags; | ||
| 2107 | signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; | ||
| 2107 | 2108 | ||
| 2108 | if (rsp_iu.cmd.status) | 2109 | ENTER; |
| 2109 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | 2110 | do { |
| 2111 | wait = 0; | ||
| 2112 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
| 2113 | list_for_each_entry(evt, &vhost->sent, queue) { | ||
| 2114 | if (match(evt, device)) { | ||
| 2115 | evt->eh_comp = ∁ | ||
| 2116 | wait++; | ||
| 2117 | } | ||
| 2118 | } | ||
| 2119 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 2110 | 2120 | ||
| 2111 | if (rsp_code) { | 2121 | if (wait) { |
| 2112 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | 2122 | timeout = wait_for_completion_timeout(&comp, timeout); |
| 2113 | rsp_code = fc_rsp->data.info.rsp_code; | ||
| 2114 | 2123 | ||
| 2115 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | 2124 | if (!timeout) { |
| 2116 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | 2125 | wait = 0; |
| 2117 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | 2126 | spin_lock_irqsave(vhost->host->host_lock, flags); |
| 2118 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | 2127 | list_for_each_entry(evt, &vhost->sent, queue) { |
| 2119 | fc_rsp->scsi_status); | 2128 | if (match(evt, device)) { |
| 2120 | rsp_rc = -EIO; | 2129 | evt->eh_comp = NULL; |
| 2121 | } else | 2130 | wait++; |
| 2122 | sdev_printk(KERN_INFO, sdev, "Abort successful\n"); | 2131 | } |
| 2132 | } | ||
| 2133 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 2134 | if (wait) | ||
| 2135 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | ||
| 2136 | LEAVE; | ||
| 2137 | return wait ? FAILED : SUCCESS; | ||
| 2138 | } | ||
| 2139 | } | ||
| 2140 | } while (wait); | ||
| 2123 | 2141 | ||
| 2124 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2142 | LEAVE; |
| 2125 | ibmvfc_free_event(evt); | 2143 | return SUCCESS; |
| 2126 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 2127 | return rsp_rc; | ||
| 2128 | } | 2144 | } |
| 2129 | 2145 | ||
| 2130 | /** | 2146 | /** |
| @@ -2212,88 +2228,130 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) | |||
| 2212 | } | 2228 | } |
| 2213 | 2229 | ||
| 2214 | /** | 2230 | /** |
| 2215 | * ibmvfc_match_target - Match function for specified target | 2231 | * ibmvfc_match_key - Match function for specified cancel key |
| 2216 | * @evt: ibmvfc event struct | 2232 | * @evt: ibmvfc event struct |
| 2217 | * @device: device to match (starget) | 2233 | * @key: cancel key to match |
| 2218 | * | 2234 | * |
| 2219 | * Returns: | 2235 | * Returns: |
| 2220 | * 1 if event matches starget / 0 if event does not match starget | 2236 | * 1 if event matches key / 0 if event does not match key |
| 2221 | **/ | 2237 | **/ |
| 2222 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | 2238 | static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) |
| 2223 | { | 2239 | { |
| 2224 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | 2240 | unsigned long cancel_key = (unsigned long)key; |
| 2225 | return 1; | ||
| 2226 | return 0; | ||
| 2227 | } | ||
| 2228 | 2241 | ||
| 2229 | /** | 2242 | if (evt->crq.format == IBMVFC_CMD_FORMAT && |
| 2230 | * ibmvfc_match_lun - Match function for specified LUN | 2243 | evt->iu.cmd.cancel_key == cancel_key) |
| 2231 | * @evt: ibmvfc event struct | ||
| 2232 | * @device: device to match (sdev) | ||
| 2233 | * | ||
| 2234 | * Returns: | ||
| 2235 | * 1 if event matches sdev / 0 if event does not match sdev | ||
| 2236 | **/ | ||
| 2237 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
| 2238 | { | ||
| 2239 | if (evt->cmnd && evt->cmnd->device == device) | ||
| 2240 | return 1; | 2244 | return 1; |
| 2241 | return 0; | 2245 | return 0; |
| 2242 | } | 2246 | } |
| 2243 | 2247 | ||
| 2244 | /** | 2248 | /** |
| 2245 | * ibmvfc_wait_for_ops - Wait for ops to complete | 2249 | * ibmvfc_abort_task_set - Abort outstanding commands to the device |
| 2246 | * @vhost: ibmvfc host struct | 2250 | * @sdev: scsi device to abort commands |
| 2247 | * @device: device to match (starget or sdev) | 2251 | * |
| 2248 | * @match: match function | 2252 | * This sends an Abort Task Set to the VIOS for the specified device. This does |
| 2253 | * NOT send any cancel to the VIOS. That must be done separately. | ||
| 2249 | * | 2254 | * |
| 2250 | * Returns: | 2255 | * Returns: |
| 2251 | * SUCCESS / FAILED | 2256 | * 0 on success / other on failure |
| 2252 | **/ | 2257 | **/ |
| 2253 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | 2258 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) |
| 2254 | int (*match) (struct ibmvfc_event *, void *)) | ||
| 2255 | { | 2259 | { |
| 2256 | struct ibmvfc_event *evt; | 2260 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
| 2257 | DECLARE_COMPLETION_ONSTACK(comp); | 2261 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
| 2258 | int wait; | 2262 | struct ibmvfc_cmd *tmf; |
| 2259 | unsigned long flags; | 2263 | struct ibmvfc_event *evt, *found_evt; |
| 2260 | signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; | 2264 | union ibmvfc_iu rsp_iu; |
| 2265 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
| 2266 | int rc, rsp_rc = -EBUSY; | ||
| 2267 | unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; | ||
| 2268 | int rsp_code = 0; | ||
| 2261 | 2269 | ||
| 2262 | ENTER; | 2270 | spin_lock_irqsave(vhost->host->host_lock, flags); |
| 2263 | do { | 2271 | found_evt = NULL; |
| 2264 | wait = 0; | 2272 | list_for_each_entry(evt, &vhost->sent, queue) { |
| 2265 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2273 | if (evt->cmnd && evt->cmnd->device == sdev) { |
| 2266 | list_for_each_entry(evt, &vhost->sent, queue) { | 2274 | found_evt = evt; |
| 2267 | if (match(evt, device)) { | 2275 | break; |
| 2268 | evt->eh_comp = ∁ | ||
| 2269 | wait++; | ||
| 2270 | } | ||
| 2271 | } | 2276 | } |
| 2277 | } | ||
| 2278 | |||
| 2279 | if (!found_evt) { | ||
| 2280 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
| 2281 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
| 2272 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2282 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
| 2283 | return 0; | ||
| 2284 | } | ||
| 2273 | 2285 | ||
| 2274 | if (wait) { | 2286 | if (vhost->state == IBMVFC_ACTIVE) { |
| 2275 | timeout = wait_for_completion_timeout(&comp, timeout); | 2287 | evt = ibmvfc_get_event(vhost); |
| 2288 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
| 2276 | 2289 | ||
| 2277 | if (!timeout) { | 2290 | tmf = &evt->iu.cmd; |
| 2278 | wait = 0; | 2291 | memset(tmf, 0, sizeof(*tmf)); |
| 2279 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2292 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); |
| 2280 | list_for_each_entry(evt, &vhost->sent, queue) { | 2293 | tmf->resp.len = sizeof(tmf->rsp); |
| 2281 | if (match(evt, device)) { | 2294 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; |
| 2282 | evt->eh_comp = NULL; | 2295 | tmf->payload_len = sizeof(tmf->iu); |
| 2283 | wait++; | 2296 | tmf->resp_len = sizeof(tmf->rsp); |
| 2284 | } | 2297 | tmf->cancel_key = (unsigned long)sdev->hostdata; |
| 2285 | } | 2298 | tmf->tgt_scsi_id = rport->port_id; |
| 2286 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2299 | int_to_scsilun(sdev->lun, &tmf->iu.lun); |
| 2287 | if (wait) | 2300 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); |
| 2288 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | 2301 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; |
| 2289 | LEAVE; | 2302 | evt->sync_iu = &rsp_iu; |
| 2290 | return wait ? FAILED : SUCCESS; | 2303 | |
| 2291 | } | 2304 | init_completion(&evt->comp); |
| 2305 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
| 2306 | } | ||
| 2307 | |||
| 2308 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 2309 | |||
| 2310 | if (rsp_rc != 0) { | ||
| 2311 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | ||
| 2312 | return -EIO; | ||
| 2313 | } | ||
| 2314 | |||
| 2315 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | ||
| 2316 | timeout = wait_for_completion_timeout(&evt->comp, timeout); | ||
| 2317 | |||
| 2318 | if (!timeout) { | ||
| 2319 | rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
| 2320 | if (!rc) { | ||
| 2321 | rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); | ||
| 2322 | if (rc == SUCCESS) | ||
| 2323 | rc = 0; | ||
| 2292 | } | 2324 | } |
| 2293 | } while (wait); | ||
| 2294 | 2325 | ||
| 2295 | LEAVE; | 2326 | if (rc) { |
| 2296 | return SUCCESS; | 2327 | sdev_printk(KERN_INFO, sdev, "Cancel failed, resetting host\n"); |
| 2328 | ibmvfc_reset_host(vhost); | ||
| 2329 | rsp_rc = 0; | ||
| 2330 | goto out; | ||
| 2331 | } | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | if (rsp_iu.cmd.status) | ||
| 2335 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | ||
| 2336 | |||
| 2337 | if (rsp_code) { | ||
| 2338 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | ||
| 2339 | rsp_code = fc_rsp->data.info.rsp_code; | ||
| 2340 | |||
| 2341 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | ||
| 2342 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | ||
| 2343 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | ||
| 2344 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | ||
| 2345 | fc_rsp->scsi_status); | ||
| 2346 | rsp_rc = -EIO; | ||
| 2347 | } else | ||
| 2348 | sdev_printk(KERN_INFO, sdev, "Abort successful\n"); | ||
| 2349 | |||
| 2350 | out: | ||
| 2351 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
| 2352 | ibmvfc_free_event(evt); | ||
| 2353 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 2354 | return rsp_rc; | ||
| 2297 | } | 2355 | } |
| 2298 | 2356 | ||
| 2299 | /** | 2357 | /** |
| @@ -2351,18 +2409,6 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
| 2351 | } | 2409 | } |
| 2352 | 2410 | ||
| 2353 | /** | 2411 | /** |
| 2354 | * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function | ||
| 2355 | * @sdev: scsi device struct | ||
| 2356 | * @data: return code | ||
| 2357 | * | ||
| 2358 | **/ | ||
| 2359 | static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) | ||
| 2360 | { | ||
| 2361 | unsigned long *rc = data; | ||
| 2362 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | /** | ||
| 2366 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | 2412 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function |
| 2367 | * @sdev: scsi device struct | 2413 | * @sdev: scsi device struct |
| 2368 | * @data: return code | 2414 | * @data: return code |
| @@ -2375,18 +2421,6 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | |||
| 2375 | } | 2421 | } |
| 2376 | 2422 | ||
| 2377 | /** | 2423 | /** |
| 2378 | * ibmvfc_dev_abort_all - Device iterated abort task set function | ||
| 2379 | * @sdev: scsi device struct | ||
| 2380 | * @data: return code | ||
| 2381 | * | ||
| 2382 | **/ | ||
| 2383 | static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data) | ||
| 2384 | { | ||
| 2385 | unsigned long *rc = data; | ||
| 2386 | *rc |= ibmvfc_abort_task_set(sdev); | ||
| 2387 | } | ||
| 2388 | |||
| 2389 | /** | ||
| 2390 | * ibmvfc_eh_target_reset_handler - Reset the target | 2424 | * ibmvfc_eh_target_reset_handler - Reset the target |
| 2391 | * @cmd: scsi command struct | 2425 | * @cmd: scsi command struct |
| 2392 | * | 2426 | * |
| @@ -2440,19 +2474,22 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | |||
| 2440 | **/ | 2474 | **/ |
| 2441 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) | 2475 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) |
| 2442 | { | 2476 | { |
| 2443 | struct scsi_target *starget = to_scsi_target(&rport->dev); | 2477 | struct Scsi_Host *shost = rport_to_shost(rport); |
| 2444 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
| 2445 | struct ibmvfc_host *vhost = shost_priv(shost); | 2478 | struct ibmvfc_host *vhost = shost_priv(shost); |
| 2446 | unsigned long cancel_rc = 0; | 2479 | struct fc_rport *dev_rport; |
| 2447 | unsigned long abort_rc = 0; | 2480 | struct scsi_device *sdev; |
| 2448 | int rc = FAILED; | 2481 | unsigned long rc; |
| 2449 | 2482 | ||
| 2450 | ENTER; | 2483 | ENTER; |
| 2451 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); | 2484 | shost_for_each_device(sdev, shost) { |
| 2452 | starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); | 2485 | dev_rport = starget_to_rport(scsi_target(sdev)); |
| 2486 | if (dev_rport != rport) | ||
| 2487 | continue; | ||
| 2488 | ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
| 2489 | ibmvfc_abort_task_set(sdev); | ||
| 2490 | } | ||
| 2453 | 2491 | ||
| 2454 | if (!cancel_rc && !abort_rc) | 2492 | rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); |
| 2455 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); | ||
| 2456 | 2493 | ||
| 2457 | if (rc == FAILED) | 2494 | if (rc == FAILED) |
| 2458 | ibmvfc_issue_fc_host_lip(shost); | 2495 | ibmvfc_issue_fc_host_lip(shost); |
| @@ -4193,11 +4230,15 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) | |||
| 4193 | if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { | 4230 | if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { |
| 4194 | tgt_dbg(tgt, "Deleting rport\n"); | 4231 | tgt_dbg(tgt, "Deleting rport\n"); |
| 4195 | list_del(&tgt->queue); | 4232 | list_del(&tgt->queue); |
| 4233 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); | ||
| 4196 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4234 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
| 4197 | fc_remote_port_delete(rport); | 4235 | fc_remote_port_delete(rport); |
| 4198 | del_timer_sync(&tgt->timer); | 4236 | del_timer_sync(&tgt->timer); |
| 4199 | kref_put(&tgt->kref, ibmvfc_release_tgt); | 4237 | kref_put(&tgt->kref, ibmvfc_release_tgt); |
| 4200 | return; | 4238 | return; |
| 4239 | } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { | ||
| 4240 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
| 4241 | return; | ||
| 4201 | } | 4242 | } |
| 4202 | 4243 | ||
| 4203 | if (rport) { | 4244 | if (rport) { |
| @@ -4297,6 +4338,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) | |||
| 4297 | rport = tgt->rport; | 4338 | rport = tgt->rport; |
| 4298 | tgt->rport = NULL; | 4339 | tgt->rport = NULL; |
| 4299 | list_del(&tgt->queue); | 4340 | list_del(&tgt->queue); |
| 4341 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); | ||
| 4300 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4342 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
| 4301 | if (rport) | 4343 | if (rport) |
| 4302 | fc_remote_port_delete(rport); | 4344 | fc_remote_port_delete(rport); |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index d7e8dcd90650..608af394c8cf 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h | |||
| @@ -29,8 +29,8 @@ | |||
| 29 | #include "viosrp.h" | 29 | #include "viosrp.h" |
| 30 | 30 | ||
| 31 | #define IBMVFC_NAME "ibmvfc" | 31 | #define IBMVFC_NAME "ibmvfc" |
| 32 | #define IBMVFC_DRIVER_VERSION "1.0.8" | 32 | #define IBMVFC_DRIVER_VERSION "1.0.9" |
| 33 | #define IBMVFC_DRIVER_DATE "(June 17, 2010)" | 33 | #define IBMVFC_DRIVER_DATE "(August 5, 2010)" |
| 34 | 34 | ||
| 35 | #define IBMVFC_DEFAULT_TIMEOUT 60 | 35 | #define IBMVFC_DEFAULT_TIMEOUT 60 |
| 36 | #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 | 36 | #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 |
| @@ -38,6 +38,7 @@ | |||
| 38 | #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \ | 38 | #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \ |
| 39 | (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT) | 39 | (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT) |
| 40 | #define IBMVFC_INIT_TIMEOUT 120 | 40 | #define IBMVFC_INIT_TIMEOUT 120 |
| 41 | #define IBMVFC_ABORT_TIMEOUT 8 | ||
| 41 | #define IBMVFC_ABORT_WAIT_TIMEOUT 40 | 42 | #define IBMVFC_ABORT_WAIT_TIMEOUT 40 |
| 42 | #define IBMVFC_MAX_REQUESTS_DEFAULT 100 | 43 | #define IBMVFC_MAX_REQUESTS_DEFAULT 100 |
| 43 | 44 | ||
| @@ -597,6 +598,7 @@ enum ibmvfc_target_action { | |||
| 597 | IBMVFC_TGT_ACTION_INIT, | 598 | IBMVFC_TGT_ACTION_INIT, |
| 598 | IBMVFC_TGT_ACTION_INIT_WAIT, | 599 | IBMVFC_TGT_ACTION_INIT_WAIT, |
| 599 | IBMVFC_TGT_ACTION_DEL_RPORT, | 600 | IBMVFC_TGT_ACTION_DEL_RPORT, |
| 601 | IBMVFC_TGT_ACTION_DELETED_RPORT, | ||
| 600 | }; | 602 | }; |
| 601 | 603 | ||
| 602 | struct ibmvfc_target { | 604 | struct ibmvfc_target { |
diff --git a/drivers/firmware/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c index df6bff7366cf..df6bff7366cf 100644 --- a/drivers/firmware/iscsi_boot_sysfs.c +++ b/drivers/scsi/iscsi_boot_sysfs.c | |||
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index eac4d09314eb..c797f6b48f05 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
| @@ -1765,14 +1765,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) | |||
| 1765 | struct fcoe_dev_stats *stats; | 1765 | struct fcoe_dev_stats *stats; |
| 1766 | 1766 | ||
| 1767 | lport = shost_priv(sc_cmd->device->host); | 1767 | lport = shost_priv(sc_cmd->device->host); |
| 1768 | spin_unlock_irq(lport->host->host_lock); | ||
| 1769 | 1768 | ||
| 1770 | rval = fc_remote_port_chkready(rport); | 1769 | rval = fc_remote_port_chkready(rport); |
| 1771 | if (rval) { | 1770 | if (rval) { |
| 1772 | sc_cmd->result = rval; | 1771 | sc_cmd->result = rval; |
| 1773 | done(sc_cmd); | 1772 | done(sc_cmd); |
| 1774 | goto out; | 1773 | return 0; |
| 1775 | } | 1774 | } |
| 1775 | spin_unlock_irq(lport->host->host_lock); | ||
| 1776 | 1776 | ||
| 1777 | if (!*(struct fc_remote_port **)rport->dd_data) { | 1777 | if (!*(struct fc_remote_port **)rport->dd_data) { |
| 1778 | /* | 1778 | /* |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3482d5a5aed2..a50aa03b8ac1 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -775,6 +775,7 @@ struct lpfc_hba { | |||
| 775 | uint8_t temp_sensor_support; | 775 | uint8_t temp_sensor_support; |
| 776 | /* Fields used for heart beat. */ | 776 | /* Fields used for heart beat. */ |
| 777 | unsigned long last_completion_time; | 777 | unsigned long last_completion_time; |
| 778 | unsigned long skipped_hb; | ||
| 778 | struct timer_list hb_tmofunc; | 779 | struct timer_list hb_tmofunc; |
| 779 | uint8_t hb_outstanding; | 780 | uint8_t hb_outstanding; |
| 780 | enum hba_temp_state over_temp_state; | 781 | enum hba_temp_state over_temp_state; |
| @@ -817,6 +818,8 @@ struct lpfc_hba { | |||
| 817 | uint32_t iocb_cnt; | 818 | uint32_t iocb_cnt; |
| 818 | uint32_t iocb_max; | 819 | uint32_t iocb_max; |
| 819 | atomic_t sdev_cnt; | 820 | atomic_t sdev_cnt; |
| 821 | uint8_t fips_spec_rev; | ||
| 822 | uint8_t fips_level; | ||
| 820 | }; | 823 | }; |
| 821 | 824 | ||
| 822 | static inline struct Scsi_Host * | 825 | static inline struct Scsi_Host * |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ad05b266e950..23ce45708335 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
| @@ -1240,6 +1240,44 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, | |||
| 1240 | } | 1240 | } |
| 1241 | 1241 | ||
| 1242 | /** | 1242 | /** |
| 1243 | * lpfc_fips_level_show - Return the current FIPS level for the HBA | ||
| 1244 | * @dev: class unused variable. | ||
| 1245 | * @attr: device attribute, not used. | ||
| 1246 | * @buf: on return contains the module description text. | ||
| 1247 | * | ||
| 1248 | * Returns: size of formatted string. | ||
| 1249 | **/ | ||
| 1250 | static ssize_t | ||
| 1251 | lpfc_fips_level_show(struct device *dev, struct device_attribute *attr, | ||
| 1252 | char *buf) | ||
| 1253 | { | ||
| 1254 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 1255 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
| 1256 | struct lpfc_hba *phba = vport->phba; | ||
| 1257 | |||
| 1258 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | /** | ||
| 1262 | * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA | ||
| 1263 | * @dev: class unused variable. | ||
| 1264 | * @attr: device attribute, not used. | ||
| 1265 | * @buf: on return contains the module description text. | ||
| 1266 | * | ||
| 1267 | * Returns: size of formatted string. | ||
| 1268 | **/ | ||
| 1269 | static ssize_t | ||
| 1270 | lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, | ||
| 1271 | char *buf) | ||
| 1272 | { | ||
| 1273 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 1274 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
| 1275 | struct lpfc_hba *phba = vport->phba; | ||
| 1276 | |||
| 1277 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | /** | ||
| 1243 | * lpfc_param_show - Return a cfg attribute value in decimal | 1281 | * lpfc_param_show - Return a cfg attribute value in decimal |
| 1244 | * | 1282 | * |
| 1245 | * Description: | 1283 | * Description: |
| @@ -1677,6 +1715,8 @@ static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); | |||
| 1677 | static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); | 1715 | static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); |
| 1678 | static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); | 1716 | static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); |
| 1679 | static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); | 1717 | static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); |
| 1718 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); | ||
| 1719 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); | ||
| 1680 | 1720 | ||
| 1681 | 1721 | ||
| 1682 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; | 1722 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
| @@ -3278,7 +3318,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); | |||
| 3278 | # - Default will result in registering capabilities for all profiles. | 3318 | # - Default will result in registering capabilities for all profiles. |
| 3279 | # | 3319 | # |
| 3280 | */ | 3320 | */ |
| 3281 | unsigned int lpfc_prot_mask = SHOST_DIX_TYPE0_PROTECTION; | 3321 | unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; |
| 3282 | 3322 | ||
| 3283 | module_param(lpfc_prot_mask, uint, 0); | 3323 | module_param(lpfc_prot_mask, uint, 0); |
| 3284 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); | 3324 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); |
| @@ -3383,6 +3423,8 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
| 3383 | &dev_attr_iocb_hw, | 3423 | &dev_attr_iocb_hw, |
| 3384 | &dev_attr_txq_hw, | 3424 | &dev_attr_txq_hw, |
| 3385 | &dev_attr_txcmplq_hw, | 3425 | &dev_attr_txcmplq_hw, |
| 3426 | &dev_attr_lpfc_fips_level, | ||
| 3427 | &dev_attr_lpfc_fips_rev, | ||
| 3386 | NULL, | 3428 | NULL, |
| 3387 | }; | 3429 | }; |
| 3388 | 3430 | ||
| @@ -3409,6 +3451,8 @@ struct device_attribute *lpfc_vport_attrs[] = { | |||
| 3409 | &dev_attr_lpfc_max_scsicmpl_time, | 3451 | &dev_attr_lpfc_max_scsicmpl_time, |
| 3410 | &dev_attr_lpfc_stat_data_ctrl, | 3452 | &dev_attr_lpfc_stat_data_ctrl, |
| 3411 | &dev_attr_lpfc_static_vport, | 3453 | &dev_attr_lpfc_static_vport, |
| 3454 | &dev_attr_lpfc_fips_level, | ||
| 3455 | &dev_attr_lpfc_fips_rev, | ||
| 3412 | NULL, | 3456 | NULL, |
| 3413 | }; | 3457 | }; |
| 3414 | 3458 | ||
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index d521569e6620..49d0cf99c24c 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
| @@ -2724,15 +2724,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2724 | 2724 | ||
| 2725 | pmboxq->context2 = ext; | 2725 | pmboxq->context2 = ext; |
| 2726 | pmboxq->in_ext_byte_len = | 2726 | pmboxq->in_ext_byte_len = |
| 2727 | mbox_req->inExtWLen * | ||
| 2728 | sizeof(uint32_t); | ||
| 2729 | pmboxq->out_ext_byte_len = | ||
| 2730 | mbox_req->outExtWLen * | ||
| 2731 | sizeof(uint32_t); | ||
| 2732 | pmboxq->mbox_offset_word = | ||
| 2733 | mbox_req->mbOffset; | ||
| 2734 | pmboxq->context2 = ext; | ||
| 2735 | pmboxq->in_ext_byte_len = | ||
| 2736 | mbox_req->inExtWLen * sizeof(uint32_t); | 2727 | mbox_req->inExtWLen * sizeof(uint32_t); |
| 2737 | pmboxq->out_ext_byte_len = | 2728 | pmboxq->out_ext_byte_len = |
| 2738 | mbox_req->outExtWLen * sizeof(uint32_t); | 2729 | mbox_req->outExtWLen * sizeof(uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h index a11f1ae7b98e..75e2e569dede 100644 --- a/drivers/scsi/lpfc/lpfc_compat.h +++ b/drivers/scsi/lpfc/lpfc_compat.h | |||
| @@ -82,8 +82,7 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) | |||
| 82 | static inline void | 82 | static inline void |
| 83 | lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) | 83 | lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) |
| 84 | { | 84 | { |
| 85 | /* actually returns 1 byte past dest */ | 85 | __iowrite32_copy(dest, src, bytes); |
| 86 | memcpy_toio( dest, src, bytes); | ||
| 87 | } | 86 | } |
| 88 | 87 | ||
| 89 | static inline void | 88 | static inline void |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index afbed6bc31f0..8d09191c327e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -600,6 +600,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 600 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 600 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
| 601 | spin_unlock_irq(shost->host_lock); | 601 | spin_unlock_irq(shost->host_lock); |
| 602 | } | 602 | } |
| 603 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
| 604 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { | ||
| 605 | /* | ||
| 606 | * Driver needs to re-reg VPI in order for f/w | ||
| 607 | * to update the MAC address. | ||
| 608 | */ | ||
| 609 | lpfc_register_new_vport(phba, vport, ndlp); | ||
| 610 | return 0; | ||
| 603 | } | 611 | } |
| 604 | 612 | ||
| 605 | if (phba->sli_rev < LPFC_SLI_REV4) { | 613 | if (phba->sli_rev < LPFC_SLI_REV4) { |
| @@ -801,9 +809,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 801 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { | 809 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { |
| 802 | lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, | 810 | lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, |
| 803 | "2611 FLOGI failed on registered " | 811 | "2611 FLOGI failed on registered " |
| 804 | "FCF record fcf_index:%d, trying " | 812 | "FCF record fcf_index(%d), status: " |
| 805 | "to perform round robin failover\n", | 813 | "x%x/x%x, tmo:x%x, trying to perform " |
| 806 | phba->fcf.current_rec.fcf_indx); | 814 | "round robin failover\n", |
| 815 | phba->fcf.current_rec.fcf_indx, | ||
| 816 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 817 | irsp->ulpTimeout); | ||
| 807 | fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); | 818 | fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); |
| 808 | if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { | 819 | if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { |
| 809 | /* | 820 | /* |
| @@ -841,6 +852,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 841 | } | 852 | } |
| 842 | } | 853 | } |
| 843 | 854 | ||
| 855 | /* FLOGI failure */ | ||
| 856 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
| 857 | "2858 FLOGI failure Status:x%x/x%x TMO:x%x\n", | ||
| 858 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 859 | irsp->ulpTimeout); | ||
| 860 | |||
| 844 | /* Check for retry */ | 861 | /* Check for retry */ |
| 845 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 862 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
| 846 | goto out; | 863 | goto out; |
| @@ -1291,6 +1308,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
| 1291 | struct serv_parm *sp; | 1308 | struct serv_parm *sp; |
| 1292 | uint8_t name[sizeof(struct lpfc_name)]; | 1309 | uint8_t name[sizeof(struct lpfc_name)]; |
| 1293 | uint32_t rc, keepDID = 0; | 1310 | uint32_t rc, keepDID = 0; |
| 1311 | int put_node; | ||
| 1312 | int put_rport; | ||
| 1294 | 1313 | ||
| 1295 | /* Fabric nodes can have the same WWPN so we don't bother searching | 1314 | /* Fabric nodes can have the same WWPN so we don't bother searching |
| 1296 | * by WWPN. Just return the ndlp that was given to us. | 1315 | * by WWPN. Just return the ndlp that was given to us. |
| @@ -1379,6 +1398,28 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | |||
| 1379 | /* Two ndlps cannot have the same did */ | 1398 | /* Two ndlps cannot have the same did */ |
| 1380 | ndlp->nlp_DID = keepDID; | 1399 | ndlp->nlp_DID = keepDID; |
| 1381 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1400 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
| 1401 | /* Since we are swapping the ndlp passed in with the new one | ||
| 1402 | * and the did has already been swapped, copy over the | ||
| 1403 | * state and names. | ||
| 1404 | */ | ||
| 1405 | memcpy(&new_ndlp->nlp_portname, &ndlp->nlp_portname, | ||
| 1406 | sizeof(struct lpfc_name)); | ||
| 1407 | memcpy(&new_ndlp->nlp_nodename, &ndlp->nlp_nodename, | ||
| 1408 | sizeof(struct lpfc_name)); | ||
| 1409 | new_ndlp->nlp_state = ndlp->nlp_state; | ||
| 1410 | /* Fix up the rport accordingly */ | ||
| 1411 | rport = ndlp->rport; | ||
| 1412 | if (rport) { | ||
| 1413 | rdata = rport->dd_data; | ||
| 1414 | put_node = rdata->pnode != NULL; | ||
| 1415 | put_rport = ndlp->rport != NULL; | ||
| 1416 | rdata->pnode = NULL; | ||
| 1417 | ndlp->rport = NULL; | ||
| 1418 | if (put_node) | ||
| 1419 | lpfc_nlp_put(ndlp); | ||
| 1420 | if (put_rport) | ||
| 1421 | put_device(&rport->dev); | ||
| 1422 | } | ||
| 1382 | } | 1423 | } |
| 1383 | return new_ndlp; | 1424 | return new_ndlp; |
| 1384 | } | 1425 | } |
| @@ -2880,6 +2921,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2880 | retry = 0; | 2921 | retry = 0; |
| 2881 | 2922 | ||
| 2882 | if (retry) { | 2923 | if (retry) { |
| 2924 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) { | ||
| 2925 | /* Stop retrying PLOGI and FDISC if in FCF discovery */ | ||
| 2926 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { | ||
| 2927 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
| 2928 | "2849 Stop retry ELS command " | ||
| 2929 | "x%x to remote NPORT x%x, " | ||
| 2930 | "Data: x%x x%x\n", cmd, did, | ||
| 2931 | cmdiocb->retry, delay); | ||
| 2932 | return 0; | ||
| 2933 | } | ||
| 2934 | } | ||
| 2883 | 2935 | ||
| 2884 | /* Retry ELS command <elsCmd> to remote NPORT <did> */ | 2936 | /* Retry ELS command <elsCmd> to remote NPORT <did> */ |
| 2885 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2937 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
| @@ -6076,8 +6128,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 6076 | 6128 | ||
| 6077 | if (mb->mbxStatus) { | 6129 | if (mb->mbxStatus) { |
| 6078 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | 6130 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
| 6079 | "0915 Register VPI failed: 0x%x\n", | 6131 | "0915 Register VPI failed : Status: x%x" |
| 6080 | mb->mbxStatus); | 6132 | " upd bit: x%x \n", mb->mbxStatus, |
| 6133 | mb->un.varRegVpi.upd); | ||
| 6134 | if (phba->sli_rev == LPFC_SLI_REV4 && | ||
| 6135 | mb->un.varRegVpi.upd) | ||
| 6136 | goto mbox_err_exit ; | ||
| 6081 | 6137 | ||
| 6082 | switch (mb->mbxStatus) { | 6138 | switch (mb->mbxStatus) { |
| 6083 | case 0x11: /* unsupported feature */ | 6139 | case 0x11: /* unsupported feature */ |
| @@ -6142,7 +6198,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 6142 | } else | 6198 | } else |
| 6143 | lpfc_do_scr_ns_plogi(phba, vport); | 6199 | lpfc_do_scr_ns_plogi(phba, vport); |
| 6144 | } | 6200 | } |
| 6145 | 6201 | mbox_err_exit: | |
| 6146 | /* Now, we decrement the ndlp reference count held for this | 6202 | /* Now, we decrement the ndlp reference count held for this |
| 6147 | * callback function | 6203 | * callback function |
| 6148 | */ | 6204 | */ |
| @@ -6387,6 +6443,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 6387 | else | 6443 | else |
| 6388 | vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG; | 6444 | vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG; |
| 6389 | spin_unlock_irq(shost->host_lock); | 6445 | spin_unlock_irq(shost->host_lock); |
| 6446 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
| 6447 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { | ||
| 6448 | /* | ||
| 6449 | * Driver needs to re-reg VPI in order for f/w | ||
| 6450 | * to update the MAC address. | ||
| 6451 | */ | ||
| 6452 | lpfc_register_new_vport(phba, vport, ndlp); | ||
| 6453 | return ; | ||
| 6390 | } | 6454 | } |
| 6391 | 6455 | ||
| 6392 | if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) | 6456 | if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0639c994349c..1f62ea8c165d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -588,7 +588,7 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
| 588 | (status & | 588 | (status & |
| 589 | HA_RXMASK)); | 589 | HA_RXMASK)); |
| 590 | } | 590 | } |
| 591 | if (pring->txq_cnt) | 591 | if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt) |
| 592 | lpfc_drain_txq(phba); | 592 | lpfc_drain_txq(phba); |
| 593 | /* | 593 | /* |
| 594 | * Turn on Ring interrupts | 594 | * Turn on Ring interrupts |
| @@ -1852,8 +1852,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 1852 | __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); | 1852 | __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); |
| 1853 | else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) | 1853 | else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) |
| 1854 | /* If in fast failover, mark it's completed */ | 1854 | /* If in fast failover, mark it's completed */ |
| 1855 | phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | | 1855 | phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; |
| 1856 | FCF_DISCOVERY); | ||
| 1857 | spin_unlock_irq(&phba->hbalock); | 1856 | spin_unlock_irq(&phba->hbalock); |
| 1858 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, | 1857 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, |
| 1859 | "2836 The new FCF record (x%x) " | 1858 | "2836 The new FCF record (x%x) " |
| @@ -2651,7 +2650,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
| 2651 | spin_unlock_irq(&phba->hbalock); | 2650 | spin_unlock_irq(&phba->hbalock); |
| 2652 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, | 2651 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, |
| 2653 | "2778 Start FCF table scan at linkup\n"); | 2652 | "2778 Start FCF table scan at linkup\n"); |
| 2654 | |||
| 2655 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, | 2653 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, |
| 2656 | LPFC_FCOE_FCF_GET_FIRST); | 2654 | LPFC_FCOE_FCF_GET_FIRST); |
| 2657 | if (rc) { | 2655 | if (rc) { |
| @@ -2660,6 +2658,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
| 2660 | spin_unlock_irq(&phba->hbalock); | 2658 | spin_unlock_irq(&phba->hbalock); |
| 2661 | goto out; | 2659 | goto out; |
| 2662 | } | 2660 | } |
| 2661 | /* Reset FCF roundrobin bmask for new discovery */ | ||
| 2662 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
| 2663 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
| 2663 | } | 2664 | } |
| 2664 | 2665 | ||
| 2665 | return; | 2666 | return; |
| @@ -5097,6 +5098,7 @@ static void | |||
| 5097 | lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | 5098 | lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) |
| 5098 | { | 5099 | { |
| 5099 | struct lpfc_vport *vport = mboxq->vport; | 5100 | struct lpfc_vport *vport = mboxq->vport; |
| 5101 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
| 5100 | 5102 | ||
| 5101 | if (mboxq->u.mb.mbxStatus) { | 5103 | if (mboxq->u.mb.mbxStatus) { |
| 5102 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, | 5104 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, |
| @@ -5104,6 +5106,9 @@ lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 5104 | "HBA state x%x\n", | 5106 | "HBA state x%x\n", |
| 5105 | mboxq->u.mb.mbxStatus, vport->port_state); | 5107 | mboxq->u.mb.mbxStatus, vport->port_state); |
| 5106 | } | 5108 | } |
| 5109 | spin_lock_irq(shost->host_lock); | ||
| 5110 | phba->pport->fc_flag &= ~FC_VFI_REGISTERED; | ||
| 5111 | spin_unlock_irq(shost->host_lock); | ||
| 5107 | mempool_free(mboxq, phba->mbox_mem_pool); | 5112 | mempool_free(mboxq, phba->mbox_mem_pool); |
| 5108 | return; | 5113 | return; |
| 5109 | } | 5114 | } |
| @@ -5285,6 +5290,10 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) | |||
| 5285 | spin_lock_irq(&phba->hbalock); | 5290 | spin_lock_irq(&phba->hbalock); |
| 5286 | phba->fcf.fcf_flag |= FCF_INIT_DISC; | 5291 | phba->fcf.fcf_flag |= FCF_INIT_DISC; |
| 5287 | spin_unlock_irq(&phba->hbalock); | 5292 | spin_unlock_irq(&phba->hbalock); |
| 5293 | |||
| 5294 | /* Reset FCF roundrobin bmask for new discovery */ | ||
| 5295 | memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask)); | ||
| 5296 | |||
| 5288 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); | 5297 | rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); |
| 5289 | 5298 | ||
| 5290 | if (rc) { | 5299 | if (rc) { |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index f5dbf2be3eab..1676f61291e7 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
| @@ -2291,7 +2291,8 @@ typedef struct { | |||
| 2291 | typedef struct { | 2291 | typedef struct { |
| 2292 | #ifdef __BIG_ENDIAN_BITFIELD | 2292 | #ifdef __BIG_ENDIAN_BITFIELD |
| 2293 | uint32_t rsvd1; | 2293 | uint32_t rsvd1; |
| 2294 | uint32_t rsvd2:8; | 2294 | uint32_t rsvd2:7; |
| 2295 | uint32_t upd:1; | ||
| 2295 | uint32_t sid:24; | 2296 | uint32_t sid:24; |
| 2296 | uint32_t wwn[2]; | 2297 | uint32_t wwn[2]; |
| 2297 | uint32_t rsvd5; | 2298 | uint32_t rsvd5; |
| @@ -2300,7 +2301,8 @@ typedef struct { | |||
| 2300 | #else /* __LITTLE_ENDIAN */ | 2301 | #else /* __LITTLE_ENDIAN */ |
| 2301 | uint32_t rsvd1; | 2302 | uint32_t rsvd1; |
| 2302 | uint32_t sid:24; | 2303 | uint32_t sid:24; |
| 2303 | uint32_t rsvd2:8; | 2304 | uint32_t upd:1; |
| 2305 | uint32_t rsvd2:7; | ||
| 2304 | uint32_t wwn[2]; | 2306 | uint32_t wwn[2]; |
| 2305 | uint32_t rsvd5; | 2307 | uint32_t rsvd5; |
| 2306 | uint16_t vpi; | 2308 | uint16_t vpi; |
| @@ -2806,11 +2808,15 @@ typedef struct { | |||
| 2806 | uint32_t rsvd6; /* Reserved */ | 2808 | uint32_t rsvd6; /* Reserved */ |
| 2807 | 2809 | ||
| 2808 | #ifdef __BIG_ENDIAN_BITFIELD | 2810 | #ifdef __BIG_ENDIAN_BITFIELD |
| 2809 | uint32_t rsvd7 : 16; /* Reserved */ | 2811 | uint32_t fips_rev : 3; /* FIPS Spec Revision */ |
| 2812 | uint32_t fips_level : 4; /* FIPS Level */ | ||
| 2813 | uint32_t sec_err : 9; /* security crypto error */ | ||
| 2810 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ | 2814 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ |
| 2811 | #else /* __LITTLE_ENDIAN */ | 2815 | #else /* __LITTLE_ENDIAN */ |
| 2812 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ | 2816 | uint32_t max_vpi : 16; /* Max number of virt N-Ports */ |
| 2813 | uint32_t rsvd7 : 16; /* Reserved */ | 2817 | uint32_t sec_err : 9; /* security crypto error */ |
| 2818 | uint32_t fips_level : 4; /* FIPS Level */ | ||
| 2819 | uint32_t fips_rev : 3; /* FIPS Spec Revision */ | ||
| 2814 | #endif | 2820 | #endif |
| 2815 | 2821 | ||
| 2816 | } CONFIG_PORT_VAR; | 2822 | } CONFIG_PORT_VAR; |
| @@ -3441,63 +3447,63 @@ struct sli3_bg_fields { | |||
| 3441 | static inline uint32_t | 3447 | static inline uint32_t |
| 3442 | lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat) | 3448 | lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat) |
| 3443 | { | 3449 | { |
| 3444 | return (le32_to_cpu(bgstat) & BGS_BIDIR_BG_PROF_MASK) >> | 3450 | return (bgstat & BGS_BIDIR_BG_PROF_MASK) >> |
| 3445 | BGS_BIDIR_BG_PROF_SHIFT; | 3451 | BGS_BIDIR_BG_PROF_SHIFT; |
| 3446 | } | 3452 | } |
| 3447 | 3453 | ||
| 3448 | static inline uint32_t | 3454 | static inline uint32_t |
| 3449 | lpfc_bgs_get_bidir_err_cond(uint32_t bgstat) | 3455 | lpfc_bgs_get_bidir_err_cond(uint32_t bgstat) |
| 3450 | { | 3456 | { |
| 3451 | return (le32_to_cpu(bgstat) & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> | 3457 | return (bgstat & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> |
| 3452 | BGS_BIDIR_ERR_COND_SHIFT; | 3458 | BGS_BIDIR_ERR_COND_SHIFT; |
| 3453 | } | 3459 | } |
| 3454 | 3460 | ||
| 3455 | static inline uint32_t | 3461 | static inline uint32_t |
| 3456 | lpfc_bgs_get_bg_prof(uint32_t bgstat) | 3462 | lpfc_bgs_get_bg_prof(uint32_t bgstat) |
| 3457 | { | 3463 | { |
| 3458 | return (le32_to_cpu(bgstat) & BGS_BG_PROFILE_MASK) >> | 3464 | return (bgstat & BGS_BG_PROFILE_MASK) >> |
| 3459 | BGS_BG_PROFILE_SHIFT; | 3465 | BGS_BG_PROFILE_SHIFT; |
| 3460 | } | 3466 | } |
| 3461 | 3467 | ||
| 3462 | static inline uint32_t | 3468 | static inline uint32_t |
| 3463 | lpfc_bgs_get_invalid_prof(uint32_t bgstat) | 3469 | lpfc_bgs_get_invalid_prof(uint32_t bgstat) |
| 3464 | { | 3470 | { |
| 3465 | return (le32_to_cpu(bgstat) & BGS_INVALID_PROF_MASK) >> | 3471 | return (bgstat & BGS_INVALID_PROF_MASK) >> |
| 3466 | BGS_INVALID_PROF_SHIFT; | 3472 | BGS_INVALID_PROF_SHIFT; |
| 3467 | } | 3473 | } |
| 3468 | 3474 | ||
| 3469 | static inline uint32_t | 3475 | static inline uint32_t |
| 3470 | lpfc_bgs_get_uninit_dif_block(uint32_t bgstat) | 3476 | lpfc_bgs_get_uninit_dif_block(uint32_t bgstat) |
| 3471 | { | 3477 | { |
| 3472 | return (le32_to_cpu(bgstat) & BGS_UNINIT_DIF_BLOCK_MASK) >> | 3478 | return (bgstat & BGS_UNINIT_DIF_BLOCK_MASK) >> |
| 3473 | BGS_UNINIT_DIF_BLOCK_SHIFT; | 3479 | BGS_UNINIT_DIF_BLOCK_SHIFT; |
| 3474 | } | 3480 | } |
| 3475 | 3481 | ||
| 3476 | static inline uint32_t | 3482 | static inline uint32_t |
| 3477 | lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat) | 3483 | lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat) |
| 3478 | { | 3484 | { |
| 3479 | return (le32_to_cpu(bgstat) & BGS_HI_WATER_MARK_PRESENT_MASK) >> | 3485 | return (bgstat & BGS_HI_WATER_MARK_PRESENT_MASK) >> |
| 3480 | BGS_HI_WATER_MARK_PRESENT_SHIFT; | 3486 | BGS_HI_WATER_MARK_PRESENT_SHIFT; |
| 3481 | } | 3487 | } |
| 3482 | 3488 | ||
| 3483 | static inline uint32_t | 3489 | static inline uint32_t |
| 3484 | lpfc_bgs_get_reftag_err(uint32_t bgstat) | 3490 | lpfc_bgs_get_reftag_err(uint32_t bgstat) |
| 3485 | { | 3491 | { |
| 3486 | return (le32_to_cpu(bgstat) & BGS_REFTAG_ERR_MASK) >> | 3492 | return (bgstat & BGS_REFTAG_ERR_MASK) >> |
| 3487 | BGS_REFTAG_ERR_SHIFT; | 3493 | BGS_REFTAG_ERR_SHIFT; |
| 3488 | } | 3494 | } |
| 3489 | 3495 | ||
| 3490 | static inline uint32_t | 3496 | static inline uint32_t |
| 3491 | lpfc_bgs_get_apptag_err(uint32_t bgstat) | 3497 | lpfc_bgs_get_apptag_err(uint32_t bgstat) |
| 3492 | { | 3498 | { |
| 3493 | return (le32_to_cpu(bgstat) & BGS_APPTAG_ERR_MASK) >> | 3499 | return (bgstat & BGS_APPTAG_ERR_MASK) >> |
| 3494 | BGS_APPTAG_ERR_SHIFT; | 3500 | BGS_APPTAG_ERR_SHIFT; |
| 3495 | } | 3501 | } |
| 3496 | 3502 | ||
| 3497 | static inline uint32_t | 3503 | static inline uint32_t |
| 3498 | lpfc_bgs_get_guard_err(uint32_t bgstat) | 3504 | lpfc_bgs_get_guard_err(uint32_t bgstat) |
| 3499 | { | 3505 | { |
| 3500 | return (le32_to_cpu(bgstat) & BGS_GUARD_ERR_MASK) >> | 3506 | return (bgstat & BGS_GUARD_ERR_MASK) >> |
| 3501 | BGS_GUARD_ERR_SHIFT; | 3507 | BGS_GUARD_ERR_SHIFT; |
| 3502 | } | 3508 | } |
| 3503 | 3509 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2786ee3b605d..da9ba06ad583 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -1032,27 +1032,46 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
| 1032 | /* If there is no heart beat outstanding, issue a heartbeat command */ | 1032 | /* If there is no heart beat outstanding, issue a heartbeat command */ |
| 1033 | if (phba->cfg_enable_hba_heartbeat) { | 1033 | if (phba->cfg_enable_hba_heartbeat) { |
| 1034 | if (!phba->hb_outstanding) { | 1034 | if (!phba->hb_outstanding) { |
| 1035 | pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); | 1035 | if ((!(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) && |
| 1036 | if (!pmboxq) { | 1036 | (list_empty(&psli->mboxq))) { |
| 1037 | mod_timer(&phba->hb_tmofunc, | 1037 | pmboxq = mempool_alloc(phba->mbox_mem_pool, |
| 1038 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 1038 | GFP_KERNEL); |
| 1039 | return; | 1039 | if (!pmboxq) { |
| 1040 | } | 1040 | mod_timer(&phba->hb_tmofunc, |
| 1041 | jiffies + | ||
| 1042 | HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 1043 | return; | ||
| 1044 | } | ||
| 1041 | 1045 | ||
| 1042 | lpfc_heart_beat(phba, pmboxq); | 1046 | lpfc_heart_beat(phba, pmboxq); |
| 1043 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; | 1047 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; |
| 1044 | pmboxq->vport = phba->pport; | 1048 | pmboxq->vport = phba->pport; |
| 1045 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | 1049 | retval = lpfc_sli_issue_mbox(phba, pmboxq, |
| 1050 | MBX_NOWAIT); | ||
| 1051 | |||
| 1052 | if (retval != MBX_BUSY && | ||
| 1053 | retval != MBX_SUCCESS) { | ||
| 1054 | mempool_free(pmboxq, | ||
| 1055 | phba->mbox_mem_pool); | ||
| 1056 | mod_timer(&phba->hb_tmofunc, | ||
| 1057 | jiffies + | ||
| 1058 | HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 1059 | return; | ||
| 1060 | } | ||
| 1061 | phba->skipped_hb = 0; | ||
| 1062 | phba->hb_outstanding = 1; | ||
| 1063 | } else if (time_before_eq(phba->last_completion_time, | ||
| 1064 | phba->skipped_hb)) { | ||
| 1065 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 1066 | "2857 Last completion time not " | ||
| 1067 | " updated in %d ms\n", | ||
| 1068 | jiffies_to_msecs(jiffies | ||
| 1069 | - phba->last_completion_time)); | ||
| 1070 | } else | ||
| 1071 | phba->skipped_hb = jiffies; | ||
| 1046 | 1072 | ||
| 1047 | if (retval != MBX_BUSY && retval != MBX_SUCCESS) { | ||
| 1048 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 1049 | mod_timer(&phba->hb_tmofunc, | ||
| 1050 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 1051 | return; | ||
| 1052 | } | ||
| 1053 | mod_timer(&phba->hb_tmofunc, | 1073 | mod_timer(&phba->hb_tmofunc, |
| 1054 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | 1074 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); |
| 1055 | phba->hb_outstanding = 1; | ||
| 1056 | return; | 1075 | return; |
| 1057 | } else { | 1076 | } else { |
| 1058 | /* | 1077 | /* |
| @@ -3281,10 +3300,10 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) | |||
| 3281 | if (!ndlp) | 3300 | if (!ndlp) |
| 3282 | return 0; | 3301 | return 0; |
| 3283 | } | 3302 | } |
| 3284 | if (phba->pport->port_state <= LPFC_FLOGI) | 3303 | if (phba->pport->port_state < LPFC_FLOGI) |
| 3285 | return NULL; | 3304 | return NULL; |
| 3286 | /* If virtual link is not yet instantiated ignore CVL */ | 3305 | /* If virtual link is not yet instantiated ignore CVL */ |
| 3287 | if (vport->port_state <= LPFC_FDISC) | 3306 | if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)) |
| 3288 | return NULL; | 3307 | return NULL; |
| 3289 | shost = lpfc_shost_from_vport(vport); | 3308 | shost = lpfc_shost_from_vport(vport); |
| 3290 | if (!shost) | 3309 | if (!shost) |
| @@ -3357,21 +3376,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
| 3357 | "evt_tag:x%x, fcf_index:x%x\n", | 3376 | "evt_tag:x%x, fcf_index:x%x\n", |
| 3358 | acqe_fcoe->event_tag, | 3377 | acqe_fcoe->event_tag, |
| 3359 | acqe_fcoe->index); | 3378 | acqe_fcoe->index); |
| 3360 | /* If the FCF discovery is in progress, do nothing. */ | 3379 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { |
| 3361 | spin_lock_irq(&phba->hbalock); | ||
| 3362 | if (phba->hba_flag & FCF_DISC_INPROGRESS) { | ||
| 3363 | spin_unlock_irq(&phba->hbalock); | ||
| 3364 | break; | ||
| 3365 | } | ||
| 3366 | /* If fast FCF failover rescan event is pending, do nothing */ | ||
| 3367 | if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { | ||
| 3368 | spin_unlock_irq(&phba->hbalock); | ||
| 3369 | break; | ||
| 3370 | } | ||
| 3371 | spin_unlock_irq(&phba->hbalock); | ||
| 3372 | |||
| 3373 | if ((phba->fcf.fcf_flag & FCF_DISCOVERY) && | ||
| 3374 | !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) { | ||
| 3375 | /* | 3380 | /* |
| 3376 | * During period of FCF discovery, read the FCF | 3381 | * During period of FCF discovery, read the FCF |
| 3377 | * table record indexed by the event to update | 3382 | * table record indexed by the event to update |
| @@ -3385,13 +3390,26 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
| 3385 | acqe_fcoe->index); | 3390 | acqe_fcoe->index); |
| 3386 | rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); | 3391 | rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); |
| 3387 | } | 3392 | } |
| 3388 | /* If the FCF has been in discovered state, do nothing. */ | 3393 | |
| 3394 | /* If the FCF discovery is in progress, do nothing. */ | ||
| 3389 | spin_lock_irq(&phba->hbalock); | 3395 | spin_lock_irq(&phba->hbalock); |
| 3396 | if (phba->hba_flag & FCF_DISC_INPROGRESS) { | ||
| 3397 | spin_unlock_irq(&phba->hbalock); | ||
| 3398 | break; | ||
| 3399 | } | ||
| 3400 | /* If fast FCF failover rescan event is pending, do nothing */ | ||
| 3401 | if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { | ||
| 3402 | spin_unlock_irq(&phba->hbalock); | ||
| 3403 | break; | ||
| 3404 | } | ||
| 3405 | |||
| 3406 | /* If the FCF has been in discovered state, do nothing. */ | ||
| 3390 | if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { | 3407 | if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { |
| 3391 | spin_unlock_irq(&phba->hbalock); | 3408 | spin_unlock_irq(&phba->hbalock); |
| 3392 | break; | 3409 | break; |
| 3393 | } | 3410 | } |
| 3394 | spin_unlock_irq(&phba->hbalock); | 3411 | spin_unlock_irq(&phba->hbalock); |
| 3412 | |||
| 3395 | /* Otherwise, scan the entire FCF table and re-discover SAN */ | 3413 | /* Otherwise, scan the entire FCF table and re-discover SAN */ |
| 3396 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, | 3414 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, |
| 3397 | "2770 Start FCF table scan due to new FCF " | 3415 | "2770 Start FCF table scan due to new FCF " |
| @@ -3417,13 +3435,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
| 3417 | "2549 FCF disconnected from network index 0x%x" | 3435 | "2549 FCF disconnected from network index 0x%x" |
| 3418 | " tag 0x%x\n", acqe_fcoe->index, | 3436 | " tag 0x%x\n", acqe_fcoe->index, |
| 3419 | acqe_fcoe->event_tag); | 3437 | acqe_fcoe->event_tag); |
| 3420 | /* If the event is not for currently used fcf do nothing */ | 3438 | /* |
| 3421 | if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) | 3439 | * If we are in the middle of FCF failover process, clear |
| 3422 | break; | 3440 | * the corresponding FCF bit in the roundrobin bitmap. |
| 3423 | /* We request port to rediscover the entire FCF table for | ||
| 3424 | * a fast recovery from case that the current FCF record | ||
| 3425 | * is no longer valid if we are not in the middle of FCF | ||
| 3426 | * failover process already. | ||
| 3427 | */ | 3441 | */ |
| 3428 | spin_lock_irq(&phba->hbalock); | 3442 | spin_lock_irq(&phba->hbalock); |
| 3429 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { | 3443 | if (phba->fcf.fcf_flag & FCF_DISCOVERY) { |
| @@ -3432,9 +3446,23 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
| 3432 | lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); | 3446 | lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); |
| 3433 | break; | 3447 | break; |
| 3434 | } | 3448 | } |
| 3449 | spin_unlock_irq(&phba->hbalock); | ||
| 3450 | |||
| 3451 | /* If the event is not for currently used fcf do nothing */ | ||
| 3452 | if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) | ||
| 3453 | break; | ||
| 3454 | |||
| 3455 | /* | ||
| 3456 | * Otherwise, request the port to rediscover the entire FCF | ||
| 3457 | * table for a fast recovery from case that the current FCF | ||
| 3458 | * is no longer valid as we are not in the middle of FCF | ||
| 3459 | * failover process already. | ||
| 3460 | */ | ||
| 3461 | spin_lock_irq(&phba->hbalock); | ||
| 3435 | /* Mark the fast failover process in progress */ | 3462 | /* Mark the fast failover process in progress */ |
| 3436 | phba->fcf.fcf_flag |= FCF_DEAD_DISC; | 3463 | phba->fcf.fcf_flag |= FCF_DEAD_DISC; |
| 3437 | spin_unlock_irq(&phba->hbalock); | 3464 | spin_unlock_irq(&phba->hbalock); |
| 3465 | |||
| 3438 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, | 3466 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, |
| 3439 | "2771 Start FCF fast failover process due to " | 3467 | "2771 Start FCF fast failover process due to " |
| 3440 | "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " | 3468 | "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " |
| @@ -3454,12 +3482,16 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
| 3454 | * as a link down to FCF registration. | 3482 | * as a link down to FCF registration. |
| 3455 | */ | 3483 | */ |
| 3456 | lpfc_sli4_fcf_dead_failthrough(phba); | 3484 | lpfc_sli4_fcf_dead_failthrough(phba); |
| 3457 | } else | 3485 | } else { |
| 3458 | /* Handling fast FCF failover to a DEAD FCF event | 3486 | /* Reset FCF roundrobin bmask for new discovery */ |
| 3459 | * is considered equalivant to receiving CVL to all | 3487 | memset(phba->fcf.fcf_rr_bmask, 0, |
| 3460 | * vports. | 3488 | sizeof(*phba->fcf.fcf_rr_bmask)); |
| 3489 | /* | ||
| 3490 | * Handling fast FCF failover to a DEAD FCF event is | ||
| 3491 | * considered equalivant to receiving CVL to all vports. | ||
| 3461 | */ | 3492 | */ |
| 3462 | lpfc_sli4_perform_all_vport_cvl(phba); | 3493 | lpfc_sli4_perform_all_vport_cvl(phba); |
| 3494 | } | ||
| 3463 | break; | 3495 | break; |
| 3464 | case LPFC_FCOE_EVENT_TYPE_CVL: | 3496 | case LPFC_FCOE_EVENT_TYPE_CVL: |
| 3465 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, | 3497 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, |
| @@ -3534,7 +3566,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
| 3534 | * the current registered FCF entry. | 3566 | * the current registered FCF entry. |
| 3535 | */ | 3567 | */ |
| 3536 | lpfc_retry_pport_discovery(phba); | 3568 | lpfc_retry_pport_discovery(phba); |
| 3537 | } | 3569 | } else |
| 3570 | /* | ||
| 3571 | * Reset FCF roundrobin bmask for new | ||
| 3572 | * discovery. | ||
| 3573 | */ | ||
| 3574 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
| 3575 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
| 3538 | } | 3576 | } |
| 3539 | break; | 3577 | break; |
| 3540 | default: | 3578 | default: |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 9c2c7c7140c7..0dfa310cd609 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
| @@ -815,9 +815,15 @@ void | |||
| 815 | lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) | 815 | lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) |
| 816 | { | 816 | { |
| 817 | MAILBOX_t *mb = &pmb->u.mb; | 817 | MAILBOX_t *mb = &pmb->u.mb; |
| 818 | struct lpfc_hba *phba = vport->phba; | ||
| 818 | 819 | ||
| 819 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 820 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
| 820 | 821 | /* | |
| 822 | * Set the re-reg VPI bit for f/w to update the MAC address. | ||
| 823 | */ | ||
| 824 | if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
| 825 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) | ||
| 826 | mb->un.varRegVpi.upd = 1; | ||
| 821 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; | 827 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; |
| 822 | mb->un.varRegVpi.sid = vport->fc_myDID; | 828 | mb->un.varRegVpi.sid = vport->fc_myDID; |
| 823 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | 829 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c818a7255962..2e51aa6b45b3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -1325,7 +1325,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 1325 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); | 1325 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); |
| 1326 | pde5->reftag = reftag; | 1326 | pde5->reftag = reftag; |
| 1327 | 1327 | ||
| 1328 | /* Endian convertion if necessary for PDE5 */ | 1328 | /* Endianness conversion if necessary for PDE5 */ |
| 1329 | pde5->word0 = cpu_to_le32(pde5->word0); | 1329 | pde5->word0 = cpu_to_le32(pde5->word0); |
| 1330 | pde5->reftag = cpu_to_le32(pde5->reftag); | 1330 | pde5->reftag = cpu_to_le32(pde5->reftag); |
| 1331 | 1331 | ||
| @@ -1347,7 +1347,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 1347 | bf_set(pde6_ai, pde6, 1); | 1347 | bf_set(pde6_ai, pde6, 1); |
| 1348 | bf_set(pde6_apptagval, pde6, apptagval); | 1348 | bf_set(pde6_apptagval, pde6, apptagval); |
| 1349 | 1349 | ||
| 1350 | /* Endian convertion if necessary for PDE6 */ | 1350 | /* Endianness conversion if necessary for PDE6 */ |
| 1351 | pde6->word0 = cpu_to_le32(pde6->word0); | 1351 | pde6->word0 = cpu_to_le32(pde6->word0); |
| 1352 | pde6->word1 = cpu_to_le32(pde6->word1); | 1352 | pde6->word1 = cpu_to_le32(pde6->word1); |
| 1353 | pde6->word2 = cpu_to_le32(pde6->word2); | 1353 | pde6->word2 = cpu_to_le32(pde6->word2); |
| @@ -1459,7 +1459,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 1459 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); | 1459 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); |
| 1460 | pde5->reftag = reftag; | 1460 | pde5->reftag = reftag; |
| 1461 | 1461 | ||
| 1462 | /* Endian convertion if necessary for PDE5 */ | 1462 | /* Endianness conversion if necessary for PDE5 */ |
| 1463 | pde5->word0 = cpu_to_le32(pde5->word0); | 1463 | pde5->word0 = cpu_to_le32(pde5->word0); |
| 1464 | pde5->reftag = cpu_to_le32(pde5->reftag); | 1464 | pde5->reftag = cpu_to_le32(pde5->reftag); |
| 1465 | 1465 | ||
| @@ -1479,7 +1479,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 1479 | bf_set(pde6_ai, pde6, 1); | 1479 | bf_set(pde6_ai, pde6, 1); |
| 1480 | bf_set(pde6_apptagval, pde6, apptagval); | 1480 | bf_set(pde6_apptagval, pde6, apptagval); |
| 1481 | 1481 | ||
| 1482 | /* Endian convertion if necessary for PDE6 */ | 1482 | /* Endianness conversion if necessary for PDE6 */ |
| 1483 | pde6->word0 = cpu_to_le32(pde6->word0); | 1483 | pde6->word0 = cpu_to_le32(pde6->word0); |
| 1484 | pde6->word1 = cpu_to_le32(pde6->word1); | 1484 | pde6->word1 = cpu_to_le32(pde6->word1); |
| 1485 | pde6->word2 = cpu_to_le32(pde6->word2); | 1485 | pde6->word2 = cpu_to_le32(pde6->word2); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e758eae0d0fd..fb8905f893f5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -1046,7 +1046,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
| 1046 | } else | 1046 | } else |
| 1047 | spin_unlock_irq(&phba->hbalock); | 1047 | spin_unlock_irq(&phba->hbalock); |
| 1048 | 1048 | ||
| 1049 | lpfc_printf_log(phba, KERN_ERR,LOG_SLI, | 1049 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, |
| 1050 | "0318 Failed to allocate IOTAG.last IOTAG is %d\n", | 1050 | "0318 Failed to allocate IOTAG.last IOTAG is %d\n", |
| 1051 | psli->last_iotag); | 1051 | psli->last_iotag); |
| 1052 | 1052 | ||
| @@ -3914,7 +3914,8 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) | |||
| 3914 | phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | | 3914 | phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | |
| 3915 | LPFC_SLI3_HBQ_ENABLED | | 3915 | LPFC_SLI3_HBQ_ENABLED | |
| 3916 | LPFC_SLI3_CRP_ENABLED | | 3916 | LPFC_SLI3_CRP_ENABLED | |
| 3917 | LPFC_SLI3_BG_ENABLED); | 3917 | LPFC_SLI3_BG_ENABLED | |
| 3918 | LPFC_SLI3_DSS_ENABLED); | ||
| 3918 | if (rc != MBX_SUCCESS) { | 3919 | if (rc != MBX_SUCCESS) { |
| 3919 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 3920 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| 3920 | "0442 Adapter failed to init, mbxCmd x%x " | 3921 | "0442 Adapter failed to init, mbxCmd x%x " |
| @@ -3949,8 +3950,23 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) | |||
| 3949 | 3950 | ||
| 3950 | } else | 3951 | } else |
| 3951 | phba->max_vpi = 0; | 3952 | phba->max_vpi = 0; |
| 3952 | if (pmb->u.mb.un.varCfgPort.gdss) | 3953 | phba->fips_level = 0; |
| 3954 | phba->fips_spec_rev = 0; | ||
| 3955 | if (pmb->u.mb.un.varCfgPort.gdss) { | ||
| 3953 | phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; | 3956 | phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; |
| 3957 | phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level; | ||
| 3958 | phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev; | ||
| 3959 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 3960 | "2850 Security Crypto Active. FIPS x%d " | ||
| 3961 | "(Spec Rev: x%d)", | ||
| 3962 | phba->fips_level, phba->fips_spec_rev); | ||
| 3963 | } | ||
| 3964 | if (pmb->u.mb.un.varCfgPort.sec_err) { | ||
| 3965 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 3966 | "2856 Config Port Security Crypto " | ||
| 3967 | "Error: x%x ", | ||
| 3968 | pmb->u.mb.un.varCfgPort.sec_err); | ||
| 3969 | } | ||
| 3954 | if (pmb->u.mb.un.varCfgPort.gerbm) | 3970 | if (pmb->u.mb.un.varCfgPort.gerbm) |
| 3955 | phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; | 3971 | phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; |
| 3956 | if (pmb->u.mb.un.varCfgPort.gcrp) | 3972 | if (pmb->u.mb.un.varCfgPort.gcrp) |
| @@ -9040,6 +9056,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
| 9040 | switch (bf_get(lpfc_cqe_code, &cqevt)) { | 9056 | switch (bf_get(lpfc_cqe_code, &cqevt)) { |
| 9041 | case CQE_CODE_COMPL_WQE: | 9057 | case CQE_CODE_COMPL_WQE: |
| 9042 | /* Process the WQ/RQ complete event */ | 9058 | /* Process the WQ/RQ complete event */ |
| 9059 | phba->last_completion_time = jiffies; | ||
| 9043 | workposted = lpfc_sli4_sp_handle_els_wcqe(phba, | 9060 | workposted = lpfc_sli4_sp_handle_els_wcqe(phba, |
| 9044 | (struct lpfc_wcqe_complete *)&cqevt); | 9061 | (struct lpfc_wcqe_complete *)&cqevt); |
| 9045 | break; | 9062 | break; |
| @@ -9050,11 +9067,13 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
| 9050 | break; | 9067 | break; |
| 9051 | case CQE_CODE_XRI_ABORTED: | 9068 | case CQE_CODE_XRI_ABORTED: |
| 9052 | /* Process the WQ XRI abort event */ | 9069 | /* Process the WQ XRI abort event */ |
| 9070 | phba->last_completion_time = jiffies; | ||
| 9053 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, | 9071 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, |
| 9054 | (struct sli4_wcqe_xri_aborted *)&cqevt); | 9072 | (struct sli4_wcqe_xri_aborted *)&cqevt); |
| 9055 | break; | 9073 | break; |
| 9056 | case CQE_CODE_RECEIVE: | 9074 | case CQE_CODE_RECEIVE: |
| 9057 | /* Process the RQ event */ | 9075 | /* Process the RQ event */ |
| 9076 | phba->last_completion_time = jiffies; | ||
| 9058 | workposted = lpfc_sli4_sp_handle_rcqe(phba, | 9077 | workposted = lpfc_sli4_sp_handle_rcqe(phba, |
| 9059 | (struct lpfc_rcqe *)&cqevt); | 9078 | (struct lpfc_rcqe *)&cqevt); |
| 9060 | break; | 9079 | break; |
| @@ -9276,7 +9295,6 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
| 9276 | { | 9295 | { |
| 9277 | struct lpfc_wcqe_release wcqe; | 9296 | struct lpfc_wcqe_release wcqe; |
| 9278 | bool workposted = false; | 9297 | bool workposted = false; |
| 9279 | unsigned long iflag; | ||
| 9280 | 9298 | ||
| 9281 | /* Copy the work queue CQE and convert endian order if needed */ | 9299 | /* Copy the work queue CQE and convert endian order if needed */ |
| 9282 | lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); | 9300 | lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); |
| @@ -9285,9 +9303,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
| 9285 | switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { | 9303 | switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { |
| 9286 | case CQE_CODE_COMPL_WQE: | 9304 | case CQE_CODE_COMPL_WQE: |
| 9287 | /* Process the WQ complete event */ | 9305 | /* Process the WQ complete event */ |
| 9288 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
| 9289 | phba->last_completion_time = jiffies; | 9306 | phba->last_completion_time = jiffies; |
| 9290 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
| 9291 | lpfc_sli4_fp_handle_fcp_wcqe(phba, | 9307 | lpfc_sli4_fp_handle_fcp_wcqe(phba, |
| 9292 | (struct lpfc_wcqe_complete *)&wcqe); | 9308 | (struct lpfc_wcqe_complete *)&wcqe); |
| 9293 | break; | 9309 | break; |
| @@ -9298,6 +9314,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
| 9298 | break; | 9314 | break; |
| 9299 | case CQE_CODE_XRI_ABORTED: | 9315 | case CQE_CODE_XRI_ABORTED: |
| 9300 | /* Process the WQ XRI abort event */ | 9316 | /* Process the WQ XRI abort event */ |
| 9317 | phba->last_completion_time = jiffies; | ||
| 9301 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, | 9318 | workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, |
| 9302 | (struct sli4_wcqe_xri_aborted *)&wcqe); | 9319 | (struct sli4_wcqe_xri_aborted *)&wcqe); |
| 9303 | break; | 9320 | break; |
| @@ -12278,12 +12295,9 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) | |||
| 12278 | spin_lock_irq(&phba->hbalock); | 12295 | spin_lock_irq(&phba->hbalock); |
| 12279 | phba->hba_flag |= FCF_DISC_INPROGRESS; | 12296 | phba->hba_flag |= FCF_DISC_INPROGRESS; |
| 12280 | spin_unlock_irq(&phba->hbalock); | 12297 | spin_unlock_irq(&phba->hbalock); |
| 12281 | /* Reset FCF round robin index bmask for new scan */ | 12298 | /* Reset eligible FCF count for new scan */ |
| 12282 | if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) { | 12299 | if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) |
| 12283 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
| 12284 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
| 12285 | phba->fcf.eligible_fcf_cnt = 0; | 12300 | phba->fcf.eligible_fcf_cnt = 0; |
| 12286 | } | ||
| 12287 | error = 0; | 12301 | error = 0; |
| 12288 | } | 12302 | } |
| 12289 | fail_fcf_scan: | 12303 | fail_fcf_scan: |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index d28830af71d8..61afb3420a96 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | * included with this package. * | 18 | * included with this package. * |
| 19 | *******************************************************************/ | 19 | *******************************************************************/ |
| 20 | 20 | ||
| 21 | #define LPFC_DRIVER_VERSION "8.3.15" | 21 | #define LPFC_DRIVER_VERSION "8.3.16" |
| 22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
| 23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" | 23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" |
| 24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" | 24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" |
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 58d1134935ef..9793aa6afb10 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
| @@ -4199,8 +4199,10 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4199 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4199 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
| 4200 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4200 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
| 4201 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4201 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| 4202 | if (rc) | 4202 | if (rc) { |
| 4203 | kfree(fw_control_context); | ||
| 4203 | return rc; | 4204 | return rc; |
| 4205 | } | ||
| 4204 | ccb = &pm8001_ha->ccb_info[tag]; | 4206 | ccb = &pm8001_ha->ccb_info[tag]; |
| 4205 | ccb->ccb_tag = tag; | 4207 | ccb->ccb_tag = tag; |
| 4206 | ccb->fw_control_context = fw_control_context; | 4208 | ccb->fw_control_context = fw_control_context; |
| @@ -4276,8 +4278,10 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4276 | ioctl_payload->length); | 4278 | ioctl_payload->length); |
| 4277 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4279 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
| 4278 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4280 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| 4279 | if (rc) | 4281 | if (rc) { |
| 4282 | kfree(fw_control_context); | ||
| 4280 | return rc; | 4283 | return rc; |
| 4284 | } | ||
| 4281 | ccb = &pm8001_ha->ccb_info[tag]; | 4285 | ccb = &pm8001_ha->ccb_info[tag]; |
| 4282 | ccb->fw_control_context = fw_control_context; | 4286 | ccb->fw_control_context = fw_control_context; |
| 4283 | ccb->ccb_tag = tag; | 4287 | ccb->ccb_tag = tag; |
| @@ -4387,6 +4391,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4387 | fw_control->len, 0) != 0) { | 4391 | fw_control->len, 0) != 0) { |
| 4388 | PM8001_FAIL_DBG(pm8001_ha, | 4392 | PM8001_FAIL_DBG(pm8001_ha, |
| 4389 | pm8001_printk("Mem alloc failure\n")); | 4393 | pm8001_printk("Mem alloc failure\n")); |
| 4394 | kfree(fw_control_context); | ||
| 4390 | return -ENOMEM; | 4395 | return -ENOMEM; |
| 4391 | } | 4396 | } |
| 4392 | } | 4397 | } |
| @@ -4401,8 +4406,10 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4401 | fw_control_context->virtAddr = buffer; | 4406 | fw_control_context->virtAddr = buffer; |
| 4402 | fw_control_context->len = fw_control->len; | 4407 | fw_control_context->len = fw_control->len; |
| 4403 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4408 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| 4404 | if (rc) | 4409 | if (rc) { |
| 4410 | kfree(fw_control_context); | ||
| 4405 | return rc; | 4411 | return rc; |
| 4412 | } | ||
| 4406 | ccb = &pm8001_ha->ccb_info[tag]; | 4413 | ccb = &pm8001_ha->ccb_info[tag]; |
| 4407 | ccb->fw_control_context = fw_control_context; | 4414 | ccb->fw_control_context = fw_control_context; |
| 4408 | ccb->ccb_tag = tag; | 4415 | ccb->ccb_tag = tag; |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a79da8dd2064..9dc0a6616edd 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
| @@ -36,6 +36,24 @@ | |||
| 36 | #include "ql4_dbg.h" | 36 | #include "ql4_dbg.h" |
| 37 | #include "ql4_nx.h" | 37 | #include "ql4_nx.h" |
| 38 | 38 | ||
| 39 | #if defined(CONFIG_PCIEAER) | ||
| 40 | #include <linux/aer.h> | ||
| 41 | #else | ||
| 42 | /* AER releated */ | ||
| 43 | static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) | ||
| 44 | { | ||
| 45 | return -EINVAL; | ||
| 46 | } | ||
| 47 | static inline int pci_disable_pcie_error_reporting(struct pci_dev *dev) | ||
| 48 | { | ||
| 49 | return -EINVAL; | ||
| 50 | } | ||
| 51 | static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | ||
| 52 | { | ||
| 53 | return -EINVAL; | ||
| 54 | } | ||
| 55 | #endif | ||
| 56 | |||
| 39 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 | 57 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 |
| 40 | #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 | 58 | #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 |
| 41 | #endif | 59 | #endif |
| @@ -137,6 +155,9 @@ | |||
| 137 | #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ | 155 | #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ |
| 138 | #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ | 156 | #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ |
| 139 | 157 | ||
| 158 | #define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */ | ||
| 159 | /* recovery timeout */ | ||
| 160 | |||
| 140 | #define LSDW(x) ((u32)((u64)(x))) | 161 | #define LSDW(x) ((u32)((u64)(x))) |
| 141 | #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) | 162 | #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) |
| 142 | 163 | ||
| @@ -249,7 +270,6 @@ struct ddb_entry { | |||
| 249 | uint32_t default_time2wait; /* Default Min time between | 270 | uint32_t default_time2wait; /* Default Min time between |
| 250 | * relogins (+aens) */ | 271 | * relogins (+aens) */ |
| 251 | 272 | ||
| 252 | atomic_t port_down_timer; /* Device connection timer */ | ||
| 253 | atomic_t retry_relogin_timer; /* Min Time between relogins | 273 | atomic_t retry_relogin_timer; /* Min Time between relogins |
| 254 | * (4000 only) */ | 274 | * (4000 only) */ |
| 255 | atomic_t relogin_timer; /* Max Time to wait for relogin to complete */ | 275 | atomic_t relogin_timer; /* Max Time to wait for relogin to complete */ |
| @@ -378,7 +398,9 @@ struct scsi_qla_host { | |||
| 378 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ | 398 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ |
| 379 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ | 399 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ |
| 380 | #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ | 400 | #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ |
| 381 | 401 | #define AF_FW_RECOVERY 19 /* 0x00080000 */ | |
| 402 | #define AF_EEH_BUSY 20 /* 0x00100000 */ | ||
| 403 | #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ | ||
| 382 | 404 | ||
| 383 | unsigned long dpc_flags; | 405 | unsigned long dpc_flags; |
| 384 | 406 | ||
| @@ -474,7 +496,6 @@ struct scsi_qla_host { | |||
| 474 | uint32_t timer_active; | 496 | uint32_t timer_active; |
| 475 | 497 | ||
| 476 | /* Recovery Timers */ | 498 | /* Recovery Timers */ |
| 477 | uint32_t port_down_retry_count; | ||
| 478 | uint32_t discovery_wait; | 499 | uint32_t discovery_wait; |
| 479 | atomic_t check_relogin_timeouts; | 500 | atomic_t check_relogin_timeouts; |
| 480 | uint32_t retry_reset_ha_cnt; | 501 | uint32_t retry_reset_ha_cnt; |
| @@ -615,6 +636,15 @@ static inline int is_qla8022(struct scsi_qla_host *ha) | |||
| 615 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; | 636 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; |
| 616 | } | 637 | } |
| 617 | 638 | ||
| 639 | /* Note: Currently AER/EEH is now supported only for 8022 cards | ||
| 640 | * This function needs to be updated when AER/EEH is enabled | ||
| 641 | * for other cards. | ||
| 642 | */ | ||
| 643 | static inline int is_aer_supported(struct scsi_qla_host *ha) | ||
| 644 | { | ||
| 645 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; | ||
| 646 | } | ||
| 647 | |||
| 618 | static inline int adapter_up(struct scsi_qla_host *ha) | 648 | static inline int adapter_up(struct scsi_qla_host *ha) |
| 619 | { | 649 | { |
| 620 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && | 650 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index c94c9ddfb3a6..0336c6db8cb3 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
| @@ -673,17 +673,17 @@ struct flash_sys_info { | |||
| 673 | }; /* 200 */ | 673 | }; /* 200 */ |
| 674 | 674 | ||
| 675 | struct mbx_sys_info { | 675 | struct mbx_sys_info { |
| 676 | uint8_t board_id_str[16]; /* Keep board ID string first */ | 676 | uint8_t board_id_str[16]; /* 0-f Keep board ID string first */ |
| 677 | /* in this structure for GUI. */ | 677 | /* in this structure for GUI. */ |
| 678 | uint16_t board_id; /* board ID code */ | 678 | uint16_t board_id; /* 10-11 board ID code */ |
| 679 | uint16_t phys_port_cnt; /* number of physical network ports */ | 679 | uint16_t phys_port_cnt; /* 12-13 number of physical network ports */ |
| 680 | uint16_t port_num; /* network port for this PCI function */ | 680 | uint16_t port_num; /* 14-15 network port for this PCI function */ |
| 681 | /* (port 0 is first port) */ | 681 | /* (port 0 is first port) */ |
| 682 | uint8_t mac_addr[6]; /* MAC address for this PCI function */ | 682 | uint8_t mac_addr[6]; /* 16-1b MAC address for this PCI function */ |
| 683 | uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */ | 683 | uint32_t iscsi_pci_func_cnt; /* 1c-1f number of iSCSI PCI functions */ |
| 684 | uint32_t pci_func; /* this PCI function */ | 684 | uint32_t pci_func; /* 20-23 this PCI function */ |
| 685 | unsigned char serial_number[16]; /* serial number string */ | 685 | unsigned char serial_number[16]; /* 24-33 serial number string */ |
| 686 | uint8_t reserved[16]; | 686 | uint8_t reserved[12]; /* 34-3f */ |
| 687 | }; | 687 | }; |
| 688 | 688 | ||
| 689 | struct crash_record { | 689 | struct crash_record { |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c9cd5d6db982..f065204e401b 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
| @@ -93,6 +93,7 @@ void qla4xxx_free_irqs(struct scsi_qla_host *ha); | |||
| 93 | void qla4xxx_process_response_queue(struct scsi_qla_host *ha); | 93 | void qla4xxx_process_response_queue(struct scsi_qla_host *ha); |
| 94 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha); | 94 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha); |
| 95 | void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); | 95 | void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); |
| 96 | void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha); | ||
| 96 | 97 | ||
| 97 | void qla4_8xxx_pci_config(struct scsi_qla_host *); | 98 | void qla4_8xxx_pci_config(struct scsi_qla_host *); |
| 98 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); | 99 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); |
| @@ -131,6 +132,7 @@ void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha); | |||
| 131 | int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); | 132 | int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); |
| 132 | void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); | 133 | void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); |
| 133 | void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); | 134 | void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); |
| 135 | inline void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha); | ||
| 134 | 136 | ||
| 135 | extern int ql4xextended_error_logging; | 137 | extern int ql4xextended_error_logging; |
| 136 | extern int ql4xdiscoverywait; | 138 | extern int ql4xdiscoverywait; |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 30073577c3a4..4c9be77ee70b 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
| @@ -308,7 +308,6 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | |||
| 308 | DEBUG2(printk("scsi%ld: %s: unable to get firmware " | 308 | DEBUG2(printk("scsi%ld: %s: unable to get firmware " |
| 309 | "state\n", ha->host_no, __func__)); | 309 | "state\n", ha->host_no, __func__)); |
| 310 | break; | 310 | break; |
| 311 | |||
| 312 | } | 311 | } |
| 313 | 312 | ||
| 314 | if (ha->firmware_state & FW_STATE_ERROR) { | 313 | if (ha->firmware_state & FW_STATE_ERROR) { |
| @@ -445,6 +444,16 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) | |||
| 445 | { | 444 | { |
| 446 | int status = QLA_ERROR; | 445 | int status = QLA_ERROR; |
| 447 | 446 | ||
| 447 | if (is_aer_supported(ha) && | ||
| 448 | test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) | ||
| 449 | return status; | ||
| 450 | |||
| 451 | /* For 82xx, stop firmware before initializing because if BIOS | ||
| 452 | * has previously initialized firmware, then driver's initialize | ||
| 453 | * firmware will fail. */ | ||
| 454 | if (is_qla8022(ha)) | ||
| 455 | qla4_8xxx_stop_firmware(ha); | ||
| 456 | |||
| 448 | ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); | 457 | ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); |
| 449 | if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { | 458 | if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { |
| 450 | DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " | 459 | DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " |
| @@ -669,7 +678,6 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, | |||
| 669 | } | 678 | } |
| 670 | 679 | ||
| 671 | ddb_entry->fw_ddb_index = fw_ddb_index; | 680 | ddb_entry->fw_ddb_index = fw_ddb_index; |
| 672 | atomic_set(&ddb_entry->port_down_timer, ha->port_down_retry_count); | ||
| 673 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); | 681 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); |
| 674 | atomic_set(&ddb_entry->relogin_timer, 0); | 682 | atomic_set(&ddb_entry->relogin_timer, 0); |
| 675 | atomic_set(&ddb_entry->relogin_retry_count, 0); | 683 | atomic_set(&ddb_entry->relogin_retry_count, 0); |
| @@ -1556,8 +1564,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
| 1556 | /* Device is back online. */ | 1564 | /* Device is back online. */ |
| 1557 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { | 1565 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { |
| 1558 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); | 1566 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); |
| 1559 | atomic_set(&ddb_entry->port_down_timer, | ||
| 1560 | ha->port_down_retry_count); | ||
| 1561 | atomic_set(&ddb_entry->relogin_retry_count, 0); | 1567 | atomic_set(&ddb_entry->relogin_retry_count, 0); |
| 1562 | atomic_set(&ddb_entry->relogin_timer, 0); | 1568 | atomic_set(&ddb_entry->relogin_timer, 0); |
| 1563 | clear_bit(DF_RELOGIN, &ddb_entry->flags); | 1569 | clear_bit(DF_RELOGIN, &ddb_entry->flags); |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index f89973deac5b..4ef9ba112ee8 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
| @@ -19,7 +19,7 @@ qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) | |||
| 19 | 19 | ||
| 20 | /* Calculate number of free request entries. */ | 20 | /* Calculate number of free request entries. */ |
| 21 | if ((req_cnt + 2) >= ha->req_q_count) { | 21 | if ((req_cnt + 2) >= ha->req_q_count) { |
| 22 | cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | 22 | cnt = (uint16_t) ha->isp_ops->rd_shdw_req_q_out(ha); |
| 23 | if (ha->request_in < cnt) | 23 | if (ha->request_in < cnt) |
| 24 | ha->req_q_count = cnt - ha->request_in; | 24 | ha->req_q_count = cnt - ha->request_in; |
| 25 | else | 25 | else |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index aa65697a86b4..2a1ab63f3eb0 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
| @@ -816,6 +816,9 @@ irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id) | |||
| 816 | unsigned long flags = 0; | 816 | unsigned long flags = 0; |
| 817 | uint8_t reqs_count = 0; | 817 | uint8_t reqs_count = 0; |
| 818 | 818 | ||
| 819 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
| 820 | return IRQ_HANDLED; | ||
| 821 | |||
| 819 | ha->isr_count++; | 822 | ha->isr_count++; |
| 820 | status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | 823 | status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); |
| 821 | if (!(status & ha->nx_legacy_intr.int_vec_bit)) | 824 | if (!(status & ha->nx_legacy_intr.int_vec_bit)) |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 940ee561ee0a..90021704d8ca 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
| @@ -39,6 +39,22 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
| 39 | "pointer\n", ha->host_no, __func__)); | 39 | "pointer\n", ha->host_no, __func__)); |
| 40 | return status; | 40 | return status; |
| 41 | } | 41 | } |
| 42 | |||
| 43 | if (is_qla8022(ha) && | ||
| 44 | test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
| 45 | DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely " | ||
| 46 | "completing mbx cmd as firmware recovery detected\n", | ||
| 47 | ha->host_no, __func__)); | ||
| 48 | return status; | ||
| 49 | } | ||
| 50 | |||
| 51 | if ((is_aer_supported(ha)) && | ||
| 52 | (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { | ||
| 53 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " | ||
| 54 | "timeout MBX Exiting.\n", ha->host_no, __func__)); | ||
| 55 | return status; | ||
| 56 | } | ||
| 57 | |||
| 42 | /* Mailbox code active */ | 58 | /* Mailbox code active */ |
| 43 | wait_count = MBOX_TOV * 100; | 59 | wait_count = MBOX_TOV * 100; |
| 44 | 60 | ||
| @@ -150,6 +166,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
| 150 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { | 166 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { |
| 151 | if (time_after_eq(jiffies, wait_count)) | 167 | if (time_after_eq(jiffies, wait_count)) |
| 152 | break; | 168 | break; |
| 169 | |||
| 153 | /* | 170 | /* |
| 154 | * Service the interrupt. | 171 | * Service the interrupt. |
| 155 | * The ISR will save the mailbox status registers | 172 | * The ISR will save the mailbox status registers |
| @@ -196,6 +213,14 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
| 196 | 213 | ||
| 197 | /* Check for mailbox timeout. */ | 214 | /* Check for mailbox timeout. */ |
| 198 | if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { | 215 | if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { |
| 216 | if (is_qla8022(ha) && | ||
| 217 | test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
| 218 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
| 219 | "scsi%ld: %s: prematurely completing mbx cmd as " | ||
| 220 | "firmware recovery detected\n", | ||
| 221 | ha->host_no, __func__)); | ||
| 222 | goto mbox_exit; | ||
| 223 | } | ||
| 199 | DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," | 224 | DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," |
| 200 | " Scheduling Adapter Reset\n", ha->host_no, | 225 | " Scheduling Adapter Reset\n", ha->host_no, |
| 201 | mbx_cmd[0])); | 226 | mbx_cmd[0])); |
| @@ -246,6 +271,28 @@ mbox_exit: | |||
| 246 | return status; | 271 | return status; |
| 247 | } | 272 | } |
| 248 | 273 | ||
| 274 | void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) | ||
| 275 | { | ||
| 276 | set_bit(AF_FW_RECOVERY, &ha->flags); | ||
| 277 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", | ||
| 278 | ha->host_no, __func__); | ||
| 279 | |||
| 280 | if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { | ||
| 281 | if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { | ||
| 282 | complete(&ha->mbx_intr_comp); | ||
| 283 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " | ||
| 284 | "recovery, doing premature completion of " | ||
| 285 | "mbx cmd\n", ha->host_no, __func__); | ||
| 286 | |||
| 287 | } else { | ||
| 288 | set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | ||
| 289 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " | ||
| 290 | "recovery, doing premature completion of " | ||
| 291 | "polling mbx cmd\n", ha->host_no, __func__); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 249 | static uint8_t | 296 | static uint8_t |
| 250 | qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | 297 | qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, |
| 251 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) | 298 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) |
| @@ -361,7 +408,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, | |||
| 361 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ | 408 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ |
| 362 | 409 | ||
| 363 | /* Save Command Line Paramater info */ | 410 | /* Save Command Line Paramater info */ |
| 364 | ha->port_down_retry_count = le16_to_cpu(init_fw_cb->conn_ka_timeout); | ||
| 365 | ha->discovery_wait = ql4xdiscoverywait; | 411 | ha->discovery_wait = ql4xdiscoverywait; |
| 366 | 412 | ||
| 367 | if (ha->acb_version == ACB_SUPPORTED) { | 413 | if (ha->acb_version == ACB_SUPPORTED) { |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 3e119ae78397..e031a734836e 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
| @@ -1418,7 +1418,7 @@ static int qla4_8xxx_rcvpeg_ready(struct scsi_qla_host *ha) | |||
| 1418 | return QLA_SUCCESS; | 1418 | return QLA_SUCCESS; |
| 1419 | } | 1419 | } |
| 1420 | 1420 | ||
| 1421 | static inline void | 1421 | inline void |
| 1422 | qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) | 1422 | qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) |
| 1423 | { | 1423 | { |
| 1424 | uint32_t drv_active; | 1424 | uint32_t drv_active; |
| @@ -1441,11 +1441,15 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) | |||
| 1441 | static inline int | 1441 | static inline int |
| 1442 | qla4_8xxx_need_reset(struct scsi_qla_host *ha) | 1442 | qla4_8xxx_need_reset(struct scsi_qla_host *ha) |
| 1443 | { | 1443 | { |
| 1444 | uint32_t drv_state; | 1444 | uint32_t drv_state, drv_active; |
| 1445 | int rval; | 1445 | int rval; |
| 1446 | 1446 | ||
| 1447 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
| 1447 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 1448 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
| 1448 | rval = drv_state & (1 << (ha->func_num * 4)); | 1449 | rval = drv_state & (1 << (ha->func_num * 4)); |
| 1450 | if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) | ||
| 1451 | rval = 1; | ||
| 1452 | |||
| 1449 | return rval; | 1453 | return rval; |
| 1450 | } | 1454 | } |
| 1451 | 1455 | ||
| @@ -1949,7 +1953,8 @@ qla4_8xxx_get_fdt_info(struct scsi_qla_host *ha) | |||
| 1949 | uint16_t cnt, chksum; | 1953 | uint16_t cnt, chksum; |
| 1950 | uint16_t *wptr; | 1954 | uint16_t *wptr; |
| 1951 | struct qla_fdt_layout *fdt; | 1955 | struct qla_fdt_layout *fdt; |
| 1952 | uint16_t mid, fid; | 1956 | uint16_t mid = 0; |
| 1957 | uint16_t fid = 0; | ||
| 1953 | struct ql82xx_hw_data *hw = &ha->hw; | 1958 | struct ql82xx_hw_data *hw = &ha->hw; |
| 1954 | 1959 | ||
| 1955 | hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; | 1960 | hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; |
| @@ -2105,6 +2110,9 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | |||
| 2105 | qla4_8xxx_clear_rst_ready(ha); | 2110 | qla4_8xxx_clear_rst_ready(ha); |
| 2106 | qla4_8xxx_idc_unlock(ha); | 2111 | qla4_8xxx_idc_unlock(ha); |
| 2107 | 2112 | ||
| 2113 | if (rval == QLA_SUCCESS) | ||
| 2114 | clear_bit(AF_FW_RECOVERY, &ha->flags); | ||
| 2115 | |||
| 2108 | return rval; | 2116 | return rval; |
| 2109 | } | 2117 | } |
| 2110 | 2118 | ||
| @@ -2145,7 +2153,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) | |||
| 2145 | goto exit_validate_mac82; | 2153 | goto exit_validate_mac82; |
| 2146 | } | 2154 | } |
| 2147 | 2155 | ||
| 2148 | if (mbox_sts[4] < sizeof(*sys_info)) { | 2156 | /* Make sure we receive the minimum required data to cache internally */ |
| 2157 | if (mbox_sts[4] < offsetof(struct mbx_sys_info, reserved)) { | ||
| 2149 | DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" | 2158 | DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" |
| 2150 | " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); | 2159 | " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); |
| 2151 | goto exit_validate_mac82; | 2160 | goto exit_validate_mac82; |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5529b2a39741..370d40ff1529 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
| @@ -163,10 +163,10 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | |||
| 163 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { | 163 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { |
| 164 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); | 164 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); |
| 165 | 165 | ||
| 166 | DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " | 166 | DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout " |
| 167 | "of (%d) secs exhausted, marking device DEAD.\n", | 167 | "of (%d) secs exhausted, marking device DEAD.\n", |
| 168 | ha->host_no, __func__, ddb_entry->fw_ddb_index, | 168 | ha->host_no, __func__, ddb_entry->fw_ddb_index, |
| 169 | ha->port_down_retry_count)); | 169 | QL4_SESS_RECOVERY_TMO)); |
| 170 | 170 | ||
| 171 | qla4xxx_wake_dpc(ha); | 171 | qla4xxx_wake_dpc(ha); |
| 172 | } | 172 | } |
| @@ -298,7 +298,8 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry) | |||
| 298 | { | 298 | { |
| 299 | int err; | 299 | int err; |
| 300 | 300 | ||
| 301 | ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count; | 301 | ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO; |
| 302 | |||
| 302 | err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); | 303 | err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); |
| 303 | if (err) { | 304 | if (err) { |
| 304 | DEBUG2(printk(KERN_ERR "Could not add session.\n")); | 305 | DEBUG2(printk(KERN_ERR "Could not add session.\n")); |
| @@ -474,6 +475,14 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, | |||
| 474 | struct srb *srb; | 475 | struct srb *srb; |
| 475 | int rval; | 476 | int rval; |
| 476 | 477 | ||
| 478 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | ||
| 479 | if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) | ||
| 480 | cmd->result = DID_NO_CONNECT << 16; | ||
| 481 | else | ||
| 482 | cmd->result = DID_REQUEUE << 16; | ||
| 483 | goto qc_fail_command; | ||
| 484 | } | ||
| 485 | |||
| 477 | if (!sess) { | 486 | if (!sess) { |
| 478 | cmd->result = DID_IMM_RETRY << 16; | 487 | cmd->result = DID_IMM_RETRY << 16; |
| 479 | goto qc_fail_command; | 488 | goto qc_fail_command; |
| @@ -654,6 +663,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
| 654 | uint32_t fw_heartbeat_counter, halt_status; | 663 | uint32_t fw_heartbeat_counter, halt_status; |
| 655 | 664 | ||
| 656 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 665 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
| 666 | /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ | ||
| 667 | if (fw_heartbeat_counter == 0xffffffff) { | ||
| 668 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " | ||
| 669 | "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", | ||
| 670 | ha->host_no, __func__)); | ||
| 671 | return; | ||
| 672 | } | ||
| 657 | 673 | ||
| 658 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { | 674 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { |
| 659 | ha->seconds_since_last_heartbeat++; | 675 | ha->seconds_since_last_heartbeat++; |
| @@ -662,6 +678,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
| 662 | ha->seconds_since_last_heartbeat = 0; | 678 | ha->seconds_since_last_heartbeat = 0; |
| 663 | halt_status = qla4_8xxx_rd_32(ha, | 679 | halt_status = qla4_8xxx_rd_32(ha, |
| 664 | QLA82XX_PEG_HALT_STATUS1); | 680 | QLA82XX_PEG_HALT_STATUS1); |
| 681 | |||
| 665 | /* Since we cannot change dev_state in interrupt | 682 | /* Since we cannot change dev_state in interrupt |
| 666 | * context, set appropriate DPC flag then wakeup | 683 | * context, set appropriate DPC flag then wakeup |
| 667 | * DPC */ | 684 | * DPC */ |
| @@ -673,6 +690,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
| 673 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 690 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
| 674 | } | 691 | } |
| 675 | qla4xxx_wake_dpc(ha); | 692 | qla4xxx_wake_dpc(ha); |
| 693 | qla4xxx_mailbox_premature_completion(ha); | ||
| 676 | } | 694 | } |
| 677 | } | 695 | } |
| 678 | ha->fw_heartbeat_counter = fw_heartbeat_counter; | 696 | ha->fw_heartbeat_counter = fw_heartbeat_counter; |
| @@ -698,6 +716,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
| 698 | ha->host_no, __func__); | 716 | ha->host_no, __func__); |
| 699 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 717 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
| 700 | qla4xxx_wake_dpc(ha); | 718 | qla4xxx_wake_dpc(ha); |
| 719 | qla4xxx_mailbox_premature_completion(ha); | ||
| 701 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | 720 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && |
| 702 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | 721 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { |
| 703 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", | 722 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", |
| @@ -719,6 +738,19 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
| 719 | { | 738 | { |
| 720 | struct ddb_entry *ddb_entry, *dtemp; | 739 | struct ddb_entry *ddb_entry, *dtemp; |
| 721 | int start_dpc = 0; | 740 | int start_dpc = 0; |
| 741 | uint16_t w; | ||
| 742 | |||
| 743 | /* If we are in the middle of AER/EEH processing | ||
| 744 | * skip any processing and reschedule the timer | ||
| 745 | */ | ||
| 746 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | ||
| 747 | mod_timer(&ha->timer, jiffies + HZ); | ||
| 748 | return; | ||
| 749 | } | ||
| 750 | |||
| 751 | /* Hardware read to trigger an EEH error during mailbox waits. */ | ||
| 752 | if (!pci_channel_offline(ha->pdev)) | ||
| 753 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); | ||
| 722 | 754 | ||
| 723 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | 755 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { |
| 724 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", | 756 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", |
| @@ -1207,7 +1239,13 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
| 1207 | 1239 | ||
| 1208 | /* Initialization not yet finished. Don't do anything yet. */ | 1240 | /* Initialization not yet finished. Don't do anything yet. */ |
| 1209 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1241 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
| 1210 | return; | 1242 | goto do_dpc_exit; |
| 1243 | |||
| 1244 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | ||
| 1245 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", | ||
| 1246 | ha->host_no, __func__, ha->flags)); | ||
| 1247 | goto do_dpc_exit; | ||
| 1248 | } | ||
| 1211 | 1249 | ||
| 1212 | /* HBA is in the process of being permanently disabled. | 1250 | /* HBA is in the process of being permanently disabled. |
| 1213 | * Don't process anything */ | 1251 | * Don't process anything */ |
| @@ -1346,6 +1384,8 @@ dpc_post_reset_ha: | |||
| 1346 | } | 1384 | } |
| 1347 | } | 1385 | } |
| 1348 | } | 1386 | } |
| 1387 | |||
| 1388 | do_dpc_exit: | ||
| 1349 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | 1389 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); |
| 1350 | } | 1390 | } |
| 1351 | 1391 | ||
| @@ -1612,6 +1652,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
| 1612 | ha->host = host; | 1652 | ha->host = host; |
| 1613 | ha->host_no = host->host_no; | 1653 | ha->host_no = host->host_no; |
| 1614 | 1654 | ||
| 1655 | pci_enable_pcie_error_reporting(pdev); | ||
| 1656 | |||
| 1615 | /* Setup Runtime configurable options */ | 1657 | /* Setup Runtime configurable options */ |
| 1616 | if (is_qla8022(ha)) { | 1658 | if (is_qla8022(ha)) { |
| 1617 | ha->isp_ops = &qla4_8xxx_isp_ops; | 1659 | ha->isp_ops = &qla4_8xxx_isp_ops; |
| @@ -1630,6 +1672,10 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
| 1630 | ha->isp_ops = &qla4xxx_isp_ops; | 1672 | ha->isp_ops = &qla4xxx_isp_ops; |
| 1631 | } | 1673 | } |
| 1632 | 1674 | ||
| 1675 | /* Set EEH reset type to fundamental if required by hba */ | ||
| 1676 | if (is_qla8022(ha)) | ||
| 1677 | pdev->needs_freset = 1; | ||
| 1678 | |||
| 1633 | /* Configure PCI I/O space. */ | 1679 | /* Configure PCI I/O space. */ |
| 1634 | ret = ha->isp_ops->iospace_config(ha); | 1680 | ret = ha->isp_ops->iospace_config(ha); |
| 1635 | if (ret) | 1681 | if (ret) |
| @@ -1726,6 +1772,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
| 1726 | } | 1772 | } |
| 1727 | } | 1773 | } |
| 1728 | 1774 | ||
| 1775 | pci_save_state(ha->pdev); | ||
| 1729 | ha->isp_ops->enable_intrs(ha); | 1776 | ha->isp_ops->enable_intrs(ha); |
| 1730 | 1777 | ||
| 1731 | /* Start timer thread. */ | 1778 | /* Start timer thread. */ |
| @@ -1752,6 +1799,7 @@ probe_failed: | |||
| 1752 | qla4xxx_free_adapter(ha); | 1799 | qla4xxx_free_adapter(ha); |
| 1753 | 1800 | ||
| 1754 | probe_failed_ioconfig: | 1801 | probe_failed_ioconfig: |
| 1802 | pci_disable_pcie_error_reporting(pdev); | ||
| 1755 | scsi_host_put(ha->host); | 1803 | scsi_host_put(ha->host); |
| 1756 | 1804 | ||
| 1757 | probe_disable_device: | 1805 | probe_disable_device: |
| @@ -1781,6 +1829,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
| 1781 | 1829 | ||
| 1782 | scsi_host_put(ha->host); | 1830 | scsi_host_put(ha->host); |
| 1783 | 1831 | ||
| 1832 | pci_disable_pcie_error_reporting(pdev); | ||
| 1784 | pci_disable_device(pdev); | 1833 | pci_disable_device(pdev); |
| 1785 | pci_set_drvdata(pdev, NULL); | 1834 | pci_set_drvdata(pdev, NULL); |
| 1786 | } | 1835 | } |
| @@ -1877,6 +1926,17 @@ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, | |||
| 1877 | int done = 0; | 1926 | int done = 0; |
| 1878 | struct srb *rp; | 1927 | struct srb *rp; |
| 1879 | uint32_t max_wait_time = EH_WAIT_CMD_TOV; | 1928 | uint32_t max_wait_time = EH_WAIT_CMD_TOV; |
| 1929 | int ret = SUCCESS; | ||
| 1930 | |||
| 1931 | /* Dont wait on command if PCI error is being handled | ||
| 1932 | * by PCI AER driver | ||
| 1933 | */ | ||
| 1934 | if (unlikely(pci_channel_offline(ha->pdev)) || | ||
| 1935 | (test_bit(AF_EEH_BUSY, &ha->flags))) { | ||
| 1936 | ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n", | ||
| 1937 | ha->host_no, __func__); | ||
| 1938 | return ret; | ||
| 1939 | } | ||
| 1880 | 1940 | ||
| 1881 | do { | 1941 | do { |
| 1882 | /* Checking to see if its returned to OS */ | 1942 | /* Checking to see if its returned to OS */ |
| @@ -2172,6 +2232,252 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
| 2172 | return return_status; | 2232 | return return_status; |
| 2173 | } | 2233 | } |
| 2174 | 2234 | ||
| 2235 | /* PCI AER driver recovers from all correctable errors w/o | ||
| 2236 | * driver intervention. For uncorrectable errors PCI AER | ||
| 2237 | * driver calls the following device driver's callbacks | ||
| 2238 | * | ||
| 2239 | * - Fatal Errors - link_reset | ||
| 2240 | * - Non-Fatal Errors - driver's pci_error_detected() which | ||
| 2241 | * returns CAN_RECOVER, NEED_RESET or DISCONNECT. | ||
| 2242 | * | ||
| 2243 | * PCI AER driver calls | ||
| 2244 | * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled | ||
| 2245 | * returns RECOVERED or NEED_RESET if fw_hung | ||
| 2246 | * NEED_RESET - driver's slot_reset() | ||
| 2247 | * DISCONNECT - device is dead & cannot recover | ||
| 2248 | * RECOVERED - driver's pci_resume() | ||
| 2249 | */ | ||
| 2250 | static pci_ers_result_t | ||
| 2251 | qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | ||
| 2252 | { | ||
| 2253 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
| 2254 | |||
| 2255 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n", | ||
| 2256 | ha->host_no, __func__, state); | ||
| 2257 | |||
| 2258 | if (!is_aer_supported(ha)) | ||
| 2259 | return PCI_ERS_RESULT_NONE; | ||
| 2260 | |||
| 2261 | switch (state) { | ||
| 2262 | case pci_channel_io_normal: | ||
| 2263 | clear_bit(AF_EEH_BUSY, &ha->flags); | ||
| 2264 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
| 2265 | case pci_channel_io_frozen: | ||
| 2266 | set_bit(AF_EEH_BUSY, &ha->flags); | ||
| 2267 | qla4xxx_mailbox_premature_completion(ha); | ||
| 2268 | qla4xxx_free_irqs(ha); | ||
| 2269 | pci_disable_device(pdev); | ||
| 2270 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 2271 | case pci_channel_io_perm_failure: | ||
| 2272 | set_bit(AF_EEH_BUSY, &ha->flags); | ||
| 2273 | set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags); | ||
| 2274 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | ||
| 2275 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 2276 | } | ||
| 2277 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 2278 | } | ||
| 2279 | |||
| 2280 | /** | ||
| 2281 | * qla4xxx_pci_mmio_enabled() gets called if | ||
| 2282 | * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER | ||
| 2283 | * and read/write to the device still works. | ||
| 2284 | **/ | ||
| 2285 | static pci_ers_result_t | ||
| 2286 | qla4xxx_pci_mmio_enabled(struct pci_dev *pdev) | ||
| 2287 | { | ||
| 2288 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
| 2289 | |||
| 2290 | if (!is_aer_supported(ha)) | ||
| 2291 | return PCI_ERS_RESULT_NONE; | ||
| 2292 | |||
| 2293 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) { | ||
| 2294 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: firmware hang -- " | ||
| 2295 | "mmio_enabled\n", ha->host_no, __func__); | ||
| 2296 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 2297 | } else | ||
| 2298 | return PCI_ERS_RESULT_RECOVERED; | ||
| 2299 | } | ||
| 2300 | |||
| 2301 | uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) | ||
| 2302 | { | ||
| 2303 | uint32_t rval = QLA_ERROR; | ||
| 2304 | int fn; | ||
| 2305 | struct pci_dev *other_pdev = NULL; | ||
| 2306 | |||
| 2307 | ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__); | ||
| 2308 | |||
| 2309 | set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
| 2310 | |||
| 2311 | if (test_bit(AF_ONLINE, &ha->flags)) { | ||
| 2312 | clear_bit(AF_ONLINE, &ha->flags); | ||
| 2313 | qla4xxx_mark_all_devices_missing(ha); | ||
| 2314 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
| 2315 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); | ||
| 2316 | } | ||
| 2317 | |||
| 2318 | fn = PCI_FUNC(ha->pdev->devfn); | ||
| 2319 | while (fn > 0) { | ||
| 2320 | fn--; | ||
| 2321 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at " | ||
| 2322 | "func %x\n", ha->host_no, __func__, fn); | ||
| 2323 | /* Get the pci device given the domain, bus, | ||
| 2324 | * slot/function number */ | ||
| 2325 | other_pdev = | ||
| 2326 | pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus), | ||
| 2327 | ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), | ||
| 2328 | fn)); | ||
| 2329 | |||
| 2330 | if (!other_pdev) | ||
| 2331 | continue; | ||
| 2332 | |||
| 2333 | if (atomic_read(&other_pdev->enable_cnt)) { | ||
| 2334 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI " | ||
| 2335 | "func in enabled state%x\n", ha->host_no, | ||
| 2336 | __func__, fn); | ||
| 2337 | pci_dev_put(other_pdev); | ||
| 2338 | break; | ||
| 2339 | } | ||
| 2340 | pci_dev_put(other_pdev); | ||
| 2341 | } | ||
| 2342 | |||
| 2343 | /* The first function on the card, the reset owner will | ||
| 2344 | * start & initialize the firmware. The other functions | ||
| 2345 | * on the card will reset the firmware context | ||
| 2346 | */ | ||
| 2347 | if (!fn) { | ||
| 2348 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset " | ||
| 2349 | "0x%x is the owner\n", ha->host_no, __func__, | ||
| 2350 | ha->pdev->devfn); | ||
| 2351 | |||
| 2352 | qla4_8xxx_idc_lock(ha); | ||
| 2353 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
| 2354 | QLA82XX_DEV_COLD); | ||
| 2355 | |||
| 2356 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, | ||
| 2357 | QLA82XX_IDC_VERSION); | ||
| 2358 | |||
| 2359 | qla4_8xxx_idc_unlock(ha); | ||
| 2360 | clear_bit(AF_FW_RECOVERY, &ha->flags); | ||
| 2361 | rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); | ||
| 2362 | qla4_8xxx_idc_lock(ha); | ||
| 2363 | |||
| 2364 | if (rval != QLA_SUCCESS) { | ||
| 2365 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " | ||
| 2366 | "FAILED\n", ha->host_no, __func__); | ||
| 2367 | qla4_8xxx_clear_drv_active(ha); | ||
| 2368 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
| 2369 | QLA82XX_DEV_FAILED); | ||
| 2370 | } else { | ||
| 2371 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " | ||
| 2372 | "READY\n", ha->host_no, __func__); | ||
| 2373 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
| 2374 | QLA82XX_DEV_READY); | ||
| 2375 | /* Clear driver state register */ | ||
| 2376 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0); | ||
| 2377 | qla4_8xxx_set_drv_active(ha); | ||
| 2378 | ha->isp_ops->enable_intrs(ha); | ||
| 2379 | } | ||
| 2380 | qla4_8xxx_idc_unlock(ha); | ||
| 2381 | } else { | ||
| 2382 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not " | ||
| 2383 | "the reset owner\n", ha->host_no, __func__, | ||
| 2384 | ha->pdev->devfn); | ||
| 2385 | if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == | ||
| 2386 | QLA82XX_DEV_READY)) { | ||
| 2387 | clear_bit(AF_FW_RECOVERY, &ha->flags); | ||
| 2388 | rval = qla4xxx_initialize_adapter(ha, | ||
| 2389 | PRESERVE_DDB_LIST); | ||
| 2390 | if (rval == QLA_SUCCESS) | ||
| 2391 | ha->isp_ops->enable_intrs(ha); | ||
| 2392 | qla4_8xxx_idc_lock(ha); | ||
| 2393 | qla4_8xxx_set_drv_active(ha); | ||
| 2394 | qla4_8xxx_idc_unlock(ha); | ||
| 2395 | } | ||
| 2396 | } | ||
| 2397 | clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
| 2398 | return rval; | ||
| 2399 | } | ||
| 2400 | |||
| 2401 | static pci_ers_result_t | ||
| 2402 | qla4xxx_pci_slot_reset(struct pci_dev *pdev) | ||
| 2403 | { | ||
| 2404 | pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; | ||
| 2405 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
| 2406 | int rc; | ||
| 2407 | |||
| 2408 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n", | ||
| 2409 | ha->host_no, __func__); | ||
| 2410 | |||
| 2411 | if (!is_aer_supported(ha)) | ||
| 2412 | return PCI_ERS_RESULT_NONE; | ||
| 2413 | |||
| 2414 | /* Restore the saved state of PCIe device - | ||
| 2415 | * BAR registers, PCI Config space, PCIX, MSI, | ||
| 2416 | * IOV states | ||
| 2417 | */ | ||
| 2418 | pci_restore_state(pdev); | ||
| 2419 | |||
| 2420 | /* pci_restore_state() clears the saved_state flag of the device | ||
| 2421 | * save restored state which resets saved_state flag | ||
| 2422 | */ | ||
| 2423 | pci_save_state(pdev); | ||
| 2424 | |||
| 2425 | /* Initialize device or resume if in suspended state */ | ||
| 2426 | rc = pci_enable_device(pdev); | ||
| 2427 | if (rc) { | ||
| 2428 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable " | ||
| 2429 | "device after reset\n", ha->host_no, __func__); | ||
| 2430 | goto exit_slot_reset; | ||
| 2431 | } | ||
| 2432 | |||
| 2433 | ret = qla4xxx_request_irqs(ha); | ||
| 2434 | if (ret) { | ||
| 2435 | ql4_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d" | ||
| 2436 | " already in use.\n", pdev->irq); | ||
| 2437 | goto exit_slot_reset; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | if (is_qla8022(ha)) { | ||
| 2441 | if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) { | ||
| 2442 | ret = PCI_ERS_RESULT_RECOVERED; | ||
| 2443 | goto exit_slot_reset; | ||
| 2444 | } else | ||
| 2445 | goto exit_slot_reset; | ||
| 2446 | } | ||
| 2447 | |||
| 2448 | exit_slot_reset: | ||
| 2449 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n" | ||
| 2450 | "device after reset\n", ha->host_no, __func__, ret); | ||
| 2451 | return ret; | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | static void | ||
| 2455 | qla4xxx_pci_resume(struct pci_dev *pdev) | ||
| 2456 | { | ||
| 2457 | struct scsi_qla_host *ha = pci_get_drvdata(pdev); | ||
| 2458 | int ret; | ||
| 2459 | |||
| 2460 | ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n", | ||
| 2461 | ha->host_no, __func__); | ||
| 2462 | |||
| 2463 | ret = qla4xxx_wait_for_hba_online(ha); | ||
| 2464 | if (ret != QLA_SUCCESS) { | ||
| 2465 | ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to " | ||
| 2466 | "resume I/O from slot/link_reset\n", ha->host_no, | ||
| 2467 | __func__); | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
| 2471 | clear_bit(AF_EEH_BUSY, &ha->flags); | ||
| 2472 | } | ||
| 2473 | |||
| 2474 | static struct pci_error_handlers qla4xxx_err_handler = { | ||
| 2475 | .error_detected = qla4xxx_pci_error_detected, | ||
| 2476 | .mmio_enabled = qla4xxx_pci_mmio_enabled, | ||
| 2477 | .slot_reset = qla4xxx_pci_slot_reset, | ||
| 2478 | .resume = qla4xxx_pci_resume, | ||
| 2479 | }; | ||
| 2480 | |||
| 2175 | static struct pci_device_id qla4xxx_pci_tbl[] = { | 2481 | static struct pci_device_id qla4xxx_pci_tbl[] = { |
| 2176 | { | 2482 | { |
| 2177 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2483 | .vendor = PCI_VENDOR_ID_QLOGIC, |
| @@ -2206,6 +2512,7 @@ static struct pci_driver qla4xxx_pci_driver = { | |||
| 2206 | .id_table = qla4xxx_pci_tbl, | 2512 | .id_table = qla4xxx_pci_tbl, |
| 2207 | .probe = qla4xxx_probe_adapter, | 2513 | .probe = qla4xxx_probe_adapter, |
| 2208 | .remove = qla4xxx_remove_adapter, | 2514 | .remove = qla4xxx_remove_adapter, |
| 2515 | .err_handler = &qla4xxx_err_handler, | ||
| 2209 | }; | 2516 | }; |
| 2210 | 2517 | ||
| 2211 | static int __init qla4xxx_module_init(void) | 2518 | static int __init qla4xxx_module_init(void) |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index c905dbd75331..a77b973f2cbc 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
| @@ -5,4 +5,4 @@ | |||
| 5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k2" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k3" |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index bbbc186dbc1a..1de30eb83bb0 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -473,14 +473,17 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) | |||
| 473 | */ | 473 | */ |
| 474 | return SUCCESS; | 474 | return SUCCESS; |
| 475 | case RESERVATION_CONFLICT: | 475 | case RESERVATION_CONFLICT: |
| 476 | /* | 476 | if (scmd->cmnd[0] == TEST_UNIT_READY) |
| 477 | * let issuer deal with this, it could be just fine | 477 | /* it is a success, we probed the device and |
| 478 | */ | 478 | * found it */ |
| 479 | return SUCCESS; | 479 | return SUCCESS; |
| 480 | /* otherwise, we failed to send the command */ | ||
| 481 | return FAILED; | ||
| 480 | case QUEUE_FULL: | 482 | case QUEUE_FULL: |
| 481 | scsi_handle_queue_full(scmd->device); | 483 | scsi_handle_queue_full(scmd->device); |
| 482 | /* fall through */ | 484 | /* fall through */ |
| 483 | case BUSY: | 485 | case BUSY: |
| 486 | return NEEDS_RETRY; | ||
| 484 | default: | 487 | default: |
| 485 | return FAILED; | 488 | return FAILED; |
| 486 | } | 489 | } |
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 66241dd525ae..c399be979921 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
| @@ -185,6 +185,7 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) | |||
| 185 | dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, | 185 | dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, |
| 186 | rq_data_dir(cmd->request)); | 186 | rq_data_dir(cmd->request)); |
| 187 | scsi_unmap_user_pages(tcmd); | 187 | scsi_unmap_user_pages(tcmd); |
| 188 | tcmd->rq->bio = NULL; | ||
| 188 | scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); | 189 | scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); |
| 189 | } | 190 | } |
| 190 | 191 | ||
