diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2009-06-08 17:19:04 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-08 19:05:18 -0400 |
commit | 3507e13fcba6b97501891a410ec8ef9f1f188620 (patch) | |
tree | 61fe3efb517492be9af6ef3ec3b31d06f62921d0 /drivers/scsi/ibmvscsi/ibmvscsi.c | |
parent | e1a5ce5b88d06344caec0c71b4ee33e7296358dd (diff) |
[SCSI] ibmvscsi: Send adapter info before login
The ibmvscsi driver currently sends the SRP Login before sending the Adapter
Info MAD, which can result in commands getting sent to the virtual adapter
before we are ready for them. This results in a slight window where the target
devices may not behave as expected. Change the order and close the window.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 170 |
1 files changed, 85 insertions, 85 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 6038c0491f8a..2ed46b8efedf 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -785,6 +785,83 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
785 | /* ------------------------------------------------------------ | 785 | /* ------------------------------------------------------------ |
786 | * Routines for driver initialization | 786 | * Routines for driver initialization |
787 | */ | 787 | */ |
788 | |||
789 | /** | ||
790 | * login_rsp: - Handle response to SRP login request | ||
791 | * @evt_struct: srp_event_struct with the response | ||
792 | * | ||
793 | * Used as a "done" callback by when sending srp_login. Gets called | ||
794 | * by ibmvscsi_handle_crq() | ||
795 | */ | ||
796 | static void login_rsp(struct srp_event_struct *evt_struct) | ||
797 | { | ||
798 | struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; | ||
799 | switch (evt_struct->xfer_iu->srp.login_rsp.opcode) { | ||
800 | case SRP_LOGIN_RSP: /* it worked! */ | ||
801 | break; | ||
802 | case SRP_LOGIN_REJ: /* refused! */ | ||
803 | dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n", | ||
804 | evt_struct->xfer_iu->srp.login_rej.reason); | ||
805 | /* Login failed. */ | ||
806 | atomic_set(&hostdata->request_limit, -1); | ||
807 | return; | ||
808 | default: | ||
809 | dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n", | ||
810 | evt_struct->xfer_iu->srp.login_rsp.opcode); | ||
811 | /* Login failed. */ | ||
812 | atomic_set(&hostdata->request_limit, -1); | ||
813 | return; | ||
814 | } | ||
815 | |||
816 | dev_info(hostdata->dev, "SRP_LOGIN succeeded\n"); | ||
817 | |||
818 | /* Now we know what the real request-limit is. | ||
819 | * This value is set rather than added to request_limit because | ||
820 | * request_limit could have been set to -1 by this client. | ||
821 | */ | ||
822 | atomic_set(&hostdata->request_limit, | ||
823 | evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); | ||
824 | |||
825 | /* If we had any pending I/Os, kick them */ | ||
826 | scsi_unblock_requests(hostdata->host); | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * send_srp_login: - Sends the srp login | ||
831 | * @hostdata: ibmvscsi_host_data of host | ||
832 | * | ||
833 | * Returns zero if successful. | ||
834 | */ | ||
835 | static int send_srp_login(struct ibmvscsi_host_data *hostdata) | ||
836 | { | ||
837 | int rc; | ||
838 | unsigned long flags; | ||
839 | struct srp_login_req *login; | ||
840 | struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool); | ||
841 | |||
842 | BUG_ON(!evt_struct); | ||
843 | init_event_struct(evt_struct, login_rsp, | ||
844 | VIOSRP_SRP_FORMAT, login_timeout); | ||
845 | |||
846 | login = &evt_struct->iu.srp.login_req; | ||
847 | memset(login, 0, sizeof(*login)); | ||
848 | login->opcode = SRP_LOGIN_REQ; | ||
849 | login->req_it_iu_len = sizeof(union srp_iu); | ||
850 | login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; | ||
851 | |||
852 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
853 | /* Start out with a request limit of 0, since this is negotiated in | ||
854 | * the login request we are just sending and login requests always | ||
855 | * get sent by the driver regardless of request_limit. | ||
856 | */ | ||
857 | atomic_set(&hostdata->request_limit, 0); | ||
858 | |||
859 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2); | ||
860 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
861 | dev_info(hostdata->dev, "sent SRP login\n"); | ||
862 | return rc; | ||
863 | }; | ||
864 | |||
788 | /** | 865 | /** |
789 | * adapter_info_rsp: - Handle response to MAD adapter info request | 866 | * adapter_info_rsp: - Handle response to MAD adapter info request |
790 | * @evt_struct: srp_event_struct with the response | 867 | * @evt_struct: srp_event_struct with the response |
@@ -825,6 +902,8 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) | |||
825 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | 902 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; |
826 | } | 903 | } |
827 | } | 904 | } |
905 | |||
906 | send_srp_login(hostdata); | ||
828 | } | 907 | } |
829 | 908 | ||
830 | /** | 909 | /** |
@@ -844,11 +923,7 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) | |||
844 | dma_addr_t addr; | 923 | dma_addr_t addr; |
845 | 924 | ||
846 | evt_struct = get_event_struct(&hostdata->pool); | 925 | evt_struct = get_event_struct(&hostdata->pool); |
847 | if (!evt_struct) { | 926 | BUG_ON(!evt_struct); |
848 | dev_err(hostdata->dev, | ||
849 | "couldn't allocate an event for ADAPTER_INFO_REQ!\n"); | ||
850 | return; | ||
851 | } | ||
852 | 927 | ||
853 | init_event_struct(evt_struct, | 928 | init_event_struct(evt_struct, |
854 | adapter_info_rsp, | 929 | adapter_info_rsp, |
@@ -886,90 +961,15 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) | |||
886 | }; | 961 | }; |
887 | 962 | ||
888 | /** | 963 | /** |
889 | * login_rsp: - Handle response to SRP login request | 964 | * init_adapter: Start virtual adapter initialization sequence |
890 | * @evt_struct: srp_event_struct with the response | ||
891 | * | 965 | * |
892 | * Used as a "done" callback by when sending srp_login. Gets called | 966 | */ |
893 | * by ibmvscsi_handle_crq() | 967 | static void init_adapter(struct ibmvscsi_host_data *hostdata) |
894 | */ | ||
895 | static void login_rsp(struct srp_event_struct *evt_struct) | ||
896 | { | 968 | { |
897 | struct ibmvscsi_host_data *hostdata = evt_struct->hostdata; | ||
898 | switch (evt_struct->xfer_iu->srp.login_rsp.opcode) { | ||
899 | case SRP_LOGIN_RSP: /* it worked! */ | ||
900 | break; | ||
901 | case SRP_LOGIN_REJ: /* refused! */ | ||
902 | dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n", | ||
903 | evt_struct->xfer_iu->srp.login_rej.reason); | ||
904 | /* Login failed. */ | ||
905 | atomic_set(&hostdata->request_limit, -1); | ||
906 | return; | ||
907 | default: | ||
908 | dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n", | ||
909 | evt_struct->xfer_iu->srp.login_rsp.opcode); | ||
910 | /* Login failed. */ | ||
911 | atomic_set(&hostdata->request_limit, -1); | ||
912 | return; | ||
913 | } | ||
914 | |||
915 | dev_info(hostdata->dev, "SRP_LOGIN succeeded\n"); | ||
916 | |||
917 | /* Now we know what the real request-limit is. | ||
918 | * This value is set rather than added to request_limit because | ||
919 | * request_limit could have been set to -1 by this client. | ||
920 | */ | ||
921 | atomic_set(&hostdata->request_limit, | ||
922 | evt_struct->xfer_iu->srp.login_rsp.req_lim_delta); | ||
923 | |||
924 | /* If we had any pending I/Os, kick them */ | ||
925 | scsi_unblock_requests(hostdata->host); | ||
926 | |||
927 | send_mad_adapter_info(hostdata); | 969 | send_mad_adapter_info(hostdata); |
928 | return; | ||
929 | } | 970 | } |
930 | 971 | ||
931 | /** | 972 | /** |
932 | * send_srp_login: - Sends the srp login | ||
933 | * @hostdata: ibmvscsi_host_data of host | ||
934 | * | ||
935 | * Returns zero if successful. | ||
936 | */ | ||
937 | static int send_srp_login(struct ibmvscsi_host_data *hostdata) | ||
938 | { | ||
939 | int rc; | ||
940 | unsigned long flags; | ||
941 | struct srp_login_req *login; | ||
942 | struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool); | ||
943 | if (!evt_struct) { | ||
944 | dev_err(hostdata->dev, "couldn't allocate an event for login req!\n"); | ||
945 | return FAILED; | ||
946 | } | ||
947 | |||
948 | init_event_struct(evt_struct, | ||
949 | login_rsp, | ||
950 | VIOSRP_SRP_FORMAT, | ||
951 | login_timeout); | ||
952 | |||
953 | login = &evt_struct->iu.srp.login_req; | ||
954 | memset(login, 0x00, sizeof(struct srp_login_req)); | ||
955 | login->opcode = SRP_LOGIN_REQ; | ||
956 | login->req_it_iu_len = sizeof(union srp_iu); | ||
957 | login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; | ||
958 | |||
959 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
960 | /* Start out with a request limit of 0, since this is negotiated in | ||
961 | * the login request we are just sending and login requests always | ||
962 | * get sent by the driver regardless of request_limit. | ||
963 | */ | ||
964 | atomic_set(&hostdata->request_limit, 0); | ||
965 | |||
966 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2); | ||
967 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
968 | dev_info(hostdata->dev, "sent SRP login\n"); | ||
969 | return rc; | ||
970 | }; | ||
971 | |||
972 | /** | ||
973 | * sync_completion: Signal that a synchronous command has completed | 973 | * sync_completion: Signal that a synchronous command has completed |
974 | * Note that after returning from this call, the evt_struct is freed. | 974 | * Note that after returning from this call, the evt_struct is freed. |
975 | * the caller waiting on this completion shouldn't touch the evt_struct | 975 | * the caller waiting on this completion shouldn't touch the evt_struct |
@@ -1282,7 +1282,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1282 | if ((rc = ibmvscsi_ops->send_crq(hostdata, | 1282 | if ((rc = ibmvscsi_ops->send_crq(hostdata, |
1283 | 0xC002000000000000LL, 0)) == 0) { | 1283 | 0xC002000000000000LL, 0)) == 0) { |
1284 | /* Now login */ | 1284 | /* Now login */ |
1285 | send_srp_login(hostdata); | 1285 | init_adapter(hostdata); |
1286 | } else { | 1286 | } else { |
1287 | dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc); | 1287 | dev_err(hostdata->dev, "Unable to send init rsp. rc=%ld\n", rc); |
1288 | } | 1288 | } |
@@ -1292,7 +1292,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, | |||
1292 | dev_info(hostdata->dev, "partner initialization complete\n"); | 1292 | dev_info(hostdata->dev, "partner initialization complete\n"); |
1293 | 1293 | ||
1294 | /* Now login */ | 1294 | /* Now login */ |
1295 | send_srp_login(hostdata); | 1295 | init_adapter(hostdata); |
1296 | break; | 1296 | break; |
1297 | default: | 1297 | default: |
1298 | dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format); | 1298 | dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format); |