aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c250
1 files changed, 178 insertions, 72 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 9dc42a68fbdd..58201e1ae478 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Interface to Linux SCSI midlayer. 4 * Interface to Linux SCSI midlayer.
5 * 5 *
6 * Copyright IBM Corporation 2002, 2008 6 * Copyright IBM Corporation 2002, 2009
7 */ 7 */
8 8
9#define KMSG_COMPONENT "zfcp" 9#define KMSG_COMPONENT "zfcp"
@@ -27,9 +27,7 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
27static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) 27static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
28{ 28{
29 struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; 29 struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
30 atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
31 unit->device = NULL; 30 unit->device = NULL;
32 zfcp_erp_unit_failed(unit, 12, NULL);
33 zfcp_unit_put(unit); 31 zfcp_unit_put(unit);
34} 32}
35 33
@@ -58,8 +56,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
58{ 56{
59 struct zfcp_unit *unit; 57 struct zfcp_unit *unit;
60 struct zfcp_adapter *adapter; 58 struct zfcp_adapter *adapter;
61 int status; 59 int status, scsi_result, ret;
62 int ret; 60 struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
63 61
64 /* reset the status for this request */ 62 /* reset the status for this request */
65 scpnt->result = 0; 63 scpnt->result = 0;
@@ -81,6 +79,14 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
81 return 0; 79 return 0;
82 } 80 }
83 81
82 scsi_result = fc_remote_port_chkready(rport);
83 if (unlikely(scsi_result)) {
84 scpnt->result = scsi_result;
85 zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL);
86 scpnt->scsi_done(scpnt);
87 return 0;
88 }
89
84 status = atomic_read(&unit->status); 90 status = atomic_read(&unit->status);
85 if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) || 91 if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) ||
86 !(status & ZFCP_STATUS_COMMON_RUNNING))) { 92 !(status & ZFCP_STATUS_COMMON_RUNNING))) {
@@ -88,8 +94,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
88 return 0;; 94 return 0;;
89 } 95 }
90 96
91 ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0, 97 ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
92 ZFCP_REQ_AUTO_CLEANUP);
93 if (unlikely(ret == -EBUSY)) 98 if (unlikely(ret == -EBUSY))
94 return SCSI_MLQUEUE_DEVICE_BUSY; 99 return SCSI_MLQUEUE_DEVICE_BUSY;
95 else if (unlikely(ret < 0)) 100 else if (unlikely(ret < 0))
@@ -133,8 +138,7 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
133 138
134 read_lock_irqsave(&zfcp_data.config_lock, flags); 139 read_lock_irqsave(&zfcp_data.config_lock, flags);
135 unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); 140 unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun);
136 if (unit && 141 if (unit) {
137 (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_REGISTERED)) {
138 sdp->hostdata = unit; 142 sdp->hostdata = unit;
139 unit->device = sdp; 143 unit->device = sdp;
140 zfcp_unit_get(unit); 144 zfcp_unit_get(unit);
@@ -147,79 +151,91 @@ out:
147 151
148static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) 152static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
149{ 153{
150 struct Scsi_Host *scsi_host; 154 struct Scsi_Host *scsi_host = scpnt->device->host;
151 struct zfcp_adapter *adapter; 155 struct zfcp_adapter *adapter =
152 struct zfcp_unit *unit; 156 (struct zfcp_adapter *) scsi_host->hostdata[0];
153 struct zfcp_fsf_req *fsf_req; 157 struct zfcp_unit *unit = scpnt->device->hostdata;
158 struct zfcp_fsf_req *old_req, *abrt_req;
154 unsigned long flags; 159 unsigned long flags;
155 unsigned long old_req_id = (unsigned long) scpnt->host_scribble; 160 unsigned long old_req_id = (unsigned long) scpnt->host_scribble;
156 int retval = SUCCESS; 161 int retval = SUCCESS;
157 162 int retry = 3;
158 scsi_host = scpnt->device->host;
159 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
160 unit = scpnt->device->hostdata;
161 163
162 /* avoid race condition between late normal completion and abort */ 164 /* avoid race condition between late normal completion and abort */
163 write_lock_irqsave(&adapter->abort_lock, flags); 165 write_lock_irqsave(&adapter->abort_lock, flags);
164 166
165 /* Check whether corresponding fsf_req is still pending */
166 spin_lock(&adapter->req_list_lock); 167 spin_lock(&adapter->req_list_lock);
167 fsf_req = zfcp_reqlist_find(adapter, old_req_id); 168 old_req = zfcp_reqlist_find(adapter, old_req_id);
168 spin_unlock(&adapter->req_list_lock); 169 spin_unlock(&adapter->req_list_lock);
169 if (!fsf_req) { 170 if (!old_req) {
170 write_unlock_irqrestore(&adapter->abort_lock, flags); 171 write_unlock_irqrestore(&adapter->abort_lock, flags);
171 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0); 172 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
172 return retval; 173 old_req_id);
174 return SUCCESS;
173 } 175 }
174 fsf_req->data = NULL; 176 old_req->data = NULL;
175 177
176 /* don't access old fsf_req after releasing the abort_lock */ 178 /* don't access old fsf_req after releasing the abort_lock */
177 write_unlock_irqrestore(&adapter->abort_lock, flags); 179 write_unlock_irqrestore(&adapter->abort_lock, flags);
178 180
179 fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0); 181 while (retry--) {
180 if (!fsf_req) { 182 abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit);
181 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, 183 if (abrt_req)
182 old_req_id); 184 break;
183 retval = FAILED; 185
184 return retval; 186 zfcp_erp_wait(adapter);
187 if (!(atomic_read(&adapter->status) &
188 ZFCP_STATUS_COMMON_RUNNING)) {
189 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
190 old_req_id);
191 return SUCCESS;
192 }
185 } 193 }
194 if (!abrt_req)
195 return FAILED;
186 196
187 __wait_event(fsf_req->completion_wq, 197 wait_event(abrt_req->completion_wq,
188 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 198 abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
189 199
190 if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { 200 if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
191 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0); 201 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0);
192 } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { 202 else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
193 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0); 203 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0);
194 } else { 204 else {
195 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0); 205 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0);
196 retval = FAILED; 206 retval = FAILED;
197 } 207 }
198 zfcp_fsf_req_free(fsf_req); 208 zfcp_fsf_req_free(abrt_req);
199
200 return retval; 209 return retval;
201} 210}
202 211
203static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags, 212static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
204 struct scsi_cmnd *scpnt)
205{ 213{
214 struct zfcp_unit *unit = scpnt->device->hostdata;
206 struct zfcp_adapter *adapter = unit->port->adapter; 215 struct zfcp_adapter *adapter = unit->port->adapter;
207 struct zfcp_fsf_req *fsf_req; 216 struct zfcp_fsf_req *fsf_req;
208 int retval = SUCCESS; 217 int retval = SUCCESS;
209 218 int retry = 3;
210 /* issue task management function */ 219
211 fsf_req = zfcp_fsf_send_fcp_ctm(adapter, unit, tm_flags, 0); 220 while (retry--) {
212 if (!fsf_req) { 221 fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
213 zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt); 222 if (fsf_req)
214 return FAILED; 223 break;
224
225 zfcp_erp_wait(adapter);
226 if (!(atomic_read(&adapter->status) &
227 ZFCP_STATUS_COMMON_RUNNING)) {
228 zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit,
229 scpnt);
230 return SUCCESS;
231 }
215 } 232 }
233 if (!fsf_req)
234 return FAILED;
216 235
217 __wait_event(fsf_req->completion_wq, 236 wait_event(fsf_req->completion_wq,
218 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 237 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
219 238
220 /*
221 * check completion status of task management function
222 */
223 if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { 239 if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
224 zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); 240 zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
225 retval = FAILED; 241 retval = FAILED;
@@ -230,40 +246,25 @@ static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags,
230 zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt); 246 zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
231 247
232 zfcp_fsf_req_free(fsf_req); 248 zfcp_fsf_req_free(fsf_req);
233
234 return retval; 249 return retval;
235} 250}
236 251
237static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) 252static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
238{ 253{
239 struct zfcp_unit *unit = scpnt->device->hostdata; 254 return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET);
240
241 if (!unit) {
242 WARN_ON(1);
243 return SUCCESS;
244 }
245 return zfcp_task_mgmt_function(unit, FCP_LOGICAL_UNIT_RESET, scpnt);
246} 255}
247 256
248static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) 257static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
249{ 258{
250 struct zfcp_unit *unit = scpnt->device->hostdata; 259 return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET);
251
252 if (!unit) {
253 WARN_ON(1);
254 return SUCCESS;
255 }
256 return zfcp_task_mgmt_function(unit, FCP_TARGET_RESET, scpnt);
257} 260}
258 261
259static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) 262static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
260{ 263{
261 struct zfcp_unit *unit; 264 struct zfcp_unit *unit = scpnt->device->hostdata;
262 struct zfcp_adapter *adapter; 265 struct zfcp_adapter *adapter = unit->port->adapter;
263 266
264 unit = scpnt->device->hostdata; 267 zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
265 adapter = unit->port->adapter;
266 zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
267 zfcp_erp_wait(adapter); 268 zfcp_erp_wait(adapter);
268 269
269 return SUCCESS; 270 return SUCCESS;
@@ -479,6 +480,109 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
479 rport->dev_loss_tmo = timeout; 480 rport->dev_loss_tmo = timeout;
480} 481}
481 482
483/**
484 * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport
485 * @rport: The rport that is about to be deleted.
486 */
487static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
488{
489 struct zfcp_port *port = rport->dd_data;
490
491 write_lock_irq(&zfcp_data.config_lock);
492 port->rport = NULL;
493 write_unlock_irq(&zfcp_data.config_lock);
494}
495
496/**
497 * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
498 * @rport: The FC rport where to teminate I/O
499 *
500 * Abort all pending SCSI commands for a port by closing the
501 * port. Using a reopen for avoids a conflict with a shutdown
502 * overwriting a reopen.
503 */
504static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
505{
506 struct zfcp_port *port = rport->dd_data;
507
508 zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
509}
510
511static void zfcp_scsi_rport_register(struct zfcp_port *port)
512{
513 struct fc_rport_identifiers ids;
514 struct fc_rport *rport;
515
516 ids.node_name = port->wwnn;
517 ids.port_name = port->wwpn;
518 ids.port_id = port->d_id;
519 ids.roles = FC_RPORT_ROLE_FCP_TARGET;
520
521 rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
522 if (!rport) {
523 dev_err(&port->adapter->ccw_device->dev,
524 "Registering port 0x%016Lx failed\n",
525 (unsigned long long)port->wwpn);
526 return;
527 }
528
529 rport->dd_data = port;
530 rport->maxframe_size = port->maxframe_size;
531 rport->supported_classes = port->supported_classes;
532 port->rport = rport;
533}
534
535static void zfcp_scsi_rport_block(struct zfcp_port *port)
536{
537 if (port->rport)
538 fc_remote_port_delete(port->rport);
539}
540
541void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
542{
543 zfcp_port_get(port);
544 port->rport_task = RPORT_ADD;
545
546 if (!queue_work(zfcp_data.work_queue, &port->rport_work))
547 zfcp_port_put(port);
548}
549
550void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
551{
552 zfcp_port_get(port);
553 port->rport_task = RPORT_DEL;
554
555 if (!queue_work(zfcp_data.work_queue, &port->rport_work))
556 zfcp_port_put(port);
557}
558
559void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
560{
561 struct zfcp_port *port;
562
563 list_for_each_entry(port, &adapter->port_list_head, list)
564 zfcp_scsi_schedule_rport_block(port);
565}
566
567void zfcp_scsi_rport_work(struct work_struct *work)
568{
569 struct zfcp_port *port = container_of(work, struct zfcp_port,
570 rport_work);
571
572 while (port->rport_task) {
573 if (port->rport_task == RPORT_ADD) {
574 port->rport_task = RPORT_NONE;
575 zfcp_scsi_rport_register(port);
576 } else {
577 port->rport_task = RPORT_NONE;
578 zfcp_scsi_rport_block(port);
579 }
580 }
581
582 zfcp_port_put(port);
583}
584
585
482struct fc_function_template zfcp_transport_functions = { 586struct fc_function_template zfcp_transport_functions = {
483 .show_starget_port_id = 1, 587 .show_starget_port_id = 1,
484 .show_starget_port_name = 1, 588 .show_starget_port_name = 1,
@@ -497,6 +601,8 @@ struct fc_function_template zfcp_transport_functions = {
497 .reset_fc_host_stats = zfcp_reset_fc_host_stats, 601 .reset_fc_host_stats = zfcp_reset_fc_host_stats,
498 .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, 602 .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
499 .get_host_port_state = zfcp_get_host_port_state, 603 .get_host_port_state = zfcp_get_host_port_state,
604 .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
605 .terminate_rport_io = zfcp_scsi_terminate_rport_io,
500 .show_host_port_state = 1, 606 .show_host_port_state = 1,
501 /* no functions registered for following dynamic attributes but 607 /* no functions registered for following dynamic attributes but
502 directly set by LLDD */ 608 directly set by LLDD */