aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_def.h3
-rw-r--r--drivers/s390/scsi/zfcp_ext.h11
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c39
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c124
4 files changed, 78 insertions, 99 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index a0cd4b080175..ff15f11923e9 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -586,9 +586,6 @@ struct zfcp_fsf_req_qtcb {
586 586
587/********************** ZFCP SPECIFIC DEFINES ********************************/ 587/********************** ZFCP SPECIFIC DEFINES ********************************/
588 588
589#define ZFCP_REQ_AUTO_CLEANUP 0x00000002
590#define ZFCP_REQ_NO_QTCB 0x00000008
591
592#define ZFCP_SET 0x00000100 589#define ZFCP_SET 0x00000100
593#define ZFCP_CLEAR 0x00000200 590#define ZFCP_CLEAR 0x00000200
594 591
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index b5adeda93e1d..799ce1db1f56 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -125,16 +125,13 @@ extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
125extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *, 125extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
126 struct zfcp_erp_action *); 126 struct zfcp_erp_action *);
127extern int zfcp_fsf_send_els(struct zfcp_send_els *); 127extern int zfcp_fsf_send_els(struct zfcp_send_els *);
128extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, 128extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
129 struct zfcp_unit *, 129 struct scsi_cmnd *);
130 struct scsi_cmnd *, int, int);
131extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *); 130extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *);
132extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); 131extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
133extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *, 132extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
134 struct zfcp_unit *, u8, int);
135extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long, 133extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
136 struct zfcp_adapter *, 134 struct zfcp_unit *);
137 struct zfcp_unit *, int);
138 135
139/* zfcp_qdio.c */ 136/* zfcp_qdio.c */
140extern int zfcp_qdio_allocate(struct zfcp_adapter *); 137extern int zfcp_qdio_allocate(struct zfcp_adapter *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 1b25158c50f0..cc69db3b71e7 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -12,6 +12,9 @@
12#include <linux/blktrace_api.h> 12#include <linux/blktrace_api.h>
13#include "zfcp_ext.h" 13#include "zfcp_ext.h"
14 14
15#define ZFCP_REQ_AUTO_CLEANUP 0x00000002
16#define ZFCP_REQ_NO_QTCB 0x00000008
17
15static void zfcp_fsf_request_timeout_handler(unsigned long data) 18static void zfcp_fsf_request_timeout_handler(unsigned long data)
16{ 19{
17 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; 20 struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
@@ -913,27 +916,22 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
913/** 916/**
914 * zfcp_fsf_abort_fcp_command - abort running SCSI command 917 * zfcp_fsf_abort_fcp_command - abort running SCSI command
915 * @old_req_id: unsigned long 918 * @old_req_id: unsigned long
916 * @adapter: pointer to struct zfcp_adapter
917 * @unit: pointer to struct zfcp_unit 919 * @unit: pointer to struct zfcp_unit
918 * @req_flags: integer specifying the request flags
919 * Returns: pointer to struct zfcp_fsf_req 920 * Returns: pointer to struct zfcp_fsf_req
920 *
921 * FIXME(design): should be watched by a timeout !!!
922 */ 921 */
923 922
924struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, 923struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
925 struct zfcp_adapter *adapter, 924 struct zfcp_unit *unit)
926 struct zfcp_unit *unit,
927 int req_flags)
928{ 925{
929 struct qdio_buffer_element *sbale; 926 struct qdio_buffer_element *sbale;
930 struct zfcp_fsf_req *req = NULL; 927 struct zfcp_fsf_req *req = NULL;
928 struct zfcp_adapter *adapter = unit->port->adapter;
931 929
932 spin_lock_bh(&adapter->req_q_lock); 930 spin_lock_bh(&adapter->req_q_lock);
933 if (zfcp_fsf_req_sbal_get(adapter)) 931 if (zfcp_fsf_req_sbal_get(adapter))
934 goto out; 932 goto out;
935 req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, 933 req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
936 req_flags, adapter->pool.fsf_req_abort); 934 0, adapter->pool.fsf_req_abort);
937 if (IS_ERR(req)) { 935 if (IS_ERR(req)) {
938 req = NULL; 936 req = NULL;
939 goto out; 937 goto out;
@@ -2309,21 +2307,17 @@ static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
2309 2307
2310/** 2308/**
2311 * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) 2309 * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
2312 * @adapter: adapter where scsi command is issued
2313 * @unit: unit where command is sent to 2310 * @unit: unit where command is sent to
2314 * @scsi_cmnd: scsi command to be sent 2311 * @scsi_cmnd: scsi command to be sent
2315 * @timer: timer to be started when request is initiated
2316 * @req_flags: flags for fsf_request
2317 */ 2312 */
2318int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, 2313int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
2319 struct zfcp_unit *unit, 2314 struct scsi_cmnd *scsi_cmnd)
2320 struct scsi_cmnd *scsi_cmnd,
2321 int use_timer, int req_flags)
2322{ 2315{
2323 struct zfcp_fsf_req *req; 2316 struct zfcp_fsf_req *req;
2324 struct fcp_cmnd_iu *fcp_cmnd_iu; 2317 struct fcp_cmnd_iu *fcp_cmnd_iu;
2325 unsigned int sbtype; 2318 unsigned int sbtype;
2326 int real_bytes, retval = -EIO; 2319 int real_bytes, retval = -EIO;
2320 struct zfcp_adapter *adapter = unit->port->adapter;
2327 2321
2328 if (unlikely(!(atomic_read(&unit->status) & 2322 if (unlikely(!(atomic_read(&unit->status) &
2329 ZFCP_STATUS_COMMON_UNBLOCKED))) 2323 ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -2332,7 +2326,8 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
2332 spin_lock(&adapter->req_q_lock); 2326 spin_lock(&adapter->req_q_lock);
2333 if (!zfcp_fsf_sbal_available(adapter)) 2327 if (!zfcp_fsf_sbal_available(adapter))
2334 goto out; 2328 goto out;
2335 req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 2329 req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND,
2330 ZFCP_REQ_AUTO_CLEANUP,
2336 adapter->pool.fsf_req_scsi); 2331 adapter->pool.fsf_req_scsi);
2337 if (IS_ERR(req)) { 2332 if (IS_ERR(req)) {
2338 retval = PTR_ERR(req); 2333 retval = PTR_ERR(req);
@@ -2414,9 +2409,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
2414 2409
2415 zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes); 2410 zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
2416 2411
2417 if (use_timer)
2418 zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2419
2420 retval = zfcp_fsf_req_send(req); 2412 retval = zfcp_fsf_req_send(req);
2421 if (unlikely(retval)) 2413 if (unlikely(retval))
2422 goto failed_scsi_cmnd; 2414 goto failed_scsi_cmnd;
@@ -2434,19 +2426,16 @@ out:
2434 2426
2435/** 2427/**
2436 * zfcp_fsf_send_fcp_ctm - send SCSI task management command 2428 * zfcp_fsf_send_fcp_ctm - send SCSI task management command
2437 * @adapter: pointer to struct zfcp-adapter
2438 * @unit: pointer to struct zfcp_unit 2429 * @unit: pointer to struct zfcp_unit
2439 * @tm_flags: unsigned byte for task management flags 2430 * @tm_flags: unsigned byte for task management flags
2440 * @req_flags: int request flags
2441 * Returns: on success pointer to struct fsf_req, NULL otherwise 2431 * Returns: on success pointer to struct fsf_req, NULL otherwise
2442 */ 2432 */
2443struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, 2433struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
2444 struct zfcp_unit *unit,
2445 u8 tm_flags, int req_flags)
2446{ 2434{
2447 struct qdio_buffer_element *sbale; 2435 struct qdio_buffer_element *sbale;
2448 struct zfcp_fsf_req *req = NULL; 2436 struct zfcp_fsf_req *req = NULL;
2449 struct fcp_cmnd_iu *fcp_cmnd_iu; 2437 struct fcp_cmnd_iu *fcp_cmnd_iu;
2438 struct zfcp_adapter *adapter = unit->port->adapter;
2450 2439
2451 if (unlikely(!(atomic_read(&unit->status) & 2440 if (unlikely(!(atomic_read(&unit->status) &
2452 ZFCP_STATUS_COMMON_UNBLOCKED))) 2441 ZFCP_STATUS_COMMON_UNBLOCKED)))
@@ -2455,7 +2444,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
2455 spin_lock_bh(&adapter->req_q_lock); 2444 spin_lock_bh(&adapter->req_q_lock);
2456 if (zfcp_fsf_req_sbal_get(adapter)) 2445 if (zfcp_fsf_req_sbal_get(adapter))
2457 goto out; 2446 goto out;
2458 req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, 2447 req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0,
2459 adapter->pool.fsf_req_scsi); 2448 adapter->pool.fsf_req_scsi);
2460 if (IS_ERR(req)) { 2449 if (IS_ERR(req)) {
2461 req = NULL; 2450 req = NULL;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 7829c72d83d0..c17505f767a9 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -87,8 +87,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
87 return 0;; 87 return 0;;
88 } 88 }
89 89
90 ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0, 90 ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
91 ZFCP_REQ_AUTO_CLEANUP);
92 if (unlikely(ret == -EBUSY)) 91 if (unlikely(ret == -EBUSY))
93 return SCSI_MLQUEUE_DEVICE_BUSY; 92 return SCSI_MLQUEUE_DEVICE_BUSY;
94 else if (unlikely(ret < 0)) 93 else if (unlikely(ret < 0))
@@ -145,79 +144,91 @@ out:
145 144
146static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) 145static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
147{ 146{
148 struct Scsi_Host *scsi_host; 147 struct Scsi_Host *scsi_host = scpnt->device->host;
149 struct zfcp_adapter *adapter; 148 struct zfcp_adapter *adapter =
150 struct zfcp_unit *unit; 149 (struct zfcp_adapter *) scsi_host->hostdata[0];
151 struct zfcp_fsf_req *fsf_req; 150 struct zfcp_unit *unit = scpnt->device->hostdata;
151 struct zfcp_fsf_req *old_req, *abrt_req;
152 unsigned long flags; 152 unsigned long flags;
153 unsigned long old_req_id = (unsigned long) scpnt->host_scribble; 153 unsigned long old_req_id = (unsigned long) scpnt->host_scribble;
154 int retval = SUCCESS; 154 int retval = SUCCESS;
155 155 int retry = 3;
156 scsi_host = scpnt->device->host;
157 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
158 unit = scpnt->device->hostdata;
159 156
160 /* avoid race condition between late normal completion and abort */ 157 /* avoid race condition between late normal completion and abort */
161 write_lock_irqsave(&adapter->abort_lock, flags); 158 write_lock_irqsave(&adapter->abort_lock, flags);
162 159
163 /* Check whether corresponding fsf_req is still pending */
164 spin_lock(&adapter->req_list_lock); 160 spin_lock(&adapter->req_list_lock);
165 fsf_req = zfcp_reqlist_find(adapter, old_req_id); 161 old_req = zfcp_reqlist_find(adapter, old_req_id);
166 spin_unlock(&adapter->req_list_lock); 162 spin_unlock(&adapter->req_list_lock);
167 if (!fsf_req) { 163 if (!old_req) {
168 write_unlock_irqrestore(&adapter->abort_lock, flags); 164 write_unlock_irqrestore(&adapter->abort_lock, flags);
169 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0); 165 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
170 return retval; 166 old_req_id);
167 return SUCCESS;
171 } 168 }
172 fsf_req->data = NULL; 169 old_req->data = NULL;
173 170
174 /* don't access old fsf_req after releasing the abort_lock */ 171 /* don't access old fsf_req after releasing the abort_lock */
175 write_unlock_irqrestore(&adapter->abort_lock, flags); 172 write_unlock_irqrestore(&adapter->abort_lock, flags);
176 173
177 fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0); 174 while (retry--) {
178 if (!fsf_req) { 175 abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit);
179 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, 176 if (abrt_req)
180 old_req_id); 177 break;
181 retval = FAILED; 178
182 return retval; 179 zfcp_erp_wait(adapter);
180 if (!(atomic_read(&adapter->status) &
181 ZFCP_STATUS_COMMON_RUNNING)) {
182 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
183 old_req_id);
184 return SUCCESS;
185 }
183 } 186 }
187 if (!abrt_req)
188 return FAILED;
184 189
185 __wait_event(fsf_req->completion_wq, 190 wait_event(abrt_req->completion_wq,
186 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 191 abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
187 192
188 if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { 193 if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
189 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0); 194 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0);
190 } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { 195 else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
191 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0); 196 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0);
192 } else { 197 else {
193 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0); 198 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0);
194 retval = FAILED; 199 retval = FAILED;
195 } 200 }
196 zfcp_fsf_req_free(fsf_req); 201 zfcp_fsf_req_free(abrt_req);
197
198 return retval; 202 return retval;
199} 203}
200 204
201static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags, 205static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
202 struct scsi_cmnd *scpnt)
203{ 206{
207 struct zfcp_unit *unit = scpnt->device->hostdata;
204 struct zfcp_adapter *adapter = unit->port->adapter; 208 struct zfcp_adapter *adapter = unit->port->adapter;
205 struct zfcp_fsf_req *fsf_req; 209 struct zfcp_fsf_req *fsf_req;
206 int retval = SUCCESS; 210 int retval = SUCCESS;
207 211 int retry = 3;
208 /* issue task management function */ 212
209 fsf_req = zfcp_fsf_send_fcp_ctm(adapter, unit, tm_flags, 0); 213 while (retry--) {
210 if (!fsf_req) { 214 fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
211 zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt); 215 if (fsf_req)
212 return FAILED; 216 break;
217
218 zfcp_erp_wait(adapter);
219 if (!(atomic_read(&adapter->status) &
220 ZFCP_STATUS_COMMON_RUNNING)) {
221 zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit,
222 scpnt);
223 return SUCCESS;
224 }
213 } 225 }
226 if (!fsf_req)
227 return FAILED;
214 228
215 __wait_event(fsf_req->completion_wq, 229 wait_event(fsf_req->completion_wq,
216 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 230 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
217 231
218 /*
219 * check completion status of task management function
220 */
221 if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { 232 if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
222 zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); 233 zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
223 retval = FAILED; 234 retval = FAILED;
@@ -228,39 +239,24 @@ static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags,
228 zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt); 239 zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
229 240
230 zfcp_fsf_req_free(fsf_req); 241 zfcp_fsf_req_free(fsf_req);
231
232 return retval; 242 return retval;
233} 243}
234 244
235static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) 245static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
236{ 246{
237 struct zfcp_unit *unit = scpnt->device->hostdata; 247 return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET);
238
239 if (!unit) {
240 WARN_ON(1);
241 return SUCCESS;
242 }
243 return zfcp_task_mgmt_function(unit, FCP_LOGICAL_UNIT_RESET, scpnt);
244} 248}
245 249
246static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) 250static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
247{ 251{
248 struct zfcp_unit *unit = scpnt->device->hostdata; 252 return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET);
249
250 if (!unit) {
251 WARN_ON(1);
252 return SUCCESS;
253 }
254 return zfcp_task_mgmt_function(unit, FCP_TARGET_RESET, scpnt);
255} 253}
256 254
257static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) 255static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
258{ 256{
259 struct zfcp_unit *unit; 257 struct zfcp_unit *unit = scpnt->device->hostdata;
260 struct zfcp_adapter *adapter; 258 struct zfcp_adapter *adapter = unit->port->adapter;
261 259
262 unit = scpnt->device->hostdata;
263 adapter = unit->port->adapter;
264 zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt); 260 zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
265 zfcp_erp_wait(adapter); 261 zfcp_erp_wait(adapter);
266 262