diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 112 |
1 files changed, 38 insertions, 74 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 1bb55086db9f..7cafa34e4c7f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -39,11 +39,10 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, | |||
39 | 39 | ||
40 | static struct device_attribute *zfcp_sysfs_sdev_attrs[]; | 40 | static struct device_attribute *zfcp_sysfs_sdev_attrs[]; |
41 | 41 | ||
42 | struct scsi_transport_template *zfcp_transport_template; | ||
43 | |||
44 | struct zfcp_data zfcp_data = { | 42 | struct zfcp_data zfcp_data = { |
45 | .scsi_host_template = { | 43 | .scsi_host_template = { |
46 | .name = ZFCP_NAME, | 44 | .name = ZFCP_NAME, |
45 | .module = THIS_MODULE, | ||
47 | .proc_name = "zfcp", | 46 | .proc_name = "zfcp", |
48 | .slave_alloc = zfcp_scsi_slave_alloc, | 47 | .slave_alloc = zfcp_scsi_slave_alloc, |
49 | .slave_configure = zfcp_scsi_slave_configure, | 48 | .slave_configure = zfcp_scsi_slave_configure, |
@@ -232,7 +231,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) | |||
232 | */ | 231 | */ |
233 | int | 232 | int |
234 | zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, | 233 | zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, |
235 | struct scsi_cmnd *scpnt, struct timer_list *timer) | 234 | struct scsi_cmnd *scpnt, int use_timer) |
236 | { | 235 | { |
237 | int tmp; | 236 | int tmp; |
238 | int retval; | 237 | int retval; |
@@ -268,7 +267,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, | |||
268 | goto out; | 267 | goto out; |
269 | } | 268 | } |
270 | 269 | ||
271 | tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer, | 270 | tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer, |
272 | ZFCP_REQ_AUTO_CLEANUP); | 271 | ZFCP_REQ_AUTO_CLEANUP); |
273 | 272 | ||
274 | if (unlikely(tmp < 0)) { | 273 | if (unlikely(tmp < 0)) { |
@@ -292,21 +291,22 @@ zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) | |||
292 | * zfcp_scsi_command_sync - send a SCSI command and wait for completion | 291 | * zfcp_scsi_command_sync - send a SCSI command and wait for completion |
293 | * @unit: unit where command is sent to | 292 | * @unit: unit where command is sent to |
294 | * @scpnt: scsi command to be sent | 293 | * @scpnt: scsi command to be sent |
295 | * @timer: timer to be started if request is successfully initiated | 294 | * @use_timer: indicates whether timer should be setup or not |
296 | * Return: 0 | 295 | * Return: 0 |
297 | * | 296 | * |
298 | * Errors are indicated in scpnt->result | 297 | * Errors are indicated in scpnt->result |
299 | */ | 298 | */ |
300 | int | 299 | int |
301 | zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt, | 300 | zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt, |
302 | struct timer_list *timer) | 301 | int use_timer) |
303 | { | 302 | { |
304 | int ret; | 303 | int ret; |
305 | DECLARE_COMPLETION(wait); | 304 | DECLARE_COMPLETION(wait); |
306 | 305 | ||
307 | scpnt->SCp.ptr = (void *) &wait; /* silent re-use */ | 306 | scpnt->SCp.ptr = (void *) &wait; /* silent re-use */ |
308 | scpnt->scsi_done = zfcp_scsi_command_sync_handler; | 307 | scpnt->scsi_done = zfcp_scsi_command_sync_handler; |
309 | ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer); | 308 | ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, |
309 | use_timer); | ||
310 | if (ret == 0) | 310 | if (ret == 0) |
311 | wait_for_completion(&wait); | 311 | wait_for_completion(&wait); |
312 | 312 | ||
@@ -342,7 +342,7 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
342 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | 342 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; |
343 | unit = (struct zfcp_unit *) scpnt->device->hostdata; | 343 | unit = (struct zfcp_unit *) scpnt->device->hostdata; |
344 | 344 | ||
345 | return zfcp_scsi_command_async(adapter, unit, scpnt, NULL); | 345 | return zfcp_scsi_command_async(adapter, unit, scpnt, 0); |
346 | } | 346 | } |
347 | 347 | ||
348 | static struct zfcp_unit * | 348 | static struct zfcp_unit * |
@@ -379,16 +379,15 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, | |||
379 | * will handle late commands. (Usually, the normal completion of late | 379 | * will handle late commands. (Usually, the normal completion of late |
380 | * commands is ignored with respect to the running abort operation.) | 380 | * commands is ignored with respect to the running abort operation.) |
381 | */ | 381 | */ |
382 | int | 382 | int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
383 | zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | ||
384 | { | 383 | { |
385 | struct Scsi_Host *scsi_host; | 384 | struct Scsi_Host *scsi_host; |
386 | struct zfcp_adapter *adapter; | 385 | struct zfcp_adapter *adapter; |
387 | struct zfcp_unit *unit; | 386 | struct zfcp_unit *unit; |
388 | int retval = SUCCESS; | 387 | struct zfcp_fsf_req *fsf_req; |
389 | struct zfcp_fsf_req *new_fsf_req = NULL; | ||
390 | struct zfcp_fsf_req *old_fsf_req; | ||
391 | unsigned long flags; | 388 | unsigned long flags; |
389 | unsigned long old_req_id; | ||
390 | int retval = SUCCESS; | ||
392 | 391 | ||
393 | scsi_host = scpnt->device->host; | 392 | scsi_host = scpnt->device->host; |
394 | adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; | 393 | adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; |
@@ -400,55 +399,47 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
400 | /* avoid race condition between late normal completion and abort */ | 399 | /* avoid race condition between late normal completion and abort */ |
401 | write_lock_irqsave(&adapter->abort_lock, flags); | 400 | write_lock_irqsave(&adapter->abort_lock, flags); |
402 | 401 | ||
403 | /* | 402 | /* Check whether corresponding fsf_req is still pending */ |
404 | * Check whether command has just completed and can not be aborted. | 403 | spin_lock(&adapter->req_list_lock); |
405 | * Even if the command has just been completed late, we can access | 404 | fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long) |
406 | * scpnt since the SCSI stack does not release it at least until | 405 | scpnt->host_scribble); |
407 | * this routine returns. (scpnt is parameter passed to this routine | 406 | spin_unlock(&adapter->req_list_lock); |
408 | * and must not disappear during abort even on late completion.) | 407 | if (!fsf_req) { |
409 | */ | ||
410 | old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; | ||
411 | if (!old_fsf_req) { | ||
412 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 408 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
413 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL); | 409 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0); |
414 | retval = SUCCESS; | 410 | retval = SUCCESS; |
415 | goto out; | 411 | goto out; |
416 | } | 412 | } |
417 | old_fsf_req->data = 0; | 413 | fsf_req->data = 0; |
418 | old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; | 414 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; |
415 | old_req_id = fsf_req->req_id; | ||
419 | 416 | ||
420 | /* don't access old_fsf_req after releasing the abort_lock */ | 417 | /* don't access old fsf_req after releasing the abort_lock */ |
421 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 418 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
422 | /* call FSF routine which does the abort */ | 419 | |
423 | new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, | 420 | fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0); |
424 | adapter, unit, 0); | 421 | if (!fsf_req) { |
425 | if (!new_fsf_req) { | ||
426 | ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); | 422 | ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); |
427 | zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, | 423 | zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, |
428 | old_fsf_req); | 424 | old_req_id); |
429 | retval = FAILED; | 425 | retval = FAILED; |
430 | goto out; | 426 | goto out; |
431 | } | 427 | } |
432 | 428 | ||
433 | /* wait for completion of abort */ | 429 | __wait_event(fsf_req->completion_wq, |
434 | __wait_event(new_fsf_req->completion_wq, | 430 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
435 | new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | ||
436 | 431 | ||
437 | /* status should be valid since signals were not permitted */ | 432 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { |
438 | if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { | 433 | zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0); |
439 | zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req, | ||
440 | NULL); | ||
441 | retval = SUCCESS; | 434 | retval = SUCCESS; |
442 | } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { | 435 | } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { |
443 | zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req, | 436 | zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0); |
444 | NULL); | ||
445 | retval = SUCCESS; | 437 | retval = SUCCESS; |
446 | } else { | 438 | } else { |
447 | zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req, | 439 | zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0); |
448 | NULL); | ||
449 | retval = FAILED; | 440 | retval = FAILED; |
450 | } | 441 | } |
451 | zfcp_fsf_req_free(new_fsf_req); | 442 | zfcp_fsf_req_free(fsf_req); |
452 | out: | 443 | out: |
453 | return retval; | 444 | return retval; |
454 | } | 445 | } |
@@ -548,14 +539,11 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, | |||
548 | 539 | ||
549 | /** | 540 | /** |
550 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset | 541 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset |
551 | * | ||
552 | * If ERP is already running it will be stopped. | ||
553 | */ | 542 | */ |
554 | int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | 543 | int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
555 | { | 544 | { |
556 | struct zfcp_unit *unit; | 545 | struct zfcp_unit *unit; |
557 | struct zfcp_adapter *adapter; | 546 | struct zfcp_adapter *adapter; |
558 | unsigned long flags; | ||
559 | 547 | ||
560 | unit = (struct zfcp_unit*) scpnt->device->hostdata; | 548 | unit = (struct zfcp_unit*) scpnt->device->hostdata; |
561 | adapter = unit->port->adapter; | 549 | adapter = unit->port->adapter; |
@@ -563,22 +551,8 @@ int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | |||
563 | ZFCP_LOG_NORMAL("host/bus reset because of problems with " | 551 | ZFCP_LOG_NORMAL("host/bus reset because of problems with " |
564 | "unit 0x%016Lx\n", unit->fcp_lun); | 552 | "unit 0x%016Lx\n", unit->fcp_lun); |
565 | 553 | ||
566 | write_lock_irqsave(&adapter->erp_lock, flags); | 554 | zfcp_erp_adapter_reopen(adapter, 0); |
567 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | 555 | zfcp_erp_wait(adapter); |
568 | &adapter->status)) { | ||
569 | zfcp_erp_modify_adapter_status(adapter, | ||
570 | ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, | ||
571 | ZFCP_CLEAR); | ||
572 | zfcp_erp_action_dismiss_adapter(adapter); | ||
573 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
574 | zfcp_fsf_req_dismiss_all(adapter); | ||
575 | adapter->fsf_req_seq_no = 0; | ||
576 | zfcp_erp_adapter_reopen(adapter, 0); | ||
577 | } else { | ||
578 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
579 | zfcp_erp_adapter_reopen(adapter, 0); | ||
580 | zfcp_erp_wait(adapter); | ||
581 | } | ||
582 | 556 | ||
583 | return SUCCESS; | 557 | return SUCCESS; |
584 | } | 558 | } |
@@ -607,7 +581,7 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
607 | adapter->scsi_host->max_channel = 0; | 581 | adapter->scsi_host->max_channel = 0; |
608 | adapter->scsi_host->unique_id = unique_id++; /* FIXME */ | 582 | adapter->scsi_host->unique_id = unique_id++; /* FIXME */ |
609 | adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; | 583 | adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; |
610 | adapter->scsi_host->transportt = zfcp_transport_template; | 584 | adapter->scsi_host->transportt = zfcp_data.scsi_transport_template; |
611 | 585 | ||
612 | /* | 586 | /* |
613 | * save a pointer to our own adapter data structure within | 587 | * save a pointer to our own adapter data structure within |
@@ -648,16 +622,6 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | |||
648 | return; | 622 | return; |
649 | } | 623 | } |
650 | 624 | ||
651 | |||
652 | void | ||
653 | zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) | ||
654 | { | ||
655 | adapter->scsi_er_timer.function = zfcp_fsf_scsi_er_timeout_handler; | ||
656 | adapter->scsi_er_timer.data = (unsigned long) adapter; | ||
657 | adapter->scsi_er_timer.expires = jiffies + ZFCP_SCSI_ER_TIMEOUT; | ||
658 | add_timer(&adapter->scsi_er_timer); | ||
659 | } | ||
660 | |||
661 | /* | 625 | /* |
662 | * Support functions for FC transport class | 626 | * Support functions for FC transport class |
663 | */ | 627 | */ |