diff options
author | Tejun Heo <htejun@gmail.com> | 2007-08-06 05:36:24 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-12 14:55:32 -0400 |
commit | 41bda9c98035dd3589b02cbc1de02f71d2faf9c8 (patch) | |
tree | 2a5b0c85584d443c1c8f7cb2b592e75bea3da6cf /drivers | |
parent | 9b1e2658faf3f3095a96558c333b333c0e29dbc0 (diff) |
libata-link: update hotplug to handle PMP links
Update hotplug to handle PMP links. When PMP is attached, the PMP
number corresponds to C of SCSI H:C:I:L. While at it, change argument
to ata_find_dev() to @devno from @id to avoid confusion with SCSI
device ID.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/libata-core.c | 7 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 159 |
2 files changed, 114 insertions, 52 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index af9c0ab600dc..14f299278f1b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -6604,6 +6604,7 @@ int ata_host_activate(struct ata_host *host, int irq, | |||
6604 | void ata_port_detach(struct ata_port *ap) | 6604 | void ata_port_detach(struct ata_port *ap) |
6605 | { | 6605 | { |
6606 | unsigned long flags; | 6606 | unsigned long flags; |
6607 | struct ata_link *link; | ||
6607 | struct ata_device *dev; | 6608 | struct ata_device *dev; |
6608 | 6609 | ||
6609 | if (!ap->ops->error_handler) | 6610 | if (!ap->ops->error_handler) |
@@ -6621,8 +6622,10 @@ void ata_port_detach(struct ata_port *ap) | |||
6621 | */ | 6622 | */ |
6622 | spin_lock_irqsave(ap->lock, flags); | 6623 | spin_lock_irqsave(ap->lock, flags); |
6623 | 6624 | ||
6624 | ata_link_for_each_dev(dev, &ap->link) | 6625 | ata_port_for_each_link(link, ap) { |
6625 | ata_dev_disable(dev); | 6626 | ata_link_for_each_dev(dev, link) |
6627 | ata_dev_disable(dev); | ||
6628 | } | ||
6626 | 6629 | ||
6627 | spin_unlock_irqrestore(ap->lock, flags); | 6630 | spin_unlock_irqrestore(ap->lock, flags); |
6628 | 6631 | ||
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3d6d5f737994..58051ee40f1a 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -2423,21 +2423,36 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) | |||
2423 | return 0; | 2423 | return 0; |
2424 | } | 2424 | } |
2425 | 2425 | ||
2426 | static struct ata_device * ata_find_dev(struct ata_port *ap, int id) | 2426 | static struct ata_device * ata_find_dev(struct ata_port *ap, int devno) |
2427 | { | 2427 | { |
2428 | if (likely(id < ata_link_max_devices(&ap->link))) | 2428 | if (ap->nr_pmp_links == 0) { |
2429 | return &ap->link.device[id]; | 2429 | if (likely(devno < ata_link_max_devices(&ap->link))) |
2430 | return &ap->link.device[devno]; | ||
2431 | } else { | ||
2432 | if (likely(devno < ap->nr_pmp_links)) | ||
2433 | return &ap->pmp_link[devno].device[0]; | ||
2434 | } | ||
2435 | |||
2430 | return NULL; | 2436 | return NULL; |
2431 | } | 2437 | } |
2432 | 2438 | ||
2433 | static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, | 2439 | static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, |
2434 | const struct scsi_device *scsidev) | 2440 | const struct scsi_device *scsidev) |
2435 | { | 2441 | { |
2442 | int devno; | ||
2443 | |||
2436 | /* skip commands not addressed to targets we simulate */ | 2444 | /* skip commands not addressed to targets we simulate */ |
2437 | if (unlikely(scsidev->channel || scsidev->lun)) | 2445 | if (ap->nr_pmp_links == 0) { |
2438 | return NULL; | 2446 | if (unlikely(scsidev->channel || scsidev->lun)) |
2447 | return NULL; | ||
2448 | devno = scsidev->id; | ||
2449 | } else { | ||
2450 | if (unlikely(scsidev->id || scsidev->lun)) | ||
2451 | return NULL; | ||
2452 | devno = scsidev->channel; | ||
2453 | } | ||
2439 | 2454 | ||
2440 | return ata_find_dev(ap, scsidev->id); | 2455 | return ata_find_dev(ap, devno); |
2441 | } | 2456 | } |
2442 | 2457 | ||
2443 | /** | 2458 | /** |
@@ -2951,22 +2966,32 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) | |||
2951 | { | 2966 | { |
2952 | int tries = 5; | 2967 | int tries = 5; |
2953 | struct ata_device *last_failed_dev = NULL; | 2968 | struct ata_device *last_failed_dev = NULL; |
2969 | struct ata_link *link; | ||
2954 | struct ata_device *dev; | 2970 | struct ata_device *dev; |
2955 | 2971 | ||
2956 | if (ap->flags & ATA_FLAG_DISABLED) | 2972 | if (ap->flags & ATA_FLAG_DISABLED) |
2957 | return; | 2973 | return; |
2958 | 2974 | ||
2959 | repeat: | 2975 | repeat: |
2960 | ata_link_for_each_dev(dev, &ap->link) { | 2976 | ata_port_for_each_link(link, ap) { |
2961 | struct scsi_device *sdev; | 2977 | ata_link_for_each_dev(dev, link) { |
2978 | struct scsi_device *sdev; | ||
2979 | int channel = 0, id = 0; | ||
2962 | 2980 | ||
2963 | if (!ata_dev_enabled(dev) || dev->sdev) | 2981 | if (!ata_dev_enabled(dev) || dev->sdev) |
2964 | continue; | 2982 | continue; |
2965 | 2983 | ||
2966 | sdev = __scsi_add_device(ap->scsi_host, 0, dev->devno, 0, NULL); | 2984 | if (ata_is_host_link(link)) |
2967 | if (!IS_ERR(sdev)) { | 2985 | id = dev->devno; |
2968 | dev->sdev = sdev; | 2986 | else |
2969 | scsi_device_put(sdev); | 2987 | channel = link->pmp; |
2988 | |||
2989 | sdev = __scsi_add_device(ap->scsi_host, channel, id, 0, | ||
2990 | NULL); | ||
2991 | if (!IS_ERR(sdev)) { | ||
2992 | dev->sdev = sdev; | ||
2993 | scsi_device_put(sdev); | ||
2994 | } | ||
2970 | } | 2995 | } |
2971 | } | 2996 | } |
2972 | 2997 | ||
@@ -2974,11 +2999,14 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) | |||
2974 | * failure occurred, scan would have failed silently. Check | 2999 | * failure occurred, scan would have failed silently. Check |
2975 | * whether all devices are attached. | 3000 | * whether all devices are attached. |
2976 | */ | 3001 | */ |
2977 | ata_link_for_each_dev(dev, &ap->link) { | 3002 | ata_port_for_each_link(link, ap) { |
2978 | if (ata_dev_enabled(dev) && !dev->sdev) | 3003 | ata_link_for_each_dev(dev, link) { |
2979 | break; | 3004 | if (ata_dev_enabled(dev) && !dev->sdev) |
3005 | goto exit_loop; | ||
3006 | } | ||
2980 | } | 3007 | } |
2981 | if (!dev) | 3008 | exit_loop: |
3009 | if (!link) | ||
2982 | return; | 3010 | return; |
2983 | 3011 | ||
2984 | /* we're missing some SCSI devices */ | 3012 | /* we're missing some SCSI devices */ |
@@ -3092,6 +3120,25 @@ static void ata_scsi_remove_dev(struct ata_device *dev) | |||
3092 | } | 3120 | } |
3093 | } | 3121 | } |
3094 | 3122 | ||
3123 | static void ata_scsi_handle_link_detach(struct ata_link *link) | ||
3124 | { | ||
3125 | struct ata_port *ap = link->ap; | ||
3126 | struct ata_device *dev; | ||
3127 | |||
3128 | ata_link_for_each_dev(dev, link) { | ||
3129 | unsigned long flags; | ||
3130 | |||
3131 | if (!(dev->flags & ATA_DFLAG_DETACHED)) | ||
3132 | continue; | ||
3133 | |||
3134 | spin_lock_irqsave(ap->lock, flags); | ||
3135 | dev->flags &= ~ATA_DFLAG_DETACHED; | ||
3136 | spin_unlock_irqrestore(ap->lock, flags); | ||
3137 | |||
3138 | ata_scsi_remove_dev(dev); | ||
3139 | } | ||
3140 | } | ||
3141 | |||
3095 | /** | 3142 | /** |
3096 | * ata_scsi_hotplug - SCSI part of hotplug | 3143 | * ata_scsi_hotplug - SCSI part of hotplug |
3097 | * @work: Pointer to ATA port to perform SCSI hotplug on | 3144 | * @work: Pointer to ATA port to perform SCSI hotplug on |
@@ -3108,7 +3155,7 @@ void ata_scsi_hotplug(struct work_struct *work) | |||
3108 | { | 3155 | { |
3109 | struct ata_port *ap = | 3156 | struct ata_port *ap = |
3110 | container_of(work, struct ata_port, hotplug_task.work); | 3157 | container_of(work, struct ata_port, hotplug_task.work); |
3111 | struct ata_device *dev; | 3158 | int i; |
3112 | 3159 | ||
3113 | if (ap->pflags & ATA_PFLAG_UNLOADING) { | 3160 | if (ap->pflags & ATA_PFLAG_UNLOADING) { |
3114 | DPRINTK("ENTER/EXIT - unloading\n"); | 3161 | DPRINTK("ENTER/EXIT - unloading\n"); |
@@ -3117,19 +3164,14 @@ void ata_scsi_hotplug(struct work_struct *work) | |||
3117 | 3164 | ||
3118 | DPRINTK("ENTER\n"); | 3165 | DPRINTK("ENTER\n"); |
3119 | 3166 | ||
3120 | /* unplug detached devices */ | 3167 | /* Unplug detached devices. We cannot use link iterator here |
3121 | ata_link_for_each_dev(dev, &ap->link) { | 3168 | * because PMP links have to be scanned even if PMP is |
3122 | unsigned long flags; | 3169 | * currently not attached. Iterate manually. |
3123 | 3170 | */ | |
3124 | if (!(dev->flags & ATA_DFLAG_DETACHED)) | 3171 | ata_scsi_handle_link_detach(&ap->link); |
3125 | continue; | 3172 | if (ap->pmp_link) |
3126 | 3173 | for (i = 0; i < SATA_PMP_MAX_PORTS; i++) | |
3127 | spin_lock_irqsave(ap->lock, flags); | 3174 | ata_scsi_handle_link_detach(&ap->pmp_link[i]); |
3128 | dev->flags &= ~ATA_DFLAG_DETACHED; | ||
3129 | spin_unlock_irqrestore(ap->lock, flags); | ||
3130 | |||
3131 | ata_scsi_remove_dev(dev); | ||
3132 | } | ||
3133 | 3175 | ||
3134 | /* scan for new ones */ | 3176 | /* scan for new ones */ |
3135 | ata_scsi_scan_host(ap, 0); | 3177 | ata_scsi_scan_host(ap, 0); |
@@ -3157,26 +3199,40 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, | |||
3157 | unsigned int id, unsigned int lun) | 3199 | unsigned int id, unsigned int lun) |
3158 | { | 3200 | { |
3159 | struct ata_port *ap = ata_shost_to_port(shost); | 3201 | struct ata_port *ap = ata_shost_to_port(shost); |
3160 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
3161 | unsigned long flags; | 3202 | unsigned long flags; |
3162 | int rc = 0; | 3203 | int devno, rc = 0; |
3163 | 3204 | ||
3164 | if (!ap->ops->error_handler) | 3205 | if (!ap->ops->error_handler) |
3165 | return -EOPNOTSUPP; | 3206 | return -EOPNOTSUPP; |
3166 | 3207 | ||
3167 | if ((channel != SCAN_WILD_CARD && channel != 0) || | 3208 | if (lun != SCAN_WILD_CARD && lun) |
3168 | (lun != SCAN_WILD_CARD && lun != 0)) | ||
3169 | return -EINVAL; | 3209 | return -EINVAL; |
3170 | 3210 | ||
3211 | if (ap->nr_pmp_links == 0) { | ||
3212 | if (channel != SCAN_WILD_CARD && channel) | ||
3213 | return -EINVAL; | ||
3214 | devno = id; | ||
3215 | } else { | ||
3216 | if (id != SCAN_WILD_CARD && id) | ||
3217 | return -EINVAL; | ||
3218 | devno = channel; | ||
3219 | } | ||
3220 | |||
3171 | spin_lock_irqsave(ap->lock, flags); | 3221 | spin_lock_irqsave(ap->lock, flags); |
3172 | 3222 | ||
3173 | if (id == SCAN_WILD_CARD) { | 3223 | if (devno == SCAN_WILD_CARD) { |
3174 | ehi->probe_mask |= (1 << ata_link_max_devices(&ap->link)) - 1; | 3224 | struct ata_link *link; |
3175 | ehi->action |= ATA_EH_SOFTRESET; | 3225 | |
3226 | ata_port_for_each_link(link, ap) { | ||
3227 | struct ata_eh_info *ehi = &link->eh_info; | ||
3228 | ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1; | ||
3229 | ehi->action |= ATA_EH_SOFTRESET; | ||
3230 | } | ||
3176 | } else { | 3231 | } else { |
3177 | struct ata_device *dev = ata_find_dev(ap, id); | 3232 | struct ata_device *dev = ata_find_dev(ap, devno); |
3178 | 3233 | ||
3179 | if (dev) { | 3234 | if (dev) { |
3235 | struct ata_eh_info *ehi = &dev->link->eh_info; | ||
3180 | ehi->probe_mask |= 1 << dev->devno; | 3236 | ehi->probe_mask |= 1 << dev->devno; |
3181 | ehi->action |= ATA_EH_SOFTRESET; | 3237 | ehi->action |= ATA_EH_SOFTRESET; |
3182 | ehi->flags |= ATA_EHI_RESUME_LINK; | 3238 | ehi->flags |= ATA_EHI_RESUME_LINK; |
@@ -3210,23 +3266,26 @@ void ata_scsi_dev_rescan(struct work_struct *work) | |||
3210 | { | 3266 | { |
3211 | struct ata_port *ap = | 3267 | struct ata_port *ap = |
3212 | container_of(work, struct ata_port, scsi_rescan_task); | 3268 | container_of(work, struct ata_port, scsi_rescan_task); |
3269 | struct ata_link *link; | ||
3213 | struct ata_device *dev; | 3270 | struct ata_device *dev; |
3214 | unsigned long flags; | 3271 | unsigned long flags; |
3215 | 3272 | ||
3216 | spin_lock_irqsave(ap->lock, flags); | 3273 | spin_lock_irqsave(ap->lock, flags); |
3217 | 3274 | ||
3218 | ata_link_for_each_dev(dev, &ap->link) { | 3275 | ata_port_for_each_link(link, ap) { |
3219 | struct scsi_device *sdev = dev->sdev; | 3276 | ata_link_for_each_dev(dev, link) { |
3277 | struct scsi_device *sdev = dev->sdev; | ||
3220 | 3278 | ||
3221 | if (!ata_dev_enabled(dev) || !sdev) | 3279 | if (!ata_dev_enabled(dev) || !sdev) |
3222 | continue; | 3280 | continue; |
3223 | if (scsi_device_get(sdev)) | 3281 | if (scsi_device_get(sdev)) |
3224 | continue; | 3282 | continue; |
3225 | 3283 | ||
3226 | spin_unlock_irqrestore(ap->lock, flags); | 3284 | spin_unlock_irqrestore(ap->lock, flags); |
3227 | scsi_rescan_device(&(sdev->sdev_gendev)); | 3285 | scsi_rescan_device(&(sdev->sdev_gendev)); |
3228 | scsi_device_put(sdev); | 3286 | scsi_device_put(sdev); |
3229 | spin_lock_irqsave(ap->lock, flags); | 3287 | spin_lock_irqsave(ap->lock, flags); |
3288 | } | ||
3230 | } | 3289 | } |
3231 | 3290 | ||
3232 | spin_unlock_irqrestore(ap->lock, flags); | 3291 | spin_unlock_irqrestore(ap->lock, flags); |