diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 463 |
1 files changed, 346 insertions, 117 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index c9aa7611e408..11d2602ae88e 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #include <linux/moduleparam.h> | 70 | #include <linux/moduleparam.h> |
71 | #include <linux/dma-mapping.h> | 71 | #include <linux/dma-mapping.h> |
72 | #include <linux/delay.h> | 72 | #include <linux/delay.h> |
73 | #include <linux/of.h> | ||
73 | #include <asm/firmware.h> | 74 | #include <asm/firmware.h> |
74 | #include <asm/vio.h> | 75 | #include <asm/vio.h> |
75 | #include <asm/firmware.h> | 76 | #include <asm/firmware.h> |
@@ -87,9 +88,15 @@ | |||
87 | */ | 88 | */ |
88 | static int max_id = 64; | 89 | static int max_id = 64; |
89 | static int max_channel = 3; | 90 | static int max_channel = 3; |
90 | static int init_timeout = 5; | 91 | static int init_timeout = 300; |
92 | static int login_timeout = 60; | ||
93 | static int info_timeout = 30; | ||
94 | static int abort_timeout = 60; | ||
95 | static int reset_timeout = 60; | ||
91 | static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; | 96 | static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; |
92 | static int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2; | 97 | static int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2; |
98 | static int fast_fail = 1; | ||
99 | static int client_reserve = 1; | ||
93 | 100 | ||
94 | static struct scsi_transport_template *ibmvscsi_transport_template; | 101 | static struct scsi_transport_template *ibmvscsi_transport_template; |
95 | 102 | ||
@@ -110,6 +117,10 @@ module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR); | |||
110 | MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds"); | 117 | MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds"); |
111 | module_param_named(max_requests, max_requests, int, S_IRUGO); | 118 | module_param_named(max_requests, max_requests, int, S_IRUGO); |
112 | MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter"); | 119 | MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter"); |
120 | module_param_named(fast_fail, fast_fail, int, S_IRUGO | S_IWUSR); | ||
121 | MODULE_PARM_DESC(fast_fail, "Enable fast fail. [Default=1]"); | ||
122 | module_param_named(client_reserve, client_reserve, int, S_IRUGO ); | ||
123 | MODULE_PARM_DESC(client_reserve, "Attempt client managed reserve/release"); | ||
113 | 124 | ||
114 | /* ------------------------------------------------------------ | 125 | /* ------------------------------------------------------------ |
115 | * Routines for the event pool and event structs | 126 | * Routines for the event pool and event structs |
@@ -781,105 +792,53 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
781 | /* ------------------------------------------------------------ | 792 | /* ------------------------------------------------------------ |
782 | * Routines for driver initialization | 793 | * Routines for driver initialization |
783 | */ | 794 | */ |
795 | |||
784 | /** | 796 | /** |
785 | * adapter_info_rsp: - Handle response to MAD adapter info request | 797 | * map_persist_bufs: - Pre-map persistent data for adapter logins |
786 | * @evt_struct: srp_event_struct with the response | 798 | * @hostdata: ibmvscsi_host_data of host |
787 | * | 799 | * |
788 | * Used as a "done" callback by when sending adapter_info. Gets called | 800 | * Map the capabilities and adapter info DMA buffers to avoid runtime failures. |
789 | * by ibmvscsi_handle_crq() | 801 | * Return 1 on error, 0 on success. |
790 | */ | 802 | */ |
791 | static void adapter_info_rsp(struct srp_event_struct *evt_struct) | 803 | static int map_persist_bufs(struct ibmvscsi_host_data *hostdata) |
792 | { | 804 | { |
793 | struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; | ||
794 | dma_unmap_single(hostdata->dev, | ||
795 | evt_struct->iu.mad.adapter_info.buffer, | ||
796 | evt_struct->iu.mad.adapter_info.common.length, | ||
797 | DMA_BIDIRECTIONAL); | ||
798 | 805 | ||
799 | if (evt_struct->xfer_iu->mad.adapter_info.common.status) { | 806 | hostdata->caps_addr = dma_map_single(hostdata->dev, &hostdata->caps, |
800 | dev_err(hostdata->dev, "error %d getting adapter info\n", | 807 | sizeof(hostdata->caps), DMA_BIDIRECTIONAL); |
801 | evt_struct->xfer_iu->mad.adapter_info.common.status); | 808 | |
802 | } else { | 809 | if (dma_mapping_error(hostdata->dev, hostdata->caps_addr)) { |
803 | dev_info(hostdata->dev, "host srp version: %s, " | 810 | dev_err(hostdata->dev, "Unable to map capabilities buffer!\n"); |
804 | "host partition %s (%d), OS %d, max io %u\n", | 811 | return 1; |
805 | hostdata->madapter_info.srp_version, | ||
806 | hostdata->madapter_info.partition_name, | ||
807 | hostdata->madapter_info.partition_number, | ||
808 | hostdata->madapter_info.os_type, | ||
809 | hostdata->madapter_info.port_max_txu[0]); | ||
810 | |||
811 | if (hostdata->madapter_info.port_max_txu[0]) | ||
812 | hostdata->host->max_sectors = | ||
813 | hostdata->madapter_info.port_max_txu[0] >> 9; | ||
814 | |||
815 | if (hostdata->madapter_info.os_type == 3 && | ||
816 | strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { | ||
817 | dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n", | ||
818 | hostdata->madapter_info.srp_version); | ||
819 | dev_err(hostdata->dev, "limiting scatterlists to %d\n", | ||
820 | MAX_INDIRECT_BUFS); | ||
821 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | ||
822 | } | ||
823 | } | 812 | } |
813 | |||
814 | hostdata->adapter_info_addr = dma_map_single(hostdata->dev, | ||
815 | &hostdata->madapter_info, | ||
816 | sizeof(hostdata->madapter_info), | ||
817 | DMA_BIDIRECTIONAL); | ||
818 | if (dma_mapping_error(hostdata->dev, hostdata->adapter_info_addr)) { | ||
819 | dev_err(hostdata->dev, "Unable to map adapter info buffer!\n"); | ||
820 | dma_unmap_single(hostdata->dev, hostdata->caps_addr, | ||
821 | sizeof(hostdata->caps), DMA_BIDIRECTIONAL); | ||
822 | return 1; | ||
823 | } | ||
824 | |||
825 | return 0; | ||
824 | } | 826 | } |
825 | 827 | ||
826 | /** | 828 | /** |
827 | * send_mad_adapter_info: - Sends the mad adapter info request | 829 | * unmap_persist_bufs: - Unmap persistent data needed for adapter logins |
828 | * and stores the result so it can be retrieved with | 830 | * @hostdata: ibmvscsi_host_data of host |
829 | * sysfs. We COULD consider causing a failure if the | 831 | * |
830 | * returned SRP version doesn't match ours. | 832 | * Unmap the capabilities and adapter info DMA buffers |
831 | * @hostdata: ibmvscsi_host_data of host | 833 | */ |
832 | * | 834 | static void unmap_persist_bufs(struct ibmvscsi_host_data *hostdata) |
833 | * Returns zero if successful. | ||
834 | */ | ||
835 | static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) | ||
836 | { | 835 | { |
837 | struct viosrp_adapter_info *req; | 836 | dma_unmap_single(hostdata->dev, hostdata->caps_addr, |
838 | struct srp_event_struct *evt_struct; | 837 | sizeof(hostdata->caps), DMA_BIDIRECTIONAL); |
839 | unsigned long flags; | ||
840 | dma_addr_t addr; | ||
841 | |||
842 | evt_struct = get_event_struct(&hostdata->pool); | ||
843 | if (!evt_struct) { | ||
844 | dev_err(hostdata->dev, | ||
845 | "couldn't allocate an event for ADAPTER_INFO_REQ!\n"); | ||
846 | return; | ||
847 | } | ||
848 | |||
849 | init_event_struct(evt_struct, | ||
850 | adapter_info_rsp, | ||
851 | VIOSRP_MAD_FORMAT, | ||
852 | init_timeout); | ||
853 | |||
854 | req = &evt_struct->iu.mad.adapter_info; | ||
855 | memset(req, 0x00, sizeof(*req)); | ||
856 | |||
857 | req->common.type = VIOSRP_ADAPTER_INFO_TYPE; | ||
858 | req->common.length = sizeof(hostdata->madapter_info); | ||
859 | req->buffer = addr = dma_map_single(hostdata->dev, | ||
860 | &hostdata->madapter_info, | ||
861 | sizeof(hostdata->madapter_info), | ||
862 | DMA_BIDIRECTIONAL); | ||
863 | 838 | ||
864 | if (dma_mapping_error(hostdata->dev, req->buffer)) { | 839 | dma_unmap_single(hostdata->dev, hostdata->adapter_info_addr, |
865 | if (!firmware_has_feature(FW_FEATURE_CMO)) | 840 | sizeof(hostdata->madapter_info), DMA_BIDIRECTIONAL); |
866 | dev_err(hostdata->dev, | 841 | } |
867 | "Unable to map request_buffer for " | ||
868 | "adapter_info!\n"); | ||
869 | free_event_struct(&hostdata->pool, evt_struct); | ||
870 | return; | ||
871 | } | ||
872 | |||
873 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
874 | if (ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2)) { | ||
875 | dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n"); | ||
876 | dma_unmap_single(hostdata->dev, | ||
877 | addr, | ||
878 | sizeof(hostdata->madapter_info), | ||
879 | DMA_BIDIRECTIONAL); | ||
880 | } | ||
881 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
882 | }; | ||
883 | 842 | ||
884 | /** | 843 | /** |
885 | * login_rsp: - Handle response to SRP login request | 844 | * login_rsp: - Handle response to SRP login request |
@@ -909,9 +868,7 @@ static void login_rsp(struct srp_event_struct *evt_struct) | |||
909 | } | 868 | } |
910 | 869 | ||
911 | dev_info(hostdata->dev, "SRP_LOGIN succeeded\n"); | 870 | dev_info(hostdata->dev, "SRP_LOGIN succeeded\n"); |
912 | 871 | hostdata->client_migrated = 0; | |
913 | if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0) | ||
914 | dev_err(hostdata->dev, "Invalid request_limit.\n"); | ||
915 | 872 | ||
916 | /* Now we know what the real request-limit is. | 873 | /* Now we know what the real request-limit is. |
917 | * This value is set rather than added to request_limit because | 874 | * This value is set rather than added to request_limit because |
@@ -922,15 +879,12 @@ static void login_rsp(struct srp_event_struct *evt_struct) | |||
922 | 879 | ||
923 | /* If we had any pending I/Os, kick them */ | 880 | /* If we had any pending I/Os, kick them */ |
924 | scsi_unblock_requests(hostdata->host); | 881 | scsi_unblock_requests(hostdata->host); |
925 | |||
926 | send_mad_adapter_info(hostdata); | ||
927 | return; | ||
928 | } | 882 | } |
929 | 883 | ||
930 | /** | 884 | /** |
931 | * send_srp_login: - Sends the srp login | 885 | * send_srp_login: - Sends the srp login |
932 | * @hostdata: ibmvscsi_host_data of host | 886 | * @hostdata: ibmvscsi_host_data of host |
933 | * | 887 | * |
934 | * Returns zero if successful. | 888 | * Returns zero if successful. |
935 | */ | 889 | */ |
936 | static int send_srp_login(struct ibmvscsi_host_data *hostdata) | 890 | static int send_srp_login(struct ibmvscsi_host_data *hostdata) |
@@ -939,22 +893,17 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata) | |||
939 | unsigned long flags; | 893 | unsigned long flags; |
940 | struct srp_login_req *login; | 894 | struct srp_login_req *login; |
941 | struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool); | 895 | struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool); |
942 | if (!evt_struct) { | ||
943 | dev_err(hostdata->dev, "couldn't allocate an event for login req!\n"); | ||
944 | return FAILED; | ||
945 | } | ||
946 | 896 | ||
947 | init_event_struct(evt_struct, | 897 | BUG_ON(!evt_struct); |
948 | login_rsp, | 898 | init_event_struct(evt_struct, login_rsp, |
949 | VIOSRP_SRP_FORMAT, | 899 | VIOSRP_SRP_FORMAT, login_timeout); |
950 | init_timeout); | ||
951 | 900 | ||
952 | login = &evt_struct->iu.srp.login_req; | 901 | login = &evt_struct->iu.srp.login_req; |
953 | memset(login, 0x00, sizeof(struct srp_login_req)); | 902 | memset(login, 0, sizeof(*login)); |
954 | login->opcode = SRP_LOGIN_REQ; | 903 | login->opcode = SRP_LOGIN_REQ; |
955 | login->req_it_iu_len = sizeof(union srp_iu); | 904 | login->req_it_iu_len = sizeof(union srp_iu); |
956 | login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; | 905 | login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; |
957 | 906 | ||
958 | spin_lock_irqsave(hostdata->host->host_lock, flags); | 907 | spin_lock_irqsave(hostdata->host->host_lock, flags); |
959 | /* Start out with a request limit of 0, since this is negotiated in | 908 | /* Start out with a request limit of 0, since this is negotiated in |
960 | * the login request we are just sending and login requests always | 909 | * the login request we are just sending and login requests always |
@@ -962,13 +911,241 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata) | |||
962 | */ | 911 | */ |
963 | atomic_set(&hostdata->request_limit, 0); | 912 | atomic_set(&hostdata->request_limit, 0); |
964 | 913 | ||
965 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2); | 914 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2); |
966 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | 915 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
967 | dev_info(hostdata->dev, "sent SRP login\n"); | 916 | dev_info(hostdata->dev, "sent SRP login\n"); |
968 | return rc; | 917 | return rc; |
969 | }; | 918 | }; |
970 | 919 | ||
971 | /** | 920 | /** |
921 | * capabilities_rsp: - Handle response to MAD adapter capabilities request | ||
922 | * @evt_struct: srp_event_struct with the response | ||
923 | * | ||
924 | * Used as a "done" callback by when sending adapter_info. | ||
925 | */ | ||
926 | static void capabilities_rsp(struct srp_event_struct *evt_struct) | ||
927 | { | ||
928 | struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; | ||
929 | |||
930 | if (evt_struct->xfer_iu->mad.capabilities.common.status) { | ||
931 | dev_err(hostdata->dev, "error 0x%X getting capabilities info\n", | ||
932 | evt_struct->xfer_iu->mad.capabilities.common.status); | ||
933 | } else { | ||
934 | if (hostdata->caps.migration.common.server_support != SERVER_SUPPORTS_CAP) | ||
935 | dev_info(hostdata->dev, "Partition migration not supported\n"); | ||
936 | |||
937 | if (client_reserve) { | ||
938 | if (hostdata->caps.reserve.common.server_support == | ||
939 | SERVER_SUPPORTS_CAP) | ||
940 | dev_info(hostdata->dev, "Client reserve enabled\n"); | ||
941 | else | ||
942 | dev_info(hostdata->dev, "Client reserve not supported\n"); | ||
943 | } | ||
944 | } | ||
945 | |||
946 | send_srp_login(hostdata); | ||
947 | } | ||
948 | |||
949 | /** | ||
950 | * send_mad_capabilities: - Sends the mad capabilities request | ||
951 | * and stores the result so it can be retrieved with | ||
952 | * @hostdata: ibmvscsi_host_data of host | ||
953 | */ | ||
954 | static void send_mad_capabilities(struct ibmvscsi_host_data *hostdata) | ||
955 | { | ||
956 | struct viosrp_capabilities *req; | ||
957 | struct srp_event_struct *evt_struct; | ||
958 | unsigned long flags; | ||
959 | struct device_node *of_node = hostdata->dev->archdata.of_node; | ||
960 | const char *location; | ||
961 | |||
962 | evt_struct = get_event_struct(&hostdata->pool); | ||
963 | BUG_ON(!evt_struct); | ||
964 | |||
965 | init_event_struct(evt_struct, capabilities_rsp, | ||
966 | VIOSRP_MAD_FORMAT, info_timeout); | ||
967 | |||
968 | req = &evt_struct->iu.mad.capabilities; | ||
969 | memset(req, 0, sizeof(*req)); | ||
970 | |||
971 | hostdata->caps.flags = CAP_LIST_SUPPORTED; | ||
972 | if (hostdata->client_migrated) | ||
973 | hostdata->caps.flags |= CLIENT_MIGRATED; | ||
974 | |||
975 | strncpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), | ||
976 | sizeof(hostdata->caps.name)); | ||
977 | hostdata->caps.name[sizeof(hostdata->caps.name) - 1] = '\0'; | ||
978 | |||
979 | location = of_get_property(of_node, "ibm,loc-code", NULL); | ||
980 | location = location ? location : dev_name(hostdata->dev); | ||
981 | strncpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); | ||
982 | hostdata->caps.loc[sizeof(hostdata->caps.loc) - 1] = '\0'; | ||
983 | |||
984 | req->common.type = VIOSRP_CAPABILITIES_TYPE; | ||
985 | req->buffer = hostdata->caps_addr; | ||
986 | |||
987 | hostdata->caps.migration.common.cap_type = MIGRATION_CAPABILITIES; | ||
988 | hostdata->caps.migration.common.length = sizeof(hostdata->caps.migration); | ||
989 | hostdata->caps.migration.common.server_support = SERVER_SUPPORTS_CAP; | ||
990 | hostdata->caps.migration.ecl = 1; | ||
991 | |||
992 | if (client_reserve) { | ||
993 | hostdata->caps.reserve.common.cap_type = RESERVATION_CAPABILITIES; | ||
994 | hostdata->caps.reserve.common.length = sizeof(hostdata->caps.reserve); | ||
995 | hostdata->caps.reserve.common.server_support = SERVER_SUPPORTS_CAP; | ||
996 | hostdata->caps.reserve.type = CLIENT_RESERVE_SCSI_2; | ||
997 | req->common.length = sizeof(hostdata->caps); | ||
998 | } else | ||
999 | req->common.length = sizeof(hostdata->caps) - sizeof(hostdata->caps.reserve); | ||
1000 | |||
1001 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
1002 | if (ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2)) | ||
1003 | dev_err(hostdata->dev, "couldn't send CAPABILITIES_REQ!\n"); | ||
1004 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1005 | }; | ||
1006 | |||
1007 | /** | ||
1008 | * fast_fail_rsp: - Handle response to MAD enable fast fail | ||
1009 | * @evt_struct: srp_event_struct with the response | ||
1010 | * | ||
1011 | * Used as a "done" callback by when sending enable fast fail. Gets called | ||
1012 | * by ibmvscsi_handle_crq() | ||
1013 | */ | ||
1014 | static void fast_fail_rsp(struct srp_event_struct *evt_struct) | ||
1015 | { | ||
1016 | struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; | ||
1017 | u8 status = evt_struct->xfer_iu->mad.fast_fail.common.status; | ||
1018 | |||
1019 | if (status == VIOSRP_MAD_NOT_SUPPORTED) | ||
1020 | dev_err(hostdata->dev, "fast_fail not supported in server\n"); | ||
1021 | else if (status == VIOSRP_MAD_FAILED) | ||
1022 | dev_err(hostdata->dev, "fast_fail request failed\n"); | ||
1023 | else if (status != VIOSRP_MAD_SUCCESS) | ||
1024 | dev_err(hostdata->dev, "error 0x%X enabling fast_fail\n", status); | ||
1025 | |||
1026 | send_mad_capabilities(hostdata); | ||
1027 | } | ||
1028 | |||
1029 | /** | ||
1030 | * init_host - Start host initialization | ||
1031 | * @hostdata: ibmvscsi_host_data of host | ||
1032 | * | ||
1033 | * Returns zero if successful. | ||
1034 | */ | ||
1035 | static int enable_fast_fail(struct ibmvscsi_host_data *hostdata) | ||
1036 | { | ||
1037 | int rc; | ||
1038 | unsigned long flags; | ||
1039 | struct viosrp_fast_fail *fast_fail_mad; | ||
1040 | struct srp_event_struct *evt_struct; | ||
1041 | |||
1042 | if (!fast_fail) { | ||
1043 | send_mad_capabilities(hostdata); | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | evt_struct = get_event_struct(&hostdata->pool); | ||
1048 | BUG_ON(!evt_struct); | ||
1049 | |||
1050 | init_event_struct(evt_struct, fast_fail_rsp, VIOSRP_MAD_FORMAT, info_timeout); | ||
1051 | |||
1052 | fast_fail_mad = &evt_struct->iu.mad.fast_fail; | ||
1053 | memset(fast_fail_mad, 0, sizeof(*fast_fail_mad)); | ||
1054 | fast_fail_mad->common.type = VIOSRP_ENABLE_FAST_FAIL; | ||
1055 | fast_fail_mad->common.length = sizeof(*fast_fail_mad); | ||
1056 | |||
1057 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
1058 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2); | ||
1059 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1060 | return rc; | ||
1061 | } | ||
1062 | |||
1063 | /** | ||
1064 | * adapter_info_rsp: - Handle response to MAD adapter info request | ||
1065 | * @evt_struct: srp_event_struct with the response | ||
1066 | * | ||
1067 | * Used as a "done" callback by when sending adapter_info. Gets called | ||
1068 | * by ibmvscsi_handle_crq() | ||
1069 | */ | ||
1070 | static void adapter_info_rsp(struct srp_event_struct *evt_struct) | ||
1071 | { | ||
1072 | struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; | ||
1073 | |||
1074 | if (evt_struct->xfer_iu->mad.adapter_info.common.status) { | ||
1075 | dev_err(hostdata->dev, "error %d getting adapter info\n", | ||
1076 | evt_struct->xfer_iu->mad.adapter_info.common.status); | ||
1077 | } else { | ||
1078 | dev_info(hostdata->dev, "host srp version: %s, " | ||
1079 | "host partition %s (%d), OS %d, max io %u\n", | ||
1080 | hostdata->madapter_info.srp_version, | ||
1081 | hostdata->madapter_info.partition_name, | ||
1082 | hostdata->madapter_info.partition_number, | ||
1083 | hostdata->madapter_info.os_type, | ||
1084 | hostdata->madapter_info.port_max_txu[0]); | ||
1085 | |||
1086 | if (hostdata->madapter_info.port_max_txu[0]) | ||
1087 | hostdata->host->max_sectors = | ||
1088 | hostdata->madapter_info.port_max_txu[0] >> 9; | ||
1089 | |||
1090 | if (hostdata->madapter_info.os_type == 3 && | ||
1091 | strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { | ||
1092 | dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n", | ||
1093 | hostdata->madapter_info.srp_version); | ||
1094 | dev_err(hostdata->dev, "limiting scatterlists to %d\n", | ||
1095 | MAX_INDIRECT_BUFS); | ||
1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | enable_fast_fail(hostdata); | ||
1101 | } | ||
1102 | |||
1103 | /** | ||
1104 | * send_mad_adapter_info: - Sends the mad adapter info request | ||
1105 | * and stores the result so it can be retrieved with | ||
1106 | * sysfs. We COULD consider causing a failure if the | ||
1107 | * returned SRP version doesn't match ours. | ||
1108 | * @hostdata: ibmvscsi_host_data of host | ||
1109 | * | ||
1110 | * Returns zero if successful. | ||
1111 | */ | ||
1112 | static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) | ||
1113 | { | ||
1114 | struct viosrp_adapter_info *req; | ||
1115 | struct srp_event_struct *evt_struct; | ||
1116 | unsigned long flags; | ||
1117 | |||
1118 | evt_struct = get_event_struct(&hostdata->pool); | ||
1119 | BUG_ON(!evt_struct); | ||
1120 | |||
1121 | init_event_struct(evt_struct, | ||
1122 | adapter_info_rsp, | ||
1123 | VIOSRP_MAD_FORMAT, | ||
1124 | info_timeout); | ||
1125 | |||
1126 | req = &evt_struct->iu.mad.adapter_info; | ||
1127 | memset(req, 0x00, sizeof(*req)); | ||
1128 | |||
1129 | req->common.type = VIOSRP_ADAPTER_INFO_TYPE; | ||
1130 | req->common.length = sizeof(hostdata->madapter_info); | ||
1131 | req->buffer = hostdata->adapter_info_addr; | ||
1132 | |||
1133 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
1134 | if (ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2)) | ||
1135 | dev_err(hostdata->dev, "couldn't send ADAPTER_INFO_REQ!\n"); | ||
1136 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1137 | }; | ||
1138 | |||
1139 | /** | ||
1140 | * init_adapter: Start virtual adapter initialization sequence | ||
1141 | * | ||
1142 | */ | ||
1143 | static void init_adapter(struct ibmvscsi_host_data *hostdata) | ||
1144 | { | ||
1145 | send_mad_adapter_info(hostdata); | ||
1146 | } | ||
1147 | |||
1148 | /** | ||
972 | * sync_completion: Signal that a synchronous command has completed | 1149 | * sync_completion: Signal that a synchronous command has completed |
973 | * Note that after returning from this call, the evt_struct is freed. | 1150 | * Note that after returning from this call, the evt_struct is freed. |
974 | * the caller waiting on this completion shouldn't touch the evt_struct | 1151 | * the caller waiting on this completion shouldn't touch the evt_struct |
@@ -1029,7 +1206,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
1029 | init_event_struct(evt, | 1206 | init_event_struct(evt, |
1030 | sync_completion, | 1207 | sync_completion, |
1031 | VIOSRP_SRP_FORMAT, | 1208 | VIOSRP_SRP_FORMAT, |
1032 | init_timeout); | 1209 | abort_timeout); |
1033 | 1210 | ||
1034 | tsk_mgmt = &evt->iu.srp.tsk_mgmt; | 1211 | tsk_mgmt = &evt->iu.srp.tsk_mgmt; |
1035 | 1212 | ||
@@ -1043,7 +1220,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
1043 | evt->sync_srp = &srp_rsp; | 1220 | evt->sync_srp = &srp_rsp; |
1044 | 1221 | ||
1045 | init_completion(&evt->comp); | 1222 | init_completion(&evt->comp); |
1046 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2); | 1223 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, abort_timeout * 2); |
1047 | 1224 | ||
1048 | if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) | 1225 | if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) |
1049 | break; | 1226 | break; |
@@ -1152,7 +1329,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1152 | init_event_struct(evt, | 1329 | init_event_struct(evt, |
1153 | sync_completion, | 1330 | sync_completion, |
1154 | VIOSRP_SRP_FORMAT, | 1331 | VIOSRP_SRP_FORMAT, |
1155 | init_timeout); | 1332 | reset_timeout); |
1156 | 1333 | ||
1157 | tsk_mgmt = &evt->iu.srp.tsk_mgmt; | 1334 | tsk_mgmt = &evt->iu.srp.tsk_mgmt; |
1158 | 1335 | ||
@@ -1165,7 +1342,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1165 | evt->sync_srp = &srp_rsp; | 1342 | evt->sync_srp = &srp_rsp; |
1166 | 1343 | ||
1167 | init_completion(&evt->comp); | 1344 | init_completion(&evt->comp); |
1168 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2); | 1345 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, reset_timeout * 2); |
1169 | 1346 | ||
1170 | if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) | 1347 | if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY) |
1171 | break; | 1348 | break; |
@@ -1281,7 +1458,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1281 | if ((rc = ibmvscsi_ops->send_crq(hostdata, | 1458 | if ((rc = ibmvscsi_ops->send_crq(hostdata, |
1282 | 0xC002000000000000LL, 0)) == 0) { | 1459 | 0xC002000000000000LL, 0)) == 0) { |
1283 | /* Now login */ | 1460 | /* Now login */ |
1284 | send_srp_login(hostdata); | 1461 | init_adapter(hostdata); |
1285 | } else { | 1462 | } else { |
1286 | dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc); | 1463 | dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc); |
1287 | } | 1464 | } |
@@ -1291,7 +1468,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1291 | dev_info(hostdata->dev, "partner initialization complete\n"); | 1468 | dev_info(hostdata->dev, "partner initialization complete\n"); |
1292 | 1469 | ||
1293 | /* Now login */ | 1470 | /* Now login */ |
1294 | send_srp_login(hostdata); | 1471 | init_adapter(hostdata); |
1295 | break; | 1472 | break; |
1296 | default: | 1473 | default: |
1297 | dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format); | 1474 | dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format); |
@@ -1303,6 +1480,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1303 | if (crq->format == 0x06) { | 1480 | if (crq->format == 0x06) { |
1304 | /* We need to re-setup the interpartition connection */ | 1481 | /* We need to re-setup the interpartition connection */ |
1305 | dev_info(hostdata->dev, "Re-enabling adapter!\n"); | 1482 | dev_info(hostdata->dev, "Re-enabling adapter!\n"); |
1483 | hostdata->client_migrated = 1; | ||
1306 | purge_requests(hostdata, DID_REQUEUE); | 1484 | purge_requests(hostdata, DID_REQUEUE); |
1307 | if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, | 1485 | if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, |
1308 | hostdata)) || | 1486 | hostdata)) || |
@@ -1397,7 +1575,7 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, | |||
1397 | init_event_struct(evt_struct, | 1575 | init_event_struct(evt_struct, |
1398 | sync_completion, | 1576 | sync_completion, |
1399 | VIOSRP_MAD_FORMAT, | 1577 | VIOSRP_MAD_FORMAT, |
1400 | init_timeout); | 1578 | info_timeout); |
1401 | 1579 | ||
1402 | host_config = &evt_struct->iu.mad.host_config; | 1580 | host_config = &evt_struct->iu.mad.host_config; |
1403 | 1581 | ||
@@ -1419,7 +1597,7 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, | |||
1419 | 1597 | ||
1420 | init_completion(&evt_struct->comp); | 1598 | init_completion(&evt_struct->comp); |
1421 | spin_lock_irqsave(hostdata->host->host_lock, flags); | 1599 | spin_lock_irqsave(hostdata->host->host_lock, flags); |
1422 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, init_timeout * 2); | 1600 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2); |
1423 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | 1601 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
1424 | if (rc == 0) | 1602 | if (rc == 0) |
1425 | wait_for_completion(&evt_struct->comp); | 1603 | wait_for_completion(&evt_struct->comp); |
@@ -1444,7 +1622,7 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev) | |||
1444 | spin_lock_irqsave(shost->host_lock, lock_flags); | 1622 | spin_lock_irqsave(shost->host_lock, lock_flags); |
1445 | if (sdev->type == TYPE_DISK) { | 1623 | if (sdev->type == TYPE_DISK) { |
1446 | sdev->allow_restart = 1; | 1624 | sdev->allow_restart = 1; |
1447 | blk_queue_rq_timeout(sdev->request_queue, 60 * HZ); | 1625 | blk_queue_rq_timeout(sdev->request_queue, 120 * HZ); |
1448 | } | 1626 | } |
1449 | scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun); | 1627 | scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun); |
1450 | spin_unlock_irqrestore(shost->host_lock, lock_flags); | 1628 | spin_unlock_irqrestore(shost->host_lock, lock_flags); |
@@ -1471,6 +1649,46 @@ static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
1471 | /* ------------------------------------------------------------ | 1649 | /* ------------------------------------------------------------ |
1472 | * sysfs attributes | 1650 | * sysfs attributes |
1473 | */ | 1651 | */ |
1652 | static ssize_t show_host_vhost_loc(struct device *dev, | ||
1653 | struct device_attribute *attr, char *buf) | ||
1654 | { | ||
1655 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1656 | struct ibmvscsi_host_data *hostdata = shost_priv(shost); | ||
1657 | int len; | ||
1658 | |||
1659 | len = snprintf(buf, sizeof(hostdata->caps.loc), "%s\n", | ||
1660 | hostdata->caps.loc); | ||
1661 | return len; | ||
1662 | } | ||
1663 | |||
1664 | static struct device_attribute ibmvscsi_host_vhost_loc = { | ||
1665 | .attr = { | ||
1666 | .name = "vhost_loc", | ||
1667 | .mode = S_IRUGO, | ||
1668 | }, | ||
1669 | .show = show_host_vhost_loc, | ||
1670 | }; | ||
1671 | |||
1672 | static ssize_t show_host_vhost_name(struct device *dev, | ||
1673 | struct device_attribute *attr, char *buf) | ||
1674 | { | ||
1675 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1676 | struct ibmvscsi_host_data *hostdata = shost_priv(shost); | ||
1677 | int len; | ||
1678 | |||
1679 | len = snprintf(buf, sizeof(hostdata->caps.name), "%s\n", | ||
1680 | hostdata->caps.name); | ||
1681 | return len; | ||
1682 | } | ||
1683 | |||
1684 | static struct device_attribute ibmvscsi_host_vhost_name = { | ||
1685 | .attr = { | ||
1686 | .name = "vhost_name", | ||
1687 | .mode = S_IRUGO, | ||
1688 | }, | ||
1689 | .show = show_host_vhost_name, | ||
1690 | }; | ||
1691 | |||
1474 | static ssize_t show_host_srp_version(struct device *dev, | 1692 | static ssize_t show_host_srp_version(struct device *dev, |
1475 | struct device_attribute *attr, char *buf) | 1693 | struct device_attribute *attr, char *buf) |
1476 | { | 1694 | { |
@@ -1594,6 +1812,8 @@ static struct device_attribute ibmvscsi_host_config = { | |||
1594 | }; | 1812 | }; |
1595 | 1813 | ||
1596 | static struct device_attribute *ibmvscsi_attrs[] = { | 1814 | static struct device_attribute *ibmvscsi_attrs[] = { |
1815 | &ibmvscsi_host_vhost_loc, | ||
1816 | &ibmvscsi_host_vhost_name, | ||
1597 | &ibmvscsi_host_srp_version, | 1817 | &ibmvscsi_host_srp_version, |
1598 | &ibmvscsi_host_partition_name, | 1818 | &ibmvscsi_host_partition_name, |
1599 | &ibmvscsi_host_partition_number, | 1819 | &ibmvscsi_host_partition_number, |
@@ -1674,6 +1894,11 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1674 | atomic_set(&hostdata->request_limit, -1); | 1894 | atomic_set(&hostdata->request_limit, -1); |
1675 | hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT; | 1895 | hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT; |
1676 | 1896 | ||
1897 | if (map_persist_bufs(hostdata)) { | ||
1898 | dev_err(&vdev->dev, "couldn't map persistent buffers\n"); | ||
1899 | goto persist_bufs_failed; | ||
1900 | } | ||
1901 | |||
1677 | rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events); | 1902 | rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events); |
1678 | if (rc != 0 && rc != H_RESOURCE) { | 1903 | if (rc != 0 && rc != H_RESOURCE) { |
1679 | dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); | 1904 | dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); |
@@ -1687,6 +1912,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1687 | host->max_lun = 8; | 1912 | host->max_lun = 8; |
1688 | host->max_id = max_id; | 1913 | host->max_id = max_id; |
1689 | host->max_channel = max_channel; | 1914 | host->max_channel = max_channel; |
1915 | host->max_cmd_len = 16; | ||
1690 | 1916 | ||
1691 | if (scsi_add_host(hostdata->host, hostdata->dev)) | 1917 | if (scsi_add_host(hostdata->host, hostdata->dev)) |
1692 | goto add_host_failed; | 1918 | goto add_host_failed; |
@@ -1733,6 +1959,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1733 | init_pool_failed: | 1959 | init_pool_failed: |
1734 | ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events); | 1960 | ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events); |
1735 | init_crq_failed: | 1961 | init_crq_failed: |
1962 | unmap_persist_bufs(hostdata); | ||
1963 | persist_bufs_failed: | ||
1736 | scsi_host_put(host); | 1964 | scsi_host_put(host); |
1737 | scsi_host_alloc_failed: | 1965 | scsi_host_alloc_failed: |
1738 | return -1; | 1966 | return -1; |
@@ -1741,6 +1969,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1741 | static int ibmvscsi_remove(struct vio_dev *vdev) | 1969 | static int ibmvscsi_remove(struct vio_dev *vdev) |
1742 | { | 1970 | { |
1743 | struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data; | 1971 | struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data; |
1972 | unmap_persist_bufs(hostdata); | ||
1744 | release_event_pool(&hostdata->pool, hostdata); | 1973 | release_event_pool(&hostdata->pool, hostdata); |
1745 | ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, | 1974 | ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, |
1746 | max_events); | 1975 | max_events); |