From b2024459252a9d2d312ee562f86f332a1498f412 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 21 Mar 2012 21:09:07 -0700 Subject: [SCSI] libsas, libata: fix start of life for a sas ata_port This changes the ordering of initialization and probing events from: 1/ allocate rphy in PORTE_BYTES_DMAED, DISCE_REVALIDATE_DOMAIN 2/ allocate ata_port and schedule port probe in DISCE_PROBE ...to: 1/ allocate ata_port in PORTE_BYTES_DMAED, DISCE_REVALIDATE_DOMAIN 2/ allocate rphy in PORTE_BYTES_DMAED, DISCE_REVALIDATE_DOMAIN 3/ schedule port probe in DISCE_PROBE This ordering prevents PHYE_SIGNAL_LOSS_EVENTS from sneaking in to destrory ata devices before they have been fully initialized: BUG: unable to handle kernel paging request at 0000000000003b10 IP: [] sas_ata_end_eh+0x12/0x5e [libsas] ... [] sas_unregister_common_dev+0x78/0xc9 [libsas] [] sas_unregister_dev+0x4f/0xad [libsas] [] sas_unregister_domain_devices+0x7f/0xbf [libsas] [] sas_deform_port+0x61/0x1b8 [libsas] [] sas_phye_loss_of_signal+0x29/0x2b [libsas] ...and kills the awkward "sata domain_device briefly existing in the domain without an ata_port" state. Reported-by: Michal Kosciowski Signed-off-by: Dan Williams Acked-by: Jeff Garzik Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_ata.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'drivers/scsi/libsas/sas_ata.c') diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index bc0cecc6ad6..441d88ad99a 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -546,11 +546,12 @@ static struct ata_port_info sata_port_info = { .port_ops = &sas_sata_ops }; -int sas_ata_init_host_and_port(struct domain_device *found_dev) +int sas_ata_init(struct domain_device *found_dev) { struct sas_ha_struct *ha = found_dev->port->ha; struct Scsi_Host *shost = ha->core.shost; struct ata_port *ap; + int rc; ata_host_init(&found_dev->sata_dev.ata_host, ha->dev, @@ -567,8 +568,11 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev) ap->private_data = found_dev; ap->cbl = ATA_CBL_SATA; ap->scsi_host = shost; - /* publish initialized ata port */ - smp_wmb(); + rc = ata_sas_port_init(ap); + if (rc) { + ata_sas_port_destroy(ap); + return rc; + } found_dev->sata_dev.ap = ap; return 0; @@ -648,18 +652,13 @@ static void sas_get_ata_command_set(struct domain_device *dev) void sas_probe_sata(struct asd_sas_port *port) { struct domain_device *dev, *n; - int err; mutex_lock(&port->ha->disco_mutex); - list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) { + list_for_each_entry(dev, &port->disco_list, disco_list_node) { if (!dev_is_sata(dev)) continue; - err = sas_ata_init_host_and_port(dev); - if (err) - sas_fail_probe(dev, __func__, err); - else - ata_sas_async_port_init(dev->sata_dev.ap); + ata_sas_async_probe(dev->sata_dev.ap); } mutex_unlock(&port->ha->disco_mutex); @@ -718,18 +717,6 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie) sas_put_device(dev); } -static bool sas_ata_dev_eh_valid(struct domain_device *dev) -{ - struct ata_port *ap; - - if (!dev_is_sata(dev)) - return false; - ap = dev->sata_dev.ap; - /* consume fully initialized ata ports */ - smp_rmb(); - return !!ap; -} - void sas_ata_strategy_handler(struct Scsi_Host *shost) { struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); @@ -753,7 +740,7 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost) spin_lock(&port->dev_list_lock); list_for_each_entry(dev, &port->dev_list, dev_list_node) { - if (!sas_ata_dev_eh_valid(dev)) + if (!dev_is_sata(dev)) continue; async_schedule_domain(async_sas_ata_eh, dev, &async); } -- cgit v1.2.3-70-g09d2