Message ID | 20230923002932.1082348-3-dlemoal@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Fix libata suspend/resume handling and code cleanup | expand |
On 9/22/23 17:29, Damien Le Moal wrote: > Also delete the WAR_ON() call checking that the ATA_PFLAG_UNLOADING flag > was cleared as that is done without holding the port lock. Hmm ... I don't see any WARN_ON() statement being removed by this patch? > - /* tell EH we're leaving & flush EH */ > + /* Wait for any ongoing EH */ > + ata_port_wait_eh(ap); > + > + mutex_lock(&ap->scsi_scan_mutex); > spin_lock_irqsave(ap->lock, flags); > + > + /* Remove scsi devices */ > + ata_for_each_link(link, ap, HOST_FIRST) { > + ata_for_each_dev(dev, link, ALL) { > + if (dev->sdev) { > + spin_unlock_irqrestore(ap->lock, flags); > + scsi_remove_device(dev->sdev); > + spin_lock_irqsave(ap->lock, flags); > + dev->sdev = NULL; > + } > + } > + } Can the lists ata_for_each_link() and ata_for_each_dev() iterate over change while ap->lock is unlocked? If not, does this perhaps have to be explained in a comment? If these lists can be changed, should these lists perhaps be examined from the start after every unlock of ap->lock? Thanks, Bart.
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 732f3d0b4fd9..8e35afe5e560 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5948,11 +5948,30 @@ static void ata_port_detach(struct ata_port *ap) struct ata_link *link; struct ata_device *dev; - /* tell EH we're leaving & flush EH */ + /* Wait for any ongoing EH */ + ata_port_wait_eh(ap); + + mutex_lock(&ap->scsi_scan_mutex); spin_lock_irqsave(ap->lock, flags); + + /* Remove scsi devices */ + ata_for_each_link(link, ap, HOST_FIRST) { + ata_for_each_dev(dev, link, ALL) { + if (dev->sdev) { + spin_unlock_irqrestore(ap->lock, flags); + scsi_remove_device(dev->sdev); + spin_lock_irqsave(ap->lock, flags); + dev->sdev = NULL; + } + } + } + + /* Tell EH to disable all devices */ ap->pflags |= ATA_PFLAG_UNLOADING; ata_port_schedule_eh(ap); + spin_unlock_irqrestore(ap->lock, flags); + mutex_unlock(&ap->scsi_scan_mutex); /* wait till EH commits suicide */ ata_port_wait_eh(ap);