diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 73 |
1 files changed, 37 insertions, 36 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 671f4a6a5d18..1bb55086db9f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -30,7 +30,6 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *, | |||
30 | void (*done) (struct scsi_cmnd *)); | 30 | void (*done) (struct scsi_cmnd *)); |
31 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); | 31 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); |
32 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); | 32 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); |
33 | static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); | ||
34 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); | 33 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); |
35 | static int zfcp_task_management_function(struct zfcp_unit *, u8, | 34 | static int zfcp_task_management_function(struct zfcp_unit *, u8, |
36 | struct scsi_cmnd *); | 35 | struct scsi_cmnd *); |
@@ -46,30 +45,22 @@ struct zfcp_data zfcp_data = { | |||
46 | .scsi_host_template = { | 45 | .scsi_host_template = { |
47 | .name = ZFCP_NAME, | 46 | .name = ZFCP_NAME, |
48 | .proc_name = "zfcp", | 47 | .proc_name = "zfcp", |
49 | .proc_info = NULL, | ||
50 | .detect = NULL, | ||
51 | .slave_alloc = zfcp_scsi_slave_alloc, | 48 | .slave_alloc = zfcp_scsi_slave_alloc, |
52 | .slave_configure = zfcp_scsi_slave_configure, | 49 | .slave_configure = zfcp_scsi_slave_configure, |
53 | .slave_destroy = zfcp_scsi_slave_destroy, | 50 | .slave_destroy = zfcp_scsi_slave_destroy, |
54 | .queuecommand = zfcp_scsi_queuecommand, | 51 | .queuecommand = zfcp_scsi_queuecommand, |
55 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, | 52 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, |
56 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, | 53 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, |
57 | .eh_bus_reset_handler = zfcp_scsi_eh_bus_reset_handler, | 54 | .eh_bus_reset_handler = zfcp_scsi_eh_host_reset_handler, |
58 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, | 55 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, |
59 | .can_queue = 4096, | 56 | .can_queue = 4096, |
60 | .this_id = -1, | 57 | .this_id = -1, |
61 | /* | ||
62 | * FIXME: | ||
63 | * one less? can zfcp_create_sbale cope with it? | ||
64 | */ | ||
65 | .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, | 58 | .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, |
66 | .cmd_per_lun = 1, | 59 | .cmd_per_lun = 1, |
67 | .unchecked_isa_dma = 0, | ||
68 | .use_clustering = 1, | 60 | .use_clustering = 1, |
69 | .sdev_attrs = zfcp_sysfs_sdev_attrs, | 61 | .sdev_attrs = zfcp_sysfs_sdev_attrs, |
70 | }, | 62 | }, |
71 | .driver_version = ZFCP_VERSION, | 63 | .driver_version = ZFCP_VERSION, |
72 | /* rest initialised with zeros */ | ||
73 | }; | 64 | }; |
74 | 65 | ||
75 | /* Find start of Response Information in FCP response unit*/ | 66 | /* Find start of Response Information in FCP response unit*/ |
@@ -176,8 +167,14 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) | |||
176 | return retval; | 167 | return retval; |
177 | } | 168 | } |
178 | 169 | ||
179 | static void | 170 | /** |
180 | zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | 171 | * zfcp_scsi_slave_destroy - called when scsi device is removed |
172 | * | ||
173 | * Remove reference to associated scsi device for an zfcp_unit. | ||
174 | * Mark zfcp_unit as failed. The scsi device might be deleted via sysfs | ||
175 | * or a scan for this device might have failed. | ||
176 | */ | ||
177 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | ||
181 | { | 178 | { |
182 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 179 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
183 | 180 | ||
@@ -185,6 +182,7 @@ zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | |||
185 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); | 182 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); |
186 | sdpnt->hostdata = NULL; | 183 | sdpnt->hostdata = NULL; |
187 | unit->device = NULL; | 184 | unit->device = NULL; |
185 | zfcp_erp_unit_failed(unit); | ||
188 | zfcp_unit_put(unit); | 186 | zfcp_unit_put(unit); |
189 | } else { | 187 | } else { |
190 | ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " | 188 | ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " |
@@ -549,35 +547,38 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, | |||
549 | } | 547 | } |
550 | 548 | ||
551 | /** | 549 | /** |
552 | * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) | 550 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset |
551 | * | ||
552 | * If ERP is already running it will be stopped. | ||
553 | */ | 553 | */ |
554 | int | 554 | int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
555 | zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) | ||
556 | { | 555 | { |
557 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; | 556 | struct zfcp_unit *unit; |
558 | struct zfcp_adapter *adapter = unit->port->adapter; | 557 | struct zfcp_adapter *adapter; |
559 | 558 | unsigned long flags; | |
560 | ZFCP_LOG_NORMAL("bus reset because of problems with " | ||
561 | "unit 0x%016Lx\n", unit->fcp_lun); | ||
562 | zfcp_erp_adapter_reopen(adapter, 0); | ||
563 | zfcp_erp_wait(adapter); | ||
564 | |||
565 | return SUCCESS; | ||
566 | } | ||
567 | 559 | ||
568 | /** | 560 | unit = (struct zfcp_unit*) scpnt->device->hostdata; |
569 | * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) | 561 | adapter = unit->port->adapter; |
570 | */ | ||
571 | int | ||
572 | zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | ||
573 | { | ||
574 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; | ||
575 | struct zfcp_adapter *adapter = unit->port->adapter; | ||
576 | 562 | ||
577 | ZFCP_LOG_NORMAL("host reset because of problems with " | 563 | ZFCP_LOG_NORMAL("host/bus reset because of problems with " |
578 | "unit 0x%016Lx\n", unit->fcp_lun); | 564 | "unit 0x%016Lx\n", unit->fcp_lun); |
579 | zfcp_erp_adapter_reopen(adapter, 0); | 565 | |
580 | zfcp_erp_wait(adapter); | 566 | write_lock_irqsave(&adapter->erp_lock, flags); |
567 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | ||
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 | } | ||
581 | 582 | ||
582 | return SUCCESS; | 583 | return SUCCESS; |
583 | } | 584 | } |