diff options
author | Andreas Herrmann <aherrman@de.ibm.com> | 2005-06-13 07:20:35 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-06-13 22:32:48 -0400 |
commit | 1db2c9c0931a53fe013db55fd2ff58859db31e8d (patch) | |
tree | 1134627ac98d91896dcdb161d5df7ecef60a4de3 /drivers/s390/scsi | |
parent | 64b29a130901d5b8578e9f602cf2dae56aaff224 (diff) |
[SCSI] zfcp: fix bug during adapter shutdown
Fixes a race between zfcp_fsf_req_dismiss_all and
zfcp_qdio_reqid_check. During adapter shutdown it occurred that a
request was cleaned up twice. First during its normal
completion. Second when dismiss_all was called. The fix is to
serialize access to fsf request list between zfcp_fsf_req_dismiss_all
and zfcp_qdio_reqid_check and delete a fsf request from the list if
its completion is triggered. (Additionally a rwlock was replaced by a
spinlock and fsf_req_cleanup was eliminated.)
Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 8 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 79 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 28 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 2 |
7 files changed, 45 insertions, 80 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 6bb4d332b474..c999042dae15 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -520,7 +520,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
520 | 520 | ||
521 | out: | 521 | out: |
522 | if (fsf_req != NULL) | 522 | if (fsf_req != NULL) |
523 | zfcp_fsf_req_cleanup(fsf_req); | 523 | zfcp_fsf_req_free(fsf_req); |
524 | 524 | ||
525 | if ((adapter != NULL) && (retval != -ENXIO)) | 525 | if ((adapter != NULL) && (retval != -ENXIO)) |
526 | zfcp_adapter_put(adapter); | 526 | zfcp_adapter_put(adapter); |
@@ -1149,7 +1149,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
1149 | INIT_LIST_HEAD(&adapter->port_remove_lh); | 1149 | INIT_LIST_HEAD(&adapter->port_remove_lh); |
1150 | 1150 | ||
1151 | /* initialize list of fsf requests */ | 1151 | /* initialize list of fsf requests */ |
1152 | rwlock_init(&adapter->fsf_req_list_lock); | 1152 | spin_lock_init(&adapter->fsf_req_list_lock); |
1153 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); | 1153 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); |
1154 | 1154 | ||
1155 | /* initialize abort lock */ | 1155 | /* initialize abort lock */ |
@@ -1234,9 +1234,9 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
1234 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); | 1234 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); |
1235 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); | 1235 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); |
1236 | /* sanity check: no pending FSF requests */ | 1236 | /* sanity check: no pending FSF requests */ |
1237 | read_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 1237 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); |
1238 | retval = !list_empty(&adapter->fsf_req_list_head); | 1238 | retval = !list_empty(&adapter->fsf_req_list_head); |
1239 | read_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 1239 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); |
1240 | if (retval) { | 1240 | if (retval) { |
1241 | ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " | 1241 | ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " |
1242 | "%i requests outstanding\n", | 1242 | "%i requests outstanding\n", |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 37982058e4d9..bfbbb825f9ab 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -861,7 +861,7 @@ struct zfcp_adapter { | |||
861 | u32 ports; /* number of remote ports */ | 861 | u32 ports; /* number of remote ports */ |
862 | struct timer_list scsi_er_timer; /* SCSI err recovery watch */ | 862 | struct timer_list scsi_er_timer; /* SCSI err recovery watch */ |
863 | struct list_head fsf_req_list_head; /* head of FSF req list */ | 863 | struct list_head fsf_req_list_head; /* head of FSF req list */ |
864 | rwlock_t fsf_req_list_lock; /* lock for ops on list of | 864 | spinlock_t fsf_req_list_lock; /* lock for ops on list of |
865 | FSF requests */ | 865 | FSF requests */ |
866 | atomic_t fsf_reqs_active; /* # active FSF reqs */ | 866 | atomic_t fsf_reqs_active; /* # active FSF reqs */ |
867 | struct zfcp_qdio_queue request_queue; /* request queue */ | 867 | struct zfcp_qdio_queue request_queue; /* request queue */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 41c67e1ec4f7..6d73891eec9e 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -891,7 +891,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
891 | 891 | ||
892 | if (erp_action->fsf_req) { | 892 | if (erp_action->fsf_req) { |
893 | /* take lock to ensure that request is not being deleted meanwhile */ | 893 | /* take lock to ensure that request is not being deleted meanwhile */ |
894 | write_lock(&adapter->fsf_req_list_lock); | 894 | spin_lock(&adapter->fsf_req_list_lock); |
895 | /* check whether fsf req does still exist */ | 895 | /* check whether fsf req does still exist */ |
896 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) | 896 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) |
897 | if (fsf_req == erp_action->fsf_req) | 897 | if (fsf_req == erp_action->fsf_req) |
@@ -934,7 +934,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
934 | */ | 934 | */ |
935 | erp_action->fsf_req = NULL; | 935 | erp_action->fsf_req = NULL; |
936 | } | 936 | } |
937 | write_unlock(&adapter->fsf_req_list_lock); | 937 | spin_unlock(&adapter->fsf_req_list_lock); |
938 | } else | 938 | } else |
939 | debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); | 939 | debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); |
940 | 940 | ||
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index d5fd43352071..8f0da2e02a47 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -116,7 +116,7 @@ extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, | |||
116 | struct timer_list*, int); | 116 | struct timer_list*, int); |
117 | extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *); | 117 | extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *); |
118 | extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *); | 118 | extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *); |
119 | extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *); | 119 | extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); |
120 | extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management( | 120 | extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management( |
121 | struct zfcp_adapter *, struct zfcp_unit *, u8, int); | 121 | struct zfcp_adapter *, struct zfcp_unit *, u8, int); |
122 | extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command( | 122 | extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command( |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 21a6d7633475..56b2ea97da1f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -61,7 +61,6 @@ static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); | |||
61 | static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); | 61 | static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); |
62 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); | 62 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); |
63 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); | 63 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); |
64 | static void zfcp_fsf_req_free(struct zfcp_fsf_req *); | ||
65 | 64 | ||
66 | /* association between FSF command and FSF QTCB type */ | 65 | /* association between FSF command and FSF QTCB type */ |
67 | static u32 fsf_qtcb_type[] = { | 66 | static u32 fsf_qtcb_type[] = { |
@@ -149,13 +148,13 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags) | |||
149 | * | 148 | * |
150 | * locks: none | 149 | * locks: none |
151 | */ | 150 | */ |
152 | static void | 151 | void |
153 | zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) | 152 | zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) |
154 | { | 153 | { |
155 | if (likely(fsf_req->pool != NULL)) | 154 | if (likely(fsf_req->pool != NULL)) |
156 | mempool_free(fsf_req, fsf_req->pool); | 155 | mempool_free(fsf_req, fsf_req->pool); |
157 | else | 156 | else |
158 | kfree(fsf_req); | 157 | kfree(fsf_req); |
159 | } | 158 | } |
160 | 159 | ||
161 | /* | 160 | /* |
@@ -170,30 +169,21 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) | |||
170 | int | 169 | int |
171 | zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) | 170 | zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) |
172 | { | 171 | { |
173 | int retval = 0; | ||
174 | struct zfcp_fsf_req *fsf_req, *tmp; | 172 | struct zfcp_fsf_req *fsf_req, *tmp; |
173 | unsigned long flags; | ||
174 | LIST_HEAD(remove_queue); | ||
175 | 175 | ||
176 | list_for_each_entry_safe(fsf_req, tmp, &adapter->fsf_req_list_head, | 176 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); |
177 | list) | 177 | list_splice_init(&adapter->fsf_req_list_head, &remove_queue); |
178 | zfcp_fsf_req_dismiss(fsf_req); | 178 | atomic_set(&adapter->fsf_reqs_active, 0); |
179 | /* wait_event_timeout? */ | 179 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); |
180 | while (!list_empty(&adapter->fsf_req_list_head)) { | ||
181 | ZFCP_LOG_DEBUG("fsf req list of adapter %s not yet empty\n", | ||
182 | zfcp_get_busid_by_adapter(adapter)); | ||
183 | /* wait for woken intiators to clean up their requests */ | ||
184 | msleep(jiffies_to_msecs(ZFCP_FSFREQ_CLEANUP_TIMEOUT)); | ||
185 | } | ||
186 | 180 | ||
187 | /* consistency check */ | 181 | list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) { |
188 | if (atomic_read(&adapter->fsf_reqs_active)) { | 182 | list_del(&fsf_req->list); |
189 | ZFCP_LOG_NORMAL("bug: There are still %d FSF requests pending " | 183 | zfcp_fsf_req_dismiss(fsf_req); |
190 | "on adapter %s after cleanup.\n", | ||
191 | atomic_read(&adapter->fsf_reqs_active), | ||
192 | zfcp_get_busid_by_adapter(adapter)); | ||
193 | atomic_set(&adapter->fsf_reqs_active, 0); | ||
194 | } | 184 | } |
195 | 185 | ||
196 | return retval; | 186 | return 0; |
197 | } | 187 | } |
198 | 188 | ||
199 | /* | 189 | /* |
@@ -226,10 +216,6 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) | |||
226 | { | 216 | { |
227 | int retval = 0; | 217 | int retval = 0; |
228 | int cleanup; | 218 | int cleanup; |
229 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
230 | |||
231 | /* do some statistics */ | ||
232 | atomic_dec(&adapter->fsf_reqs_active); | ||
233 | 219 | ||
234 | if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { | 220 | if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { |
235 | ZFCP_LOG_DEBUG("Status read response received\n"); | 221 | ZFCP_LOG_DEBUG("Status read response received\n"); |
@@ -260,7 +246,7 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) | |||
260 | * lock must not be held here since it will be | 246 | * lock must not be held here since it will be |
261 | * grabed by the called routine, too | 247 | * grabed by the called routine, too |
262 | */ | 248 | */ |
263 | zfcp_fsf_req_cleanup(fsf_req); | 249 | zfcp_fsf_req_free(fsf_req); |
264 | } else { | 250 | } else { |
265 | /* notify initiator waiting for the requests completion */ | 251 | /* notify initiator waiting for the requests completion */ |
266 | ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req); | 252 | ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req); |
@@ -936,7 +922,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
936 | 922 | ||
937 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { | 923 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { |
938 | mempool_free(status_buffer, adapter->pool.data_status_read); | 924 | mempool_free(status_buffer, adapter->pool.data_status_read); |
939 | zfcp_fsf_req_cleanup(fsf_req); | 925 | zfcp_fsf_req_free(fsf_req); |
940 | goto out; | 926 | goto out; |
941 | } | 927 | } |
942 | 928 | ||
@@ -1033,7 +1019,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
1033 | break; | 1019 | break; |
1034 | } | 1020 | } |
1035 | mempool_free(status_buffer, adapter->pool.data_status_read); | 1021 | mempool_free(status_buffer, adapter->pool.data_status_read); |
1036 | zfcp_fsf_req_cleanup(fsf_req); | 1022 | zfcp_fsf_req_free(fsf_req); |
1037 | /* | 1023 | /* |
1038 | * recycle buffer and start new request repeat until outbound | 1024 | * recycle buffer and start new request repeat until outbound |
1039 | * queue is empty or adapter shutdown is requested | 1025 | * queue is empty or adapter shutdown is requested |
@@ -2258,7 +2244,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2258 | wait_event(fsf_req->completion_wq, | 2244 | wait_event(fsf_req->completion_wq, |
2259 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 2245 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
2260 | del_timer_sync(timer); | 2246 | del_timer_sync(timer); |
2261 | zfcp_fsf_req_cleanup(fsf_req); | 2247 | zfcp_fsf_req_free(fsf_req); |
2262 | out: | 2248 | out: |
2263 | kfree(timer); | 2249 | kfree(timer); |
2264 | return retval; | 2250 | return retval; |
@@ -4607,7 +4593,7 @@ zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req, | |||
4607 | *status = fsf_req->status; | 4593 | *status = fsf_req->status; |
4608 | 4594 | ||
4609 | /* cleanup request */ | 4595 | /* cleanup request */ |
4610 | zfcp_fsf_req_cleanup(fsf_req); | 4596 | zfcp_fsf_req_free(fsf_req); |
4611 | out: | 4597 | out: |
4612 | return retval; | 4598 | return retval; |
4613 | } | 4599 | } |
@@ -4806,9 +4792,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4806 | inc_seq_no = 0; | 4792 | inc_seq_no = 0; |
4807 | 4793 | ||
4808 | /* put allocated FSF request at list tail */ | 4794 | /* put allocated FSF request at list tail */ |
4809 | write_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 4795 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); |
4810 | list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); | 4796 | list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); |
4811 | write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 4797 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); |
4812 | 4798 | ||
4813 | /* figure out expiration time of timeout and start timeout */ | 4799 | /* figure out expiration time of timeout and start timeout */ |
4814 | if (unlikely(timer)) { | 4800 | if (unlikely(timer)) { |
@@ -4852,9 +4838,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4852 | */ | 4838 | */ |
4853 | if (timer) | 4839 | if (timer) |
4854 | del_timer(timer); | 4840 | del_timer(timer); |
4855 | write_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 4841 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); |
4856 | list_del(&fsf_req->list); | 4842 | list_del(&fsf_req->list); |
4857 | write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 4843 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); |
4858 | /* | 4844 | /* |
4859 | * adjust the number of free SBALs in request queue as well as | 4845 | * adjust the number of free SBALs in request queue as well as |
4860 | * position of first one | 4846 | * position of first one |
@@ -4892,25 +4878,4 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4892 | return retval; | 4878 | return retval; |
4893 | } | 4879 | } |
4894 | 4880 | ||
4895 | /* | ||
4896 | * function: zfcp_fsf_req_cleanup | ||
4897 | * | ||
4898 | * purpose: cleans up an FSF request and removes it from the specified list | ||
4899 | * | ||
4900 | * returns: | ||
4901 | * | ||
4902 | * assumption: no pending SB in SBALEs other than QTCB | ||
4903 | */ | ||
4904 | void | ||
4905 | zfcp_fsf_req_cleanup(struct zfcp_fsf_req *fsf_req) | ||
4906 | { | ||
4907 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
4908 | unsigned long flags; | ||
4909 | |||
4910 | write_lock_irqsave(&adapter->fsf_req_list_lock, flags); | ||
4911 | list_del(&fsf_req->list); | ||
4912 | write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | ||
4913 | zfcp_fsf_req_free(fsf_req); | ||
4914 | } | ||
4915 | |||
4916 | #undef ZFCP_LOG_AREA | 4881 | #undef ZFCP_LOG_AREA |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index fb218dd9d934..24e16ec331d9 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -446,37 +446,37 @@ int | |||
446 | zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) | 446 | zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) |
447 | { | 447 | { |
448 | struct zfcp_fsf_req *fsf_req; | 448 | struct zfcp_fsf_req *fsf_req; |
449 | int retval = 0; | ||
450 | 449 | ||
451 | /* invalid (per convention used in this driver) */ | 450 | /* invalid (per convention used in this driver) */ |
452 | if (unlikely(!sbale_addr)) { | 451 | if (unlikely(!sbale_addr)) { |
453 | ZFCP_LOG_NORMAL("bug: invalid reqid\n"); | 452 | ZFCP_LOG_NORMAL("bug: invalid reqid\n"); |
454 | retval = -EINVAL; | 453 | return -EINVAL; |
455 | goto out; | ||
456 | } | 454 | } |
457 | 455 | ||
458 | /* valid request id and thus (hopefully :) valid fsf_req address */ | 456 | /* valid request id and thus (hopefully :) valid fsf_req address */ |
459 | fsf_req = (struct zfcp_fsf_req *) sbale_addr; | 457 | fsf_req = (struct zfcp_fsf_req *) sbale_addr; |
460 | 458 | ||
459 | /* serialize with zfcp_fsf_req_dismiss_all */ | ||
460 | spin_lock(&adapter->fsf_req_list_lock); | ||
461 | if (list_empty(&adapter->fsf_req_list_head)) { | ||
462 | spin_unlock(&adapter->fsf_req_list_lock); | ||
463 | return 0; | ||
464 | } | ||
465 | list_del(&fsf_req->list); | ||
466 | atomic_dec(&adapter->fsf_reqs_active); | ||
467 | spin_unlock(&adapter->fsf_req_list_lock); | ||
468 | |||
461 | if (unlikely(adapter != fsf_req->adapter)) { | 469 | if (unlikely(adapter != fsf_req->adapter)) { |
462 | ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, " | 470 | ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, " |
463 | "fsf_req->adapter=%p, adapter=%p)\n", | 471 | "fsf_req->adapter=%p, adapter=%p)\n", |
464 | fsf_req, fsf_req->adapter, adapter); | 472 | fsf_req, fsf_req->adapter, adapter); |
465 | retval = -EINVAL; | 473 | return -EINVAL; |
466 | goto out; | ||
467 | } | ||
468 | |||
469 | ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb); | ||
470 | if (likely(fsf_req->qtcb)) { | ||
471 | ZFCP_LOG_TRACE("hex dump of QTCB:\n"); | ||
472 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb, | ||
473 | sizeof(struct fsf_qtcb)); | ||
474 | } | 474 | } |
475 | 475 | ||
476 | /* finish the FSF request */ | 476 | /* finish the FSF request */ |
477 | zfcp_fsf_req_complete(fsf_req); | 477 | zfcp_fsf_req_complete(fsf_req); |
478 | out: | 478 | |
479 | return retval; | 479 | return 0; |
480 | } | 480 | } |
481 | 481 | ||
482 | /** | 482 | /** |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e21b547fd427..c6f69fc475a2 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -575,7 +575,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
575 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0]; | 575 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0]; |
576 | dbf_fsf_qual[1] = | 576 | dbf_fsf_qual[1] = |
577 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2]; | 577 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2]; |
578 | zfcp_fsf_req_cleanup(new_fsf_req); | 578 | zfcp_fsf_req_free(new_fsf_req); |
579 | #else | 579 | #else |
580 | retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req, | 580 | retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req, |
581 | ZFCP_UNINTERRUPTIBLE, &status); | 581 | ZFCP_UNINTERRUPTIBLE, &status); |