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.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 3dc6188af0e8..12563998d97c 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2786,3 +2786,119 @@ int ata_scsi_offline_dev(struct ata_device *dev)
2786 } 2786 }
2787 return 0; 2787 return 0;
2788} 2788}
2789
2790/**
2791 * ata_scsi_remove_dev - remove attached SCSI device
2792 * @dev: ATA device to remove attached SCSI device for
2793 *
2794 * This function is called from ata_eh_scsi_hotplug() and
2795 * responsible for removing the SCSI device attached to @dev.
2796 *
2797 * LOCKING:
2798 * Kernel thread context (may sleep).
2799 */
2800static void ata_scsi_remove_dev(struct ata_device *dev)
2801{
2802 struct ata_port *ap = dev->ap;
2803 struct scsi_device *sdev;
2804 unsigned long flags;
2805
2806 /* Alas, we need to grab scan_mutex to ensure SCSI device
2807 * state doesn't change underneath us and thus
2808 * scsi_device_get() always succeeds. The mutex locking can
2809 * be removed if there is __scsi_device_get() interface which
2810 * increments reference counts regardless of device state.
2811 */
2812 mutex_lock(&ap->host->scan_mutex);
2813 spin_lock_irqsave(&ap->host_set->lock, flags);
2814
2815 /* clearing dev->sdev is protected by host_set lock */
2816 sdev = dev->sdev;
2817 dev->sdev = NULL;
2818
2819 if (sdev) {
2820 /* If user initiated unplug races with us, sdev can go
2821 * away underneath us after the host_set lock and
2822 * scan_mutex are released. Hold onto it.
2823 */
2824 if (scsi_device_get(sdev) == 0) {
2825 /* The following ensures the attached sdev is
2826 * offline on return from ata_scsi_offline_dev()
2827 * regardless it wins or loses the race
2828 * against this function.
2829 */
2830 scsi_device_set_state(sdev, SDEV_OFFLINE);
2831 } else {
2832 WARN_ON(1);
2833 sdev = NULL;
2834 }
2835 }
2836
2837 spin_unlock_irqrestore(&ap->host_set->lock, flags);
2838 mutex_unlock(&ap->host->scan_mutex);
2839
2840 if (sdev) {
2841 ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
2842 sdev->sdev_gendev.bus_id);
2843
2844 scsi_remove_device(sdev);
2845 scsi_device_put(sdev);
2846 }
2847}
2848
2849/**
2850 * ata_scsi_hotplug - SCSI part of hotplug
2851 * @data: Pointer to ATA port to perform SCSI hotplug on
2852 *
2853 * Perform SCSI part of hotplug. It's executed from a separate
2854 * workqueue after EH completes. This is necessary because SCSI
2855 * hot plugging requires working EH and hot unplugging is
2856 * synchronized with hot plugging with a mutex.
2857 *
2858 * LOCKING:
2859 * Kernel thread context (may sleep).
2860 */
2861void ata_scsi_hotplug(void *data)
2862{
2863 struct ata_port *ap = data;
2864 int i;
2865
2866 if (ap->flags & ATA_FLAG_UNLOADING) {
2867 DPRINTK("ENTER/EXIT - unloading\n");
2868 return;
2869 }
2870
2871 DPRINTK("ENTER\n");
2872
2873 /* unplug detached devices */
2874 for (i = 0; i < ATA_MAX_DEVICES; i++) {
2875 struct ata_device *dev = &ap->device[i];
2876 unsigned long flags;
2877
2878 if (!(dev->flags & ATA_DFLAG_DETACHED))
2879 continue;
2880
2881 spin_lock_irqsave(&ap->host_set->lock, flags);
2882 dev->flags &= ~ATA_DFLAG_DETACHED;
2883 spin_unlock_irqrestore(&ap->host_set->lock, flags);
2884
2885 ata_scsi_remove_dev(dev);
2886 }
2887
2888 /* scan for new ones */
2889 ata_scsi_scan_host(ap);
2890
2891 /* If we scanned while EH was in progress, scan would have
2892 * failed silently. Requeue if there are enabled but
2893 * unattached devices.
2894 */
2895 for (i = 0; i < ATA_MAX_DEVICES; i++) {
2896 struct ata_device *dev = &ap->device[i];
2897 if (ata_dev_enabled(dev) && !dev->sdev) {
2898 queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
2899 break;
2900 }
2901 }
2902
2903 DPRINTK("EXIT\n");
2904}