aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_srp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_srp.c')
-rw-r--r--drivers/scsi/scsi_transport_srp.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index ae45bd99baed..e3cd3ece4412 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -61,6 +61,11 @@ static inline struct Scsi_Host *rport_to_shost(struct srp_rport *r)
61 return dev_to_shost(r->dev.parent); 61 return dev_to_shost(r->dev.parent);
62} 62}
63 63
64static inline struct srp_rport *shost_to_rport(struct Scsi_Host *shost)
65{
66 return transport_class_to_srp_rport(&shost->shost_gendev);
67}
68
64/** 69/**
65 * srp_tmo_valid() - check timeout combination validity 70 * srp_tmo_valid() - check timeout combination validity
66 * @reconnect_delay: Reconnect delay in seconds. 71 * @reconnect_delay: Reconnect delay in seconds.
@@ -198,7 +203,7 @@ static ssize_t srp_show_tmo(char *buf, int tmo)
198 return tmo >= 0 ? sprintf(buf, "%d\n", tmo) : sprintf(buf, "off\n"); 203 return tmo >= 0 ? sprintf(buf, "%d\n", tmo) : sprintf(buf, "off\n");
199} 204}
200 205
201static int srp_parse_tmo(int *tmo, const char *buf) 206int srp_parse_tmo(int *tmo, const char *buf)
202{ 207{
203 int res = 0; 208 int res = 0;
204 209
@@ -209,6 +214,7 @@ static int srp_parse_tmo(int *tmo, const char *buf)
209 214
210 return res; 215 return res;
211} 216}
217EXPORT_SYMBOL(srp_parse_tmo);
212 218
213static ssize_t show_reconnect_delay(struct device *dev, 219static ssize_t show_reconnect_delay(struct device *dev,
214 struct device_attribute *attr, char *buf) 220 struct device_attribute *attr, char *buf)
@@ -396,6 +402,36 @@ static void srp_reconnect_work(struct work_struct *work)
396 } 402 }
397} 403}
398 404
405/**
406 * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
407 * @shost: SCSI host for which to count the number of scsi_request_fn() callers.
408 *
409 * To do: add support for scsi-mq in this function.
410 */
411static int scsi_request_fn_active(struct Scsi_Host *shost)
412{
413 struct scsi_device *sdev;
414 struct request_queue *q;
415 int request_fn_active = 0;
416
417 shost_for_each_device(sdev, shost) {
418 q = sdev->request_queue;
419
420 spin_lock_irq(q->queue_lock);
421 request_fn_active += q->request_fn_active;
422 spin_unlock_irq(q->queue_lock);
423 }
424
425 return request_fn_active;
426}
427
428/* Wait until ongoing shost->hostt->queuecommand() calls have finished. */
429static void srp_wait_for_queuecommand(struct Scsi_Host *shost)
430{
431 while (scsi_request_fn_active(shost))
432 msleep(20);
433}
434
399static void __rport_fail_io_fast(struct srp_rport *rport) 435static void __rport_fail_io_fast(struct srp_rport *rport)
400{ 436{
401 struct Scsi_Host *shost = rport_to_shost(rport); 437 struct Scsi_Host *shost = rport_to_shost(rport);
@@ -409,8 +445,10 @@ static void __rport_fail_io_fast(struct srp_rport *rport)
409 445
410 /* Involve the LLD if possible to terminate all I/O on the rport. */ 446 /* Involve the LLD if possible to terminate all I/O on the rport. */
411 i = to_srp_internal(shost->transportt); 447 i = to_srp_internal(shost->transportt);
412 if (i->f->terminate_rport_io) 448 if (i->f->terminate_rport_io) {
449 srp_wait_for_queuecommand(shost);
413 i->f->terminate_rport_io(rport); 450 i->f->terminate_rport_io(rport);
451 }
414} 452}
415 453
416/** 454/**
@@ -504,27 +542,6 @@ void srp_start_tl_fail_timers(struct srp_rport *rport)
504EXPORT_SYMBOL(srp_start_tl_fail_timers); 542EXPORT_SYMBOL(srp_start_tl_fail_timers);
505 543
506/** 544/**
507 * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
508 * @shost: SCSI host for which to count the number of scsi_request_fn() callers.
509 */
510static int scsi_request_fn_active(struct Scsi_Host *shost)
511{
512 struct scsi_device *sdev;
513 struct request_queue *q;
514 int request_fn_active = 0;
515
516 shost_for_each_device(sdev, shost) {
517 q = sdev->request_queue;
518
519 spin_lock_irq(q->queue_lock);
520 request_fn_active += q->request_fn_active;
521 spin_unlock_irq(q->queue_lock);
522 }
523
524 return request_fn_active;
525}
526
527/**
528 * srp_reconnect_rport() - reconnect to an SRP target port 545 * srp_reconnect_rport() - reconnect to an SRP target port
529 * @rport: SRP target port. 546 * @rport: SRP target port.
530 * 547 *
@@ -559,8 +576,7 @@ int srp_reconnect_rport(struct srp_rport *rport)
559 if (res) 576 if (res)
560 goto out; 577 goto out;
561 scsi_target_block(&shost->shost_gendev); 578 scsi_target_block(&shost->shost_gendev);
562 while (scsi_request_fn_active(shost)) 579 srp_wait_for_queuecommand(shost);
563 msleep(20);
564 res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; 580 res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV;
565 pr_debug("%s (state %d): transport.reconnect() returned %d\n", 581 pr_debug("%s (state %d): transport.reconnect() returned %d\n",
566 dev_name(&shost->shost_gendev), rport->state, res); 582 dev_name(&shost->shost_gendev), rport->state, res);
@@ -618,9 +634,11 @@ static enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd)
618 struct scsi_device *sdev = scmd->device; 634 struct scsi_device *sdev = scmd->device;
619 struct Scsi_Host *shost = sdev->host; 635 struct Scsi_Host *shost = sdev->host;
620 struct srp_internal *i = to_srp_internal(shost->transportt); 636 struct srp_internal *i = to_srp_internal(shost->transportt);
637 struct srp_rport *rport = shost_to_rport(shost);
621 638
622 pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev)); 639 pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev));
623 return i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? 640 return rport->fast_io_fail_tmo < 0 && rport->dev_loss_tmo < 0 &&
641 i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ?
624 BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; 642 BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED;
625} 643}
626 644