aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r--drivers/scsi/libata-scsi.c137
1 files changed, 130 insertions, 7 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 2915bca691e8..e92c31d698ff 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -397,20 +397,129 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
397 } 397 }
398} 398}
399 399
400int ata_scsi_device_resume(struct scsi_device *sdev) 400/**
401 * ata_scsi_device_suspend - suspend ATA device associated with sdev
402 * @sdev: the SCSI device to suspend
403 * @state: target power management state
404 *
405 * Request suspend EH action on the ATA device associated with
406 * @sdev and wait for the operation to complete.
407 *
408 * LOCKING:
409 * Kernel thread context (may sleep).
410 *
411 * RETURNS:
412 * 0 on success, -errno otherwise.
413 */
414int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
401{ 415{
402 struct ata_port *ap = ata_shost_to_port(sdev->host); 416 struct ata_port *ap = ata_shost_to_port(sdev->host);
403 struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); 417 struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
418 unsigned long flags;
419 unsigned int action;
420 int rc = 0;
421
422 if (!dev)
423 goto out;
424
425 spin_lock_irqsave(ap->lock, flags);
426
427 /* wait for the previous resume to complete */
428 while (dev->flags & ATA_DFLAG_SUSPENDED) {
429 spin_unlock_irqrestore(ap->lock, flags);
430 ata_port_wait_eh(ap);
431 spin_lock_irqsave(ap->lock, flags);
432 }
433
434 /* if @sdev is already detached, nothing to do */
435 if (sdev->sdev_state == SDEV_OFFLINE ||
436 sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
437 goto out_unlock;
438
439 /* request suspend */
440 action = ATA_EH_SUSPEND;
441 if (state.event != PM_EVENT_SUSPEND)
442 action |= ATA_EH_PM_FREEZE;
443 ap->eh_info.dev_action[dev->devno] |= action;
444 ap->eh_info.flags |= ATA_EHI_QUIET;
445 ata_port_schedule_eh(ap);
446
447 spin_unlock_irqrestore(ap->lock, flags);
448
449 /* wait for EH to do the job */
450 ata_port_wait_eh(ap);
451
452 spin_lock_irqsave(ap->lock, flags);
453
454 /* If @sdev is still attached but the associated ATA device
455 * isn't suspended, the operation failed.
456 */
457 if (sdev->sdev_state != SDEV_OFFLINE &&
458 sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL &&
459 !(dev->flags & ATA_DFLAG_SUSPENDED))
460 rc = -EIO;
404 461
405 return ata_device_resume(dev); 462 out_unlock:
463 spin_unlock_irqrestore(ap->lock, flags);
464 out:
465 if (rc == 0)
466 sdev->sdev_gendev.power.power_state = state;
467 return rc;
406} 468}
407 469
408int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) 470/**
471 * ata_scsi_device_resume - resume ATA device associated with sdev
472 * @sdev: the SCSI device to resume
473 *
474 * Request resume EH action on the ATA device associated with
475 * @sdev and return immediately. This enables parallel
476 * wakeup/spinup of devices.
477 *
478 * LOCKING:
479 * Kernel thread context (may sleep).
480 *
481 * RETURNS:
482 * 0.
483 */
484int ata_scsi_device_resume(struct scsi_device *sdev)
409{ 485{
410 struct ata_port *ap = ata_shost_to_port(sdev->host); 486 struct ata_port *ap = ata_shost_to_port(sdev->host);
411 struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); 487 struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
488 struct ata_eh_info *ehi = &ap->eh_info;
489 unsigned long flags;
490 unsigned int action;
412 491
413 return ata_device_suspend(dev, state); 492 if (!dev)
493 goto out;
494
495 spin_lock_irqsave(ap->lock, flags);
496
497 /* if @sdev is already detached, nothing to do */
498 if (sdev->sdev_state == SDEV_OFFLINE ||
499 sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
500 goto out_unlock;
501
502 /* request resume */
503 action = ATA_EH_RESUME;
504 if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND)
505 __ata_ehi_hotplugged(ehi);
506 else
507 action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET;
508 ehi->dev_action[dev->devno] |= action;
509
510 /* We don't want autopsy and verbose EH messages. Disable
511 * those if we're the only device on this link.
512 */
513 if (ata_port_max_devices(ap) == 1)
514 ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
515
516 ata_port_schedule_eh(ap);
517
518 out_unlock:
519 spin_unlock_irqrestore(ap->lock, flags);
520 out:
521 sdev->sdev_gendev.power.power_state = PMSG_ON;
522 return 0;
414} 523}
415 524
416/** 525/**
@@ -2244,6 +2353,19 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
2244 ata_gen_ata_desc_sense(qc); 2353 ata_gen_ata_desc_sense(qc);
2245 } 2354 }
2246 2355
2356 /* SCSI EH automatically locks door if sdev->locked is
2357 * set. Sometimes door lock request continues to
2358 * fail, for example, when no media is present. This
2359 * creates a loop - SCSI EH issues door lock which
2360 * fails and gets invoked again to acquire sense data
2361 * for the failed command.
2362 *
2363 * If door lock fails, always clear sdev->locked to
2364 * avoid this infinite loop.
2365 */
2366 if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
2367 qc->dev->sdev->locked = 0;
2368
2247 qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; 2369 qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
2248 qc->scsidone(cmd); 2370 qc->scsidone(cmd);
2249 ata_qc_free(qc); 2371 ata_qc_free(qc);
@@ -2930,7 +3052,7 @@ void ata_scsi_hotplug(void *data)
2930 struct ata_port *ap = data; 3052 struct ata_port *ap = data;
2931 int i; 3053 int i;
2932 3054
2933 if (ap->flags & ATA_FLAG_UNLOADING) { 3055 if (ap->pflags & ATA_PFLAG_UNLOADING) {
2934 DPRINTK("ENTER/EXIT - unloading\n"); 3056 DPRINTK("ENTER/EXIT - unloading\n");
2935 return; 3057 return;
2936 } 3058 }
@@ -3011,6 +3133,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
3011 if (dev) { 3133 if (dev) {
3012 ap->eh_info.probe_mask |= 1 << dev->devno; 3134 ap->eh_info.probe_mask |= 1 << dev->devno;
3013 ap->eh_info.action |= ATA_EH_SOFTRESET; 3135 ap->eh_info.action |= ATA_EH_SOFTRESET;
3136 ap->eh_info.flags |= ATA_EHI_RESUME_LINK;
3014 } else 3137 } else
3015 rc = -EINVAL; 3138 rc = -EINVAL;
3016 } 3139 }