libata: separate out ata_host_start()
Separate out ata_host_start() from ata_device_add(). ata_host_start() calls ->port_start on each port if available and freezes the port. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
@@ -5819,11 +5819,14 @@ static void ata_host_release(struct device *gendev, void *res)
|
|||||||
for (i = 0; i < host->n_ports; i++) {
|
for (i = 0; i < host->n_ports; i++) {
|
||||||
struct ata_port *ap = host->ports[i];
|
struct ata_port *ap = host->ports[i];
|
||||||
|
|
||||||
if (ap && ap->ops->port_stop)
|
if (!ap)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop)
|
||||||
ap->ops->port_stop(ap);
|
ap->ops->port_stop(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host->ops->host_stop)
|
if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop)
|
||||||
host->ops->host_stop(host);
|
host->ops->host_stop(host);
|
||||||
|
|
||||||
for (i = 0; i < host->n_ports; i++) {
|
for (i = 0; i < host->n_ports; i++) {
|
||||||
@@ -5842,6 +5845,56 @@ static void ata_host_release(struct device *gendev, void *res)
|
|||||||
dev_set_drvdata(gendev, NULL);
|
dev_set_drvdata(gendev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_host_start - start and freeze ports of an ATA host
|
||||||
|
* @host: ATA host to start ports for
|
||||||
|
*
|
||||||
|
* Start and then freeze ports of @host. Started status is
|
||||||
|
* recorded in host->flags, so this function can be called
|
||||||
|
* multiple times. Ports are guaranteed to get started only
|
||||||
|
* once.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from calling layer (may sleep).
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 if all ports are started successfully, -errno otherwise.
|
||||||
|
*/
|
||||||
|
int ata_host_start(struct ata_host *host)
|
||||||
|
{
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
if (host->flags & ATA_HOST_STARTED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < host->n_ports; i++) {
|
||||||
|
struct ata_port *ap = host->ports[i];
|
||||||
|
|
||||||
|
if (ap->ops->port_start) {
|
||||||
|
rc = ap->ops->port_start(ap);
|
||||||
|
if (rc) {
|
||||||
|
ata_port_printk(ap, KERN_ERR, "failed to "
|
||||||
|
"start port (errno=%d)\n", rc);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ata_eh_freeze_port(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
host->flags |= ATA_HOST_STARTED;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
while (--i >= 0) {
|
||||||
|
struct ata_port *ap = host->ports[i];
|
||||||
|
|
||||||
|
if (ap->ops->port_stop)
|
||||||
|
ap->ops->port_stop(ap);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_sas_host_init - Initialize a host struct
|
* ata_sas_host_init - Initialize a host struct
|
||||||
* @host: host to initialize
|
* @host: host to initialize
|
||||||
@@ -5931,14 +5984,6 @@ int ata_device_add(const struct ata_probe_ent *ent)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start port */
|
|
||||||
rc = ap->ops->port_start(ap);
|
|
||||||
if (rc) {
|
|
||||||
host->ports[i] = NULL;
|
|
||||||
scsi_host_put(ap->scsi_host);
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Report the secondary IRQ for second channel legacy */
|
/* Report the secondary IRQ for second channel legacy */
|
||||||
if (i == 1 && ent->irq2)
|
if (i == 1 && ent->irq2)
|
||||||
irq_line = ent->irq2;
|
irq_line = ent->irq2;
|
||||||
@@ -5956,11 +6001,13 @@ int ata_device_add(const struct ata_probe_ent *ent)
|
|||||||
ap->ioaddr.ctl_addr,
|
ap->ioaddr.ctl_addr,
|
||||||
ap->ioaddr.bmdma_addr,
|
ap->ioaddr.bmdma_addr,
|
||||||
irq_line);
|
irq_line);
|
||||||
|
|
||||||
/* freeze port before requesting IRQ */
|
|
||||||
ata_eh_freeze_port(ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* start ports */
|
||||||
|
rc = ata_host_start(host);
|
||||||
|
if (rc)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
/* obtain irq, that may be shared between channels */
|
/* obtain irq, that may be shared between channels */
|
||||||
rc = devm_request_irq(dev, ent->irq, ent->port_ops->irq_handler,
|
rc = devm_request_irq(dev, ent->irq, ent->port_ops->irq_handler,
|
||||||
ent->irq_flags, DRV_NAME, host);
|
ent->irq_flags, DRV_NAME, host);
|
||||||
@@ -6446,6 +6493,7 @@ EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
|
|||||||
EXPORT_SYMBOL_GPL(ata_std_bios_param);
|
EXPORT_SYMBOL_GPL(ata_std_bios_param);
|
||||||
EXPORT_SYMBOL_GPL(ata_std_ports);
|
EXPORT_SYMBOL_GPL(ata_std_ports);
|
||||||
EXPORT_SYMBOL_GPL(ata_host_init);
|
EXPORT_SYMBOL_GPL(ata_host_init);
|
||||||
|
EXPORT_SYMBOL_GPL(ata_host_start);
|
||||||
EXPORT_SYMBOL_GPL(ata_device_add);
|
EXPORT_SYMBOL_GPL(ata_device_add);
|
||||||
EXPORT_SYMBOL_GPL(ata_host_detach);
|
EXPORT_SYMBOL_GPL(ata_host_detach);
|
||||||
EXPORT_SYMBOL_GPL(ata_sg_init);
|
EXPORT_SYMBOL_GPL(ata_sg_init);
|
||||||
|
@@ -210,6 +210,7 @@ enum {
|
|||||||
|
|
||||||
/* host set flags */
|
/* host set flags */
|
||||||
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */
|
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */
|
||||||
|
ATA_HOST_STARTED = (1 << 1), /* Host started */
|
||||||
|
|
||||||
/* various lengths of time */
|
/* various lengths of time */
|
||||||
ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
|
ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
|
||||||
@@ -732,6 +733,7 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
|
|||||||
#endif
|
#endif
|
||||||
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
|
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
|
||||||
#endif /* CONFIG_PCI */
|
#endif /* CONFIG_PCI */
|
||||||
|
extern int ata_host_start(struct ata_host *host);
|
||||||
extern int ata_device_add(const struct ata_probe_ent *ent);
|
extern int ata_device_add(const struct ata_probe_ent *ent);
|
||||||
extern void ata_host_detach(struct ata_host *host);
|
extern void ata_host_detach(struct ata_host *host);
|
||||||
extern void ata_host_init(struct ata_host *, struct device *,
|
extern void ata_host_init(struct ata_host *, struct device *,
|
||||||
|
Reference in New Issue
Block a user