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.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 12563998d97c..7c1ac58c430a 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -57,6 +57,8 @@ static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
57 const struct scsi_device *scsidev); 57 const struct scsi_device *scsidev);
58static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, 58static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
59 const struct scsi_device *scsidev); 59 const struct scsi_device *scsidev);
60static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
61 unsigned int id, unsigned int lun);
60 62
61 63
62#define RW_RECOVERY_MPAGE 0x1 64#define RW_RECOVERY_MPAGE 0x1
@@ -727,6 +729,40 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
727} 729}
728 730
729/** 731/**
732 * ata_scsi_slave_destroy - SCSI device is about to be destroyed
733 * @sdev: SCSI device to be destroyed
734 *
735 * @sdev is about to be destroyed for hot/warm unplugging. If
736 * this unplugging was initiated by libata as indicated by NULL
737 * dev->sdev, this function doesn't have to do anything.
738 * Otherwise, SCSI layer initiated warm-unplug is in progress.
739 * Clear dev->sdev, schedule the device for ATA detach and invoke
740 * EH.
741 *
742 * LOCKING:
743 * Defined by SCSI layer. We don't really care.
744 */
745void ata_scsi_slave_destroy(struct scsi_device *sdev)
746{
747 struct ata_port *ap = ata_shost_to_port(sdev->host);
748 unsigned long flags;
749 struct ata_device *dev;
750
751 if (!ap->ops->error_handler)
752 return;
753
754 spin_lock_irqsave(&ap->host_set->lock, flags);
755 dev = __ata_scsi_find_dev(ap, sdev);
756 if (dev && dev->sdev) {
757 /* SCSI device already in CANCEL state, no need to offline it */
758 dev->sdev = NULL;
759 dev->flags |= ATA_DFLAG_DETACH;
760 ata_port_schedule_eh(ap);
761 }
762 spin_unlock_irqrestore(&ap->host_set->lock, flags);
763}
764
765/**
730 * ata_scsi_change_queue_depth - SCSI callback for queue depth config 766 * ata_scsi_change_queue_depth - SCSI callback for queue depth config
731 * @sdev: SCSI device to configure queue depth for 767 * @sdev: SCSI device to configure queue depth for
732 * @queue_depth: new queue depth 768 * @queue_depth: new queue depth
@@ -2902,3 +2938,56 @@ void ata_scsi_hotplug(void *data)
2902 2938
2903 DPRINTK("EXIT\n"); 2939 DPRINTK("EXIT\n");
2904} 2940}
2941
2942/**
2943 * ata_scsi_user_scan - indication for user-initiated bus scan
2944 * @shost: SCSI host to scan
2945 * @channel: Channel to scan
2946 * @id: ID to scan
2947 * @lun: LUN to scan
2948 *
2949 * This function is called when user explicitly requests bus
2950 * scan. Set probe pending flag and invoke EH.
2951 *
2952 * LOCKING:
2953 * SCSI layer (we don't care)
2954 *
2955 * RETURNS:
2956 * Zero.
2957 */
2958static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
2959 unsigned int id, unsigned int lun)
2960{
2961 struct ata_port *ap = ata_shost_to_port(shost);
2962 unsigned long flags;
2963 int rc = 0;
2964
2965 if (!ap->ops->error_handler)
2966 return -EOPNOTSUPP;
2967
2968 if ((channel != SCAN_WILD_CARD && channel != 0) ||
2969 (lun != SCAN_WILD_CARD && lun != 0))
2970 return -EINVAL;
2971
2972 spin_lock_irqsave(&ap->host_set->lock, flags);
2973
2974 if (id == SCAN_WILD_CARD) {
2975 ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
2976 ap->eh_info.action |= ATA_EH_SOFTRESET;
2977 } else {
2978 struct ata_device *dev = ata_find_dev(ap, id);
2979
2980 if (dev) {
2981 ap->eh_info.probe_mask |= 1 << dev->devno;
2982 ap->eh_info.action |= ATA_EH_SOFTRESET;
2983 } else
2984 rc = -EINVAL;
2985 }
2986
2987 if (rc == 0)
2988 ata_port_schedule_eh(ap);
2989
2990 spin_unlock_irqrestore(&ap->host_set->lock, flags);
2991
2992 return rc;
2993}