Commit f3187195 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

libata: separate out ata_host_alloc() and ata_host_register()

Reorganize ata_host_alloc() and its subroutines into the following
three functions.

* ata_host_alloc() : allocates host and its ports.  shost is not
  registered automatically.

* ata_scsi_add_hosts() : allocates and adds shosts associated with an
  ATA host.  Used by ata_host_register().

* ata_host_register() : takes a fully initialized ata_host structure
  and registers it to libata layer and probes it.

Only ata_host_alloc() and ata_host_register() are exported.
ata_device_add() is rewritten using the above functions.  This patch
does not introduce any observable behavior change.  Things worth
mentioning.

* print_id is assigned at registration time and LLDs are allowed to
  overallocate ports and reduce host->n_ports during initialization.
  ata_host_register() will throw away unused ports automatically.

* All SCSI host initialization stuff now resides in
  ata_scsi_add_hosts() in libata-scsi.c, where it should be.

* ipr is now the only user of ata_host_init().  Either kill it by
  converting ipr to use ata_host_alloc() and friends or rename and
  move it to libata-scsi.c
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent ecef7253
This diff is collapsed.
......@@ -104,7 +104,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
* libata transport template. libata doesn't do real transport stuff.
* It just needs the eh_timed_out hook.
*/
struct scsi_transport_template ata_scsi_transport_template = {
static struct scsi_transport_template ata_scsi_transport_template = {
.eh_strategy_handler = ata_scsi_error,
.eh_timed_out = ata_scsi_timed_out,
.user_scan = ata_scsi_user_scan,
......@@ -2961,6 +2961,48 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
}
}
int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
{
int i, rc;
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
struct Scsi_Host *shost;
rc = -ENOMEM;
shost = scsi_host_alloc(sht, sizeof(struct ata_port *));
if (!shost)
goto err_alloc;
*(struct ata_port **)&shost->hostdata[0] = ap;
ap->scsi_host = shost;
shost->transportt = &ata_scsi_transport_template;
shost->unique_id = ap->print_id;
shost->max_id = 16;
shost->max_lun = 1;
shost->max_channel = 1;
shost->max_cmd_len = 16;
rc = scsi_add_host(ap->scsi_host, ap->host->dev);
if (rc)
goto err_add;
}
return 0;
err_add:
scsi_host_put(host->ports[i]->scsi_host);
err_alloc:
while (--i >= 0) {
struct Scsi_Host *shost = host->ports[i]->scsi_host;
scsi_remove_host(shost);
scsi_host_put(shost);
}
return rc;
}
void ata_scsi_scan_host(struct ata_port *ap)
{
unsigned int i;
......@@ -3237,21 +3279,21 @@ struct ata_port *ata_sas_port_alloc(struct ata_host *host,
struct ata_port_info *port_info,
struct Scsi_Host *shost)
{
struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
struct ata_probe_ent *ent;
struct ata_port *ap;
ap = ata_port_alloc(host);
if (!ap)
return NULL;
ent = ata_probe_ent_alloc(host->dev, port_info);
if (!ent) {
kfree(ap);
return NULL;
}
ata_port_init(ap, host, ent, 0);
ap->port_no = 0;
ap->lock = shost->host_lock;
devm_kfree(host->dev, ent);
ap->pio_mask = port_info->pio_mask;
ap->mwdma_mask = port_info->mwdma_mask;
ap->udma_mask = port_info->udma_mask;
ap->flags |= port_info->flags;
ap->ops = port_info->port_ops;
ap->cbl = ATA_CBL_SATA;
return ap;
}
EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
......@@ -3307,8 +3349,10 @@ int ata_sas_port_init(struct ata_port *ap)
{
int rc = ap->ops->port_start(ap);
if (!rc)
if (!rc) {
ap->print_id = ata_print_id++;
rc = ata_bus_probe(ap);
}
return rc;
}
......
......@@ -52,6 +52,7 @@ enum {
ATA_DNXFER_QUIET = (1 << 31),
};
extern unsigned int ata_print_id;
extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled;
extern int atapi_dmadir;
......@@ -92,10 +93,9 @@ extern int ata_flush_cache(struct ata_device *dev);
extern void ata_dev_init(struct ata_device *dev);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern void ata_port_init(struct ata_port *ap, struct ata_host *host,
const struct ata_probe_ent *ent, unsigned int port_no);
extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
const struct ata_port_info *port);
extern struct ata_port *ata_port_alloc(struct ata_host *host);
/* libata-acpi.c */
#ifdef CONFIG_SATA_ACPI
......@@ -113,8 +113,8 @@ static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
#endif
/* libata-scsi.c */
extern struct scsi_transport_template ata_scsi_transport_template;
extern int ata_scsi_add_hosts(struct ata_host *host,
struct scsi_host_template *sht);
extern void ata_scsi_scan_host(struct ata_port *ap);
extern int ata_scsi_offline_dev(struct ata_device *dev);
extern void ata_scsi_hotplug(struct work_struct *work);
......
......@@ -733,7 +733,10 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
#endif
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
extern int ata_host_start(struct ata_host *host);
extern int ata_host_register(struct ata_host *host,
struct scsi_host_template *sht);
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_detach(struct ata_host *host);
extern void ata_host_init(struct ata_host *, struct device *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment