diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 63 | ||||
-rw-r--r-- | drivers/ata/libata.h | 2 |
3 files changed, 49 insertions, 18 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 05922e9f4fad..35b621293831 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -6453,7 +6453,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
6453 | for (i = 0; i < host->n_ports; i++) { | 6453 | for (i = 0; i < host->n_ports; i++) { |
6454 | struct ata_port *ap = host->ports[i]; | 6454 | struct ata_port *ap = host->ports[i]; |
6455 | 6455 | ||
6456 | ata_scsi_scan_host(ap); | 6456 | ata_scsi_scan_host(ap, 1); |
6457 | } | 6457 | } |
6458 | 6458 | ||
6459 | return 0; | 6459 | return 0; |
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index cfde22da07ac..12ac0b511f79 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -2947,17 +2947,22 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) | |||
2947 | return rc; | 2947 | return rc; |
2948 | } | 2948 | } |
2949 | 2949 | ||
2950 | void ata_scsi_scan_host(struct ata_port *ap) | 2950 | void ata_scsi_scan_host(struct ata_port *ap, int sync) |
2951 | { | 2951 | { |
2952 | int tries = 5; | ||
2953 | struct ata_device *last_failed_dev = NULL; | ||
2954 | struct ata_device *dev; | ||
2952 | unsigned int i; | 2955 | unsigned int i; |
2953 | 2956 | ||
2954 | if (ap->flags & ATA_FLAG_DISABLED) | 2957 | if (ap->flags & ATA_FLAG_DISABLED) |
2955 | return; | 2958 | return; |
2956 | 2959 | ||
2960 | repeat: | ||
2957 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | 2961 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
2958 | struct ata_device *dev = &ap->device[i]; | ||
2959 | struct scsi_device *sdev; | 2962 | struct scsi_device *sdev; |
2960 | 2963 | ||
2964 | dev = &ap->device[i]; | ||
2965 | |||
2961 | if (!ata_dev_enabled(dev) || dev->sdev) | 2966 | if (!ata_dev_enabled(dev) || dev->sdev) |
2962 | continue; | 2967 | continue; |
2963 | 2968 | ||
@@ -2967,6 +2972,45 @@ void ata_scsi_scan_host(struct ata_port *ap) | |||
2967 | scsi_device_put(sdev); | 2972 | scsi_device_put(sdev); |
2968 | } | 2973 | } |
2969 | } | 2974 | } |
2975 | |||
2976 | /* If we scanned while EH was in progress or allocation | ||
2977 | * failure occurred, scan would have failed silently. Check | ||
2978 | * whether all devices are attached. | ||
2979 | */ | ||
2980 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
2981 | dev = &ap->device[i]; | ||
2982 | if (ata_dev_enabled(dev) && !dev->sdev) | ||
2983 | break; | ||
2984 | } | ||
2985 | if (i == ATA_MAX_DEVICES) | ||
2986 | return; | ||
2987 | |||
2988 | /* we're missing some SCSI devices */ | ||
2989 | if (sync) { | ||
2990 | /* If caller requested synchrnous scan && we've made | ||
2991 | * any progress, sleep briefly and repeat. | ||
2992 | */ | ||
2993 | if (dev != last_failed_dev) { | ||
2994 | msleep(100); | ||
2995 | last_failed_dev = dev; | ||
2996 | goto repeat; | ||
2997 | } | ||
2998 | |||
2999 | /* We might be failing to detect boot device, give it | ||
3000 | * a few more chances. | ||
3001 | */ | ||
3002 | if (--tries) { | ||
3003 | msleep(100); | ||
3004 | goto repeat; | ||
3005 | } | ||
3006 | |||
3007 | ata_port_printk(ap, KERN_ERR, "WARNING: synchronous SCSI scan " | ||
3008 | "failed without making any progress,\n" | ||
3009 | " switching to async\n"); | ||
3010 | } | ||
3011 | |||
3012 | queue_delayed_work(ata_aux_wq, &ap->hotplug_task, | ||
3013 | round_jiffies_relative(HZ)); | ||
2970 | } | 3014 | } |
2971 | 3015 | ||
2972 | /** | 3016 | /** |
@@ -3093,20 +3137,7 @@ void ata_scsi_hotplug(struct work_struct *work) | |||
3093 | } | 3137 | } |
3094 | 3138 | ||
3095 | /* scan for new ones */ | 3139 | /* scan for new ones */ |
3096 | ata_scsi_scan_host(ap); | 3140 | ata_scsi_scan_host(ap, 0); |
3097 | |||
3098 | /* If we scanned while EH was in progress, scan would have | ||
3099 | * failed silently. Requeue if there are enabled but | ||
3100 | * unattached devices. | ||
3101 | */ | ||
3102 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
3103 | struct ata_device *dev = &ap->device[i]; | ||
3104 | if (ata_dev_enabled(dev) && !dev->sdev) { | ||
3105 | queue_delayed_work(ata_aux_wq, &ap->hotplug_task, | ||
3106 | round_jiffies_relative(HZ)); | ||
3107 | break; | ||
3108 | } | ||
3109 | } | ||
3110 | 3141 | ||
3111 | DPRINTK("EXIT\n"); | 3142 | DPRINTK("EXIT\n"); |
3112 | } | 3143 | } |
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index ba17fc5f2e99..48836b22ce2f 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -112,7 +112,7 @@ static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; } | |||
112 | /* libata-scsi.c */ | 112 | /* libata-scsi.c */ |
113 | extern int ata_scsi_add_hosts(struct ata_host *host, | 113 | extern int ata_scsi_add_hosts(struct ata_host *host, |
114 | struct scsi_host_template *sht); | 114 | struct scsi_host_template *sht); |
115 | extern void ata_scsi_scan_host(struct ata_port *ap); | 115 | extern void ata_scsi_scan_host(struct ata_port *ap, int sync); |
116 | extern int ata_scsi_offline_dev(struct ata_device *dev); | 116 | extern int ata_scsi_offline_dev(struct ata_device *dev); |
117 | extern void ata_scsi_hotplug(struct work_struct *work); | 117 | extern void ata_scsi_hotplug(struct work_struct *work); |
118 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, | 118 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, |