diff options
author | Dave C Boutcher <sleddog@us.ibm.com> | 2005-08-15 17:52:58 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-08-28 12:14:08 -0400 |
commit | be042f240a8528b8f6b741a484cdbbf515698388 (patch) | |
tree | 2015cb8448cdfb0350cfd582c660535e4242fed0 /drivers/scsi/ibmvscsi/ibmvscsi.c | |
parent | 3b2946cc96bfafa90a555c70b2e876cbbd0fae98 (diff) |
[SCSI] ibmvscsi eh locking
With the removal of the spinlocking around eh calls, we need to add a
little more locking back in, otherwise we do some naked list
manipulation.
Signed-off-by: Dave Boutcher <boutcher@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index fe09d145542a..1ae800ae93d7 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -826,11 +826,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
826 | struct srp_event_struct *tmp_evt, *found_evt; | 826 | struct srp_event_struct *tmp_evt, *found_evt; |
827 | union viosrp_iu srp_rsp; | 827 | union viosrp_iu srp_rsp; |
828 | int rsp_rc; | 828 | int rsp_rc; |
829 | unsigned long flags; | ||
829 | u16 lun = lun_from_dev(cmd->device); | 830 | u16 lun = lun_from_dev(cmd->device); |
830 | 831 | ||
831 | /* First, find this command in our sent list so we can figure | 832 | /* First, find this command in our sent list so we can figure |
832 | * out the correct tag | 833 | * out the correct tag |
833 | */ | 834 | */ |
835 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
834 | found_evt = NULL; | 836 | found_evt = NULL; |
835 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | 837 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { |
836 | if (tmp_evt->cmnd == cmd) { | 838 | if (tmp_evt->cmnd == cmd) { |
@@ -839,11 +841,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
839 | } | 841 | } |
840 | } | 842 | } |
841 | 843 | ||
842 | if (!found_evt) | 844 | if (!found_evt) { |
845 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
843 | return FAILED; | 846 | return FAILED; |
847 | } | ||
844 | 848 | ||
845 | evt = get_event_struct(&hostdata->pool); | 849 | evt = get_event_struct(&hostdata->pool); |
846 | if (evt == NULL) { | 850 | if (evt == NULL) { |
851 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
847 | printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n"); | 852 | printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n"); |
848 | return FAILED; | 853 | return FAILED; |
849 | } | 854 | } |
@@ -867,7 +872,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
867 | 872 | ||
868 | evt->sync_srp = &srp_rsp; | 873 | evt->sync_srp = &srp_rsp; |
869 | init_completion(&evt->comp); | 874 | init_completion(&evt->comp); |
870 | if (ibmvscsi_send_srp_event(evt, hostdata) != 0) { | 875 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata); |
876 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
877 | if (rsp_rc != 0) { | ||
871 | printk(KERN_ERR "ibmvscsi: failed to send abort() event\n"); | 878 | printk(KERN_ERR "ibmvscsi: failed to send abort() event\n"); |
872 | return FAILED; | 879 | return FAILED; |
873 | } | 880 | } |
@@ -901,6 +908,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
901 | * The event is no longer in our list. Make sure it didn't | 908 | * The event is no longer in our list. Make sure it didn't |
902 | * complete while we were aborting | 909 | * complete while we were aborting |
903 | */ | 910 | */ |
911 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
904 | found_evt = NULL; | 912 | found_evt = NULL; |
905 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { | 913 | list_for_each_entry(tmp_evt, &hostdata->sent, list) { |
906 | if (tmp_evt->cmnd == cmd) { | 914 | if (tmp_evt->cmnd == cmd) { |
@@ -910,6 +918,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
910 | } | 918 | } |
911 | 919 | ||
912 | if (found_evt == NULL) { | 920 | if (found_evt == NULL) { |
921 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
913 | printk(KERN_INFO | 922 | printk(KERN_INFO |
914 | "ibmvscsi: aborted task tag 0x%lx completed\n", | 923 | "ibmvscsi: aborted task tag 0x%lx completed\n", |
915 | tsk_mgmt->managed_task_tag); | 924 | tsk_mgmt->managed_task_tag); |
@@ -924,6 +933,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) | |||
924 | list_del(&found_evt->list); | 933 | list_del(&found_evt->list); |
925 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev); | 934 | unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev); |
926 | free_event_struct(&found_evt->hostdata->pool, found_evt); | 935 | free_event_struct(&found_evt->hostdata->pool, found_evt); |
936 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
927 | atomic_inc(&hostdata->request_limit); | 937 | atomic_inc(&hostdata->request_limit); |
928 | return SUCCESS; | 938 | return SUCCESS; |
929 | } | 939 | } |
@@ -943,10 +953,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
943 | struct srp_event_struct *tmp_evt, *pos; | 953 | struct srp_event_struct *tmp_evt, *pos; |
944 | union viosrp_iu srp_rsp; | 954 | union viosrp_iu srp_rsp; |
945 | int rsp_rc; | 955 | int rsp_rc; |
956 | unsigned long flags; | ||
946 | u16 lun = lun_from_dev(cmd->device); | 957 | u16 lun = lun_from_dev(cmd->device); |
947 | 958 | ||
959 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
948 | evt = get_event_struct(&hostdata->pool); | 960 | evt = get_event_struct(&hostdata->pool); |
949 | if (evt == NULL) { | 961 | if (evt == NULL) { |
962 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
950 | printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n"); | 963 | printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n"); |
951 | return FAILED; | 964 | return FAILED; |
952 | } | 965 | } |
@@ -969,7 +982,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
969 | 982 | ||
970 | evt->sync_srp = &srp_rsp; | 983 | evt->sync_srp = &srp_rsp; |
971 | init_completion(&evt->comp); | 984 | init_completion(&evt->comp); |
972 | if (ibmvscsi_send_srp_event(evt, hostdata) != 0) { | 985 | rsp_rc = ibmvscsi_send_srp_event(evt, hostdata); |
986 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
987 | if (rsp_rc != 0) { | ||
973 | printk(KERN_ERR "ibmvscsi: failed to send reset event\n"); | 988 | printk(KERN_ERR "ibmvscsi: failed to send reset event\n"); |
974 | return FAILED; | 989 | return FAILED; |
975 | } | 990 | } |
@@ -1002,6 +1017,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1002 | /* We need to find all commands for this LUN that have not yet been | 1017 | /* We need to find all commands for this LUN that have not yet been |
1003 | * responded to, and fail them with DID_RESET | 1018 | * responded to, and fail them with DID_RESET |
1004 | */ | 1019 | */ |
1020 | spin_lock_irqsave(hostdata->host->host_lock, flags); | ||
1005 | list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { | 1021 | list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { |
1006 | if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { | 1022 | if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) { |
1007 | if (tmp_evt->cmnd) | 1023 | if (tmp_evt->cmnd) |
@@ -1017,6 +1033,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
1017 | tmp_evt->done(tmp_evt); | 1033 | tmp_evt->done(tmp_evt); |
1018 | } | 1034 | } |
1019 | } | 1035 | } |
1036 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); | ||
1020 | return SUCCESS; | 1037 | return SUCCESS; |
1021 | } | 1038 | } |
1022 | 1039 | ||