diff options
| -rw-r--r-- | drivers/ata/libata-scsi.c | 35 | ||||
| -rw-r--r-- | drivers/scsi/ipr.c | 6 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 33 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 13 | ||||
| -rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 8 | ||||
| -rw-r--r-- | include/linux/libata.h | 3 | ||||
| -rw-r--r-- | include/scsi/sas_ata.h | 4 |
7 files changed, 54 insertions, 48 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7832b1ad2327..22226350cd0c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -3839,18 +3839,25 @@ void ata_sas_port_stop(struct ata_port *ap) | |||
| 3839 | } | 3839 | } |
| 3840 | EXPORT_SYMBOL_GPL(ata_sas_port_stop); | 3840 | EXPORT_SYMBOL_GPL(ata_sas_port_stop); |
| 3841 | 3841 | ||
| 3842 | int ata_sas_async_port_init(struct ata_port *ap) | 3842 | /** |
| 3843 | * ata_sas_async_probe - simply schedule probing and return | ||
| 3844 | * @ap: Port to probe | ||
| 3845 | * | ||
| 3846 | * For batch scheduling of probe for sas attached ata devices, assumes | ||
| 3847 | * the port has already been through ata_sas_port_init() | ||
| 3848 | */ | ||
| 3849 | void ata_sas_async_probe(struct ata_port *ap) | ||
| 3843 | { | 3850 | { |
| 3844 | int rc = ap->ops->port_start(ap); | 3851 | __ata_port_probe(ap); |
| 3845 | 3852 | } | |
| 3846 | if (!rc) { | 3853 | EXPORT_SYMBOL_GPL(ata_sas_async_probe); |
| 3847 | ap->print_id = atomic_inc_return(&ata_print_id); | ||
| 3848 | __ata_port_probe(ap); | ||
| 3849 | } | ||
| 3850 | 3854 | ||
| 3851 | return rc; | 3855 | int ata_sas_sync_probe(struct ata_port *ap) |
| 3856 | { | ||
| 3857 | return ata_port_probe(ap); | ||
| 3852 | } | 3858 | } |
| 3853 | EXPORT_SYMBOL_GPL(ata_sas_async_port_init); | 3859 | EXPORT_SYMBOL_GPL(ata_sas_sync_probe); |
| 3860 | |||
| 3854 | 3861 | ||
| 3855 | /** | 3862 | /** |
| 3856 | * ata_sas_port_init - Initialize a SATA device | 3863 | * ata_sas_port_init - Initialize a SATA device |
| @@ -3867,12 +3874,10 @@ int ata_sas_port_init(struct ata_port *ap) | |||
| 3867 | { | 3874 | { |
| 3868 | int rc = ap->ops->port_start(ap); | 3875 | int rc = ap->ops->port_start(ap); |
| 3869 | 3876 | ||
| 3870 | if (!rc) { | 3877 | if (rc) |
| 3871 | ap->print_id = atomic_inc_return(&ata_print_id); | 3878 | return rc; |
| 3872 | rc = ata_port_probe(ap); | 3879 | ap->print_id = atomic_inc_return(&ata_print_id); |
| 3873 | } | 3880 | return 0; |
| 3874 | |||
| 3875 | return rc; | ||
| 3876 | } | 3881 | } |
| 3877 | EXPORT_SYMBOL_GPL(ata_sas_port_init); | 3882 | EXPORT_SYMBOL_GPL(ata_sas_port_init); |
| 3878 | 3883 | ||
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e002cd466e9a..467dc38246f9 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -4549,8 +4549,12 @@ static int ipr_ata_slave_alloc(struct scsi_device *sdev) | |||
| 4549 | ENTER; | 4549 | ENTER; |
| 4550 | if (sdev->sdev_target) | 4550 | if (sdev->sdev_target) |
| 4551 | sata_port = sdev->sdev_target->hostdata; | 4551 | sata_port = sdev->sdev_target->hostdata; |
| 4552 | if (sata_port) | 4552 | if (sata_port) { |
| 4553 | rc = ata_sas_port_init(sata_port->ap); | 4553 | rc = ata_sas_port_init(sata_port->ap); |
| 4554 | if (rc == 0) | ||
| 4555 | rc = ata_sas_sync_probe(sata_port->ap); | ||
| 4556 | } | ||
| 4557 | |||
| 4554 | if (rc) | 4558 | if (rc) |
| 4555 | ipr_slave_destroy(sdev); | 4559 | ipr_slave_destroy(sdev); |
| 4556 | 4560 | ||
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index bc0cecc6ad62..441d88ad99a7 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 = { | |||
| 546 | .port_ops = &sas_sata_ops | 546 | .port_ops = &sas_sata_ops |
| 547 | }; | 547 | }; |
| 548 | 548 | ||
| 549 | int sas_ata_init_host_and_port(struct domain_device *found_dev) | 549 | int sas_ata_init(struct domain_device *found_dev) |
| 550 | { | 550 | { |
| 551 | struct sas_ha_struct *ha = found_dev->port->ha; | 551 | struct sas_ha_struct *ha = found_dev->port->ha; |
| 552 | struct Scsi_Host *shost = ha->core.shost; | 552 | struct Scsi_Host *shost = ha->core.shost; |
| 553 | struct ata_port *ap; | 553 | struct ata_port *ap; |
| 554 | int rc; | ||
| 554 | 555 | ||
| 555 | ata_host_init(&found_dev->sata_dev.ata_host, | 556 | ata_host_init(&found_dev->sata_dev.ata_host, |
| 556 | ha->dev, | 557 | ha->dev, |
| @@ -567,8 +568,11 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev) | |||
| 567 | ap->private_data = found_dev; | 568 | ap->private_data = found_dev; |
| 568 | ap->cbl = ATA_CBL_SATA; | 569 | ap->cbl = ATA_CBL_SATA; |
| 569 | ap->scsi_host = shost; | 570 | ap->scsi_host = shost; |
| 570 | /* publish initialized ata port */ | 571 | rc = ata_sas_port_init(ap); |
| 571 | smp_wmb(); | 572 | if (rc) { |
| 573 | ata_sas_port_destroy(ap); | ||
| 574 | return rc; | ||
| 575 | } | ||
| 572 | found_dev->sata_dev.ap = ap; | 576 | found_dev->sata_dev.ap = ap; |
| 573 | 577 | ||
| 574 | return 0; | 578 | return 0; |
| @@ -648,18 +652,13 @@ static void sas_get_ata_command_set(struct domain_device *dev) | |||
| 648 | void sas_probe_sata(struct asd_sas_port *port) | 652 | void sas_probe_sata(struct asd_sas_port *port) |
| 649 | { | 653 | { |
| 650 | struct domain_device *dev, *n; | 654 | struct domain_device *dev, *n; |
| 651 | int err; | ||
| 652 | 655 | ||
| 653 | mutex_lock(&port->ha->disco_mutex); | 656 | mutex_lock(&port->ha->disco_mutex); |
| 654 | list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) { | 657 | list_for_each_entry(dev, &port->disco_list, disco_list_node) { |
| 655 | if (!dev_is_sata(dev)) | 658 | if (!dev_is_sata(dev)) |
| 656 | continue; | 659 | continue; |
| 657 | 660 | ||
| 658 | err = sas_ata_init_host_and_port(dev); | 661 | ata_sas_async_probe(dev->sata_dev.ap); |
| 659 | if (err) | ||
| 660 | sas_fail_probe(dev, __func__, err); | ||
| 661 | else | ||
| 662 | ata_sas_async_port_init(dev->sata_dev.ap); | ||
| 663 | } | 662 | } |
| 664 | mutex_unlock(&port->ha->disco_mutex); | 663 | mutex_unlock(&port->ha->disco_mutex); |
| 665 | 664 | ||
| @@ -718,18 +717,6 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie) | |||
| 718 | sas_put_device(dev); | 717 | sas_put_device(dev); |
| 719 | } | 718 | } |
| 720 | 719 | ||
| 721 | static bool sas_ata_dev_eh_valid(struct domain_device *dev) | ||
| 722 | { | ||
| 723 | struct ata_port *ap; | ||
| 724 | |||
| 725 | if (!dev_is_sata(dev)) | ||
| 726 | return false; | ||
| 727 | ap = dev->sata_dev.ap; | ||
| 728 | /* consume fully initialized ata ports */ | ||
| 729 | smp_rmb(); | ||
| 730 | return !!ap; | ||
| 731 | } | ||
| 732 | |||
| 733 | void sas_ata_strategy_handler(struct Scsi_Host *shost) | 720 | void sas_ata_strategy_handler(struct Scsi_Host *shost) |
| 734 | { | 721 | { |
| 735 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); | 722 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); |
| @@ -753,7 +740,7 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost) | |||
| 753 | 740 | ||
| 754 | spin_lock(&port->dev_list_lock); | 741 | spin_lock(&port->dev_list_lock); |
| 755 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { | 742 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { |
| 756 | if (!sas_ata_dev_eh_valid(dev)) | 743 | if (!dev_is_sata(dev)) |
| 757 | continue; | 744 | continue; |
| 758 | async_schedule_domain(async_sas_ata_eh, dev, &async); | 745 | async_schedule_domain(async_sas_ata_eh, dev, &async); |
| 759 | } | 746 | } |
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 13b5891f9961..629a0865b130 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
| @@ -72,6 +72,7 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 72 | struct asd_sas_phy *phy; | 72 | struct asd_sas_phy *phy; |
| 73 | struct sas_rphy *rphy; | 73 | struct sas_rphy *rphy; |
| 74 | struct domain_device *dev; | 74 | struct domain_device *dev; |
| 75 | int rc = -ENODEV; | ||
| 75 | 76 | ||
| 76 | dev = sas_alloc_device(); | 77 | dev = sas_alloc_device(); |
| 77 | if (!dev) | 78 | if (!dev) |
| @@ -110,9 +111,16 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 110 | 111 | ||
| 111 | sas_init_dev(dev); | 112 | sas_init_dev(dev); |
| 112 | 113 | ||
| 114 | dev->port = port; | ||
| 113 | switch (dev->dev_type) { | 115 | switch (dev->dev_type) { |
| 114 | case SAS_END_DEV: | ||
| 115 | case SATA_DEV: | 116 | case SATA_DEV: |
| 117 | rc = sas_ata_init(dev); | ||
| 118 | if (rc) { | ||
| 119 | rphy = NULL; | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | /* fall through */ | ||
| 123 | case SAS_END_DEV: | ||
| 116 | rphy = sas_end_device_alloc(port->port); | 124 | rphy = sas_end_device_alloc(port->port); |
| 117 | break; | 125 | break; |
| 118 | case EDGE_DEV: | 126 | case EDGE_DEV: |
| @@ -131,7 +139,7 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 131 | 139 | ||
| 132 | if (!rphy) { | 140 | if (!rphy) { |
| 133 | sas_put_device(dev); | 141 | sas_put_device(dev); |
| 134 | return -ENODEV; | 142 | return rc; |
| 135 | } | 143 | } |
| 136 | 144 | ||
| 137 | rphy->identify.phy_identifier = phy->phy->identify.phy_identifier; | 145 | rphy->identify.phy_identifier = phy->phy->identify.phy_identifier; |
| @@ -139,7 +147,6 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 139 | sas_fill_in_rphy(dev, rphy); | 147 | sas_fill_in_rphy(dev, rphy); |
| 140 | sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | 148 | sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); |
| 141 | port->port_dev = dev; | 149 | port->port_dev = dev; |
| 142 | dev->port = port; | ||
| 143 | dev->linkrate = port->linkrate; | 150 | dev->linkrate = port->linkrate; |
| 144 | dev->min_linkrate = port->linkrate; | 151 | dev->min_linkrate = port->linkrate; |
| 145 | dev->max_linkrate = port->linkrate; | 152 | dev->max_linkrate = port->linkrate; |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index c1f91b1c27c3..75247a176c6b 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -790,12 +790,14 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
| 790 | if (res) | 790 | if (res) |
| 791 | goto out_free; | 791 | goto out_free; |
| 792 | 792 | ||
| 793 | sas_init_dev(child); | ||
| 794 | res = sas_ata_init(child); | ||
| 795 | if (res) | ||
| 796 | goto out_free; | ||
| 793 | rphy = sas_end_device_alloc(phy->port); | 797 | rphy = sas_end_device_alloc(phy->port); |
| 794 | if (unlikely(!rphy)) | 798 | if (!rphy) |
| 795 | goto out_free; | 799 | goto out_free; |
| 796 | 800 | ||
| 797 | sas_init_dev(child); | ||
| 798 | |||
| 799 | child->rphy = rphy; | 801 | child->rphy = rphy; |
| 800 | get_device(&rphy->dev); | 802 | get_device(&rphy->dev); |
| 801 | 803 | ||
diff --git a/include/linux/libata.h b/include/linux/libata.h index 42378d637ffb..e926df7b54c9 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -996,7 +996,8 @@ extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev, | |||
| 996 | extern void ata_sas_port_destroy(struct ata_port *); | 996 | extern void ata_sas_port_destroy(struct ata_port *); |
| 997 | extern struct ata_port *ata_sas_port_alloc(struct ata_host *, | 997 | extern struct ata_port *ata_sas_port_alloc(struct ata_host *, |
| 998 | struct ata_port_info *, struct Scsi_Host *); | 998 | struct ata_port_info *, struct Scsi_Host *); |
| 999 | extern int ata_sas_async_port_init(struct ata_port *); | 999 | extern void ata_sas_async_probe(struct ata_port *ap); |
| 1000 | extern int ata_sas_sync_probe(struct ata_port *ap); | ||
| 1000 | extern int ata_sas_port_init(struct ata_port *); | 1001 | extern int ata_sas_port_init(struct ata_port *); |
| 1001 | extern int ata_sas_port_start(struct ata_port *ap); | 1002 | extern int ata_sas_port_start(struct ata_port *ap); |
| 1002 | extern void ata_sas_port_stop(struct ata_port *ap); | 1003 | extern void ata_sas_port_stop(struct ata_port *ap); |
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h index cdccd2eb7b6c..77670e823ed8 100644 --- a/include/scsi/sas_ata.h +++ b/include/scsi/sas_ata.h | |||
| @@ -37,7 +37,7 @@ static inline int dev_is_sata(struct domain_device *dev) | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy); | 39 | int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy); |
| 40 | int sas_ata_init_host_and_port(struct domain_device *found_dev); | 40 | int sas_ata_init(struct domain_device *dev); |
| 41 | void sas_ata_task_abort(struct sas_task *task); | 41 | void sas_ata_task_abort(struct sas_task *task); |
| 42 | void sas_ata_strategy_handler(struct Scsi_Host *shost); | 42 | void sas_ata_strategy_handler(struct Scsi_Host *shost); |
| 43 | void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, | 43 | void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, |
| @@ -52,7 +52,7 @@ static inline int dev_is_sata(struct domain_device *dev) | |||
| 52 | { | 52 | { |
| 53 | return 0; | 53 | return 0; |
| 54 | } | 54 | } |
| 55 | static inline int sas_ata_init_host_and_port(struct domain_device *found_dev) | 55 | static inline int sas_ata_init(struct domain_device *dev) |
| 56 | { | 56 | { |
| 57 | return 0; | 57 | return 0; |
| 58 | } | 58 | } |
