diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-22 13:41:41 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-22 13:41:41 -0800 |
| commit | 8762069330316392331e693befd8a5b632833618 (patch) | |
| tree | 26716f1064b9b0b376d4bf77604cdcdc600efdb2 /drivers/scsi/libsas/sas_ata.c | |
| parent | Merge tag 'ata-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlem... (diff) | |
| parent | scsi: ufs: core: Fix an error handling path in ufshcd_read_desc_param() (diff) | |
| download | linux-8762069330316392331e693befd8a5b632833618.tar.gz linux-8762069330316392331e693befd8a5b632833618.zip | |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"Updates to the usual drivers (ufs, lpfc, qla2xxx, libsas).
The major core change is a rework to remove the two helpers around
scsi_execute_cmd and use it as the only submission interface along
with other minor fixes and updates"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (142 commits)
scsi: ufs: core: Fix an error handling path in ufshcd_read_desc_param()
scsi: ufs: core: Fix device management cmd timeout flow
scsi: aic94xx: Add missing check for dma_map_single()
scsi: smartpqi: Replace one-element array with flexible-array member
scsi: mpt3sas: Fix a memory leak
scsi: qla2xxx: Remove the unused variable wwn
scsi: ufs: core: Fix kernel-doc syntax
scsi: ufs: core: Add hibernation callbacks
scsi: snic: Fix memory leak with using debugfs_lookup()
scsi: ufs: core: Limit DMA alignment check
scsi: Documentation: Correct spelling
scsi: Documentation: Correct spelling
scsi: target: Documentation: Correct spelling
scsi: aacraid: Allocate cmd_priv with scsicmd
scsi: ufs: qcom: dt-bindings: Add SM8550 compatible string
scsi: ufs: ufs-qcom: Clear qunipro_g4_sel for HW version major 5
scsi: ufs: qcom: fix platform_msi_domain_free_irqs() reference
scsi: ufs: core: Enable DMA clustering
scsi: ufs: exynos: Fix the maximum segment size
scsi: ufs: exynos: Fix DMA alignment for PAGE_SIZE != 4096
...
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
| -rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 88 |
1 files changed, 73 insertions, 15 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 12d9bdd11a4c..77714a495cbb 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -238,7 +238,17 @@ static struct sas_internal *dev_to_sas_internal(struct domain_device *dev) return to_sas_internal(dev->port->ha->core.shost->transportt); } -static int sas_get_ata_command_set(struct domain_device *dev); +static int sas_get_ata_command_set(struct domain_device *dev) +{ + struct ata_taskfile tf; + + if (dev->dev_type == SAS_SATA_PENDING) + return ATA_DEV_UNKNOWN; + + ata_tf_from_fis(dev->frame_rcvd, &tf); + + return ata_dev_classify(&tf); +} int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy) { @@ -636,20 +646,6 @@ void sas_ata_task_abort(struct sas_task *task) complete(waiting); } -static int sas_get_ata_command_set(struct domain_device *dev) -{ - struct dev_to_host_fis *fis = - (struct dev_to_host_fis *) dev->frame_rcvd; - struct ata_taskfile tf; - - if (dev->dev_type == SAS_SATA_PENDING) - return ATA_DEV_UNKNOWN; - - ata_tf_from_fis((const u8 *)fis, &tf); - - return ata_dev_classify(&tf); -} - void sas_probe_sata(struct asd_sas_port *port) { struct domain_device *dev, *n; @@ -678,6 +674,68 @@ void sas_probe_sata(struct asd_sas_port *port) } +int sas_ata_add_dev(struct domain_device *parent, struct ex_phy *phy, + struct domain_device *child, int phy_id) +{ + struct sas_rphy *rphy; + int ret; + + if (child->linkrate > parent->min_linkrate) { + struct sas_phy *cphy = child->phy; + enum sas_linkrate min_prate = cphy->minimum_linkrate, + parent_min_lrate = parent->min_linkrate, + min_linkrate = (min_prate > parent_min_lrate) ? + parent_min_lrate : 0; + struct sas_phy_linkrates rates = { + .maximum_linkrate = parent->min_linkrate, + .minimum_linkrate = min_linkrate, + }; + + pr_notice("ex %016llx phy%02d SATA device linkrate > min pathway connection rate, attempting to lower device linkrate\n", + SAS_ADDR(child->sas_addr), phy_id); + ret = sas_smp_phy_control(parent, phy_id, + PHY_FUNC_LINK_RESET, &rates); + if (ret) { + pr_err("ex %016llx phy%02d SATA device could not set linkrate (%d)\n", + SAS_ADDR(child->sas_addr), phy_id, ret); + return ret; + } + pr_notice("ex %016llx phy%02d SATA device set linkrate successfully\n", + SAS_ADDR(child->sas_addr), phy_id); + child->linkrate = child->min_linkrate; + } + ret = sas_get_ata_info(child, phy); + if (ret) + return ret; + + sas_init_dev(child); + ret = sas_ata_init(child); + if (ret) + return ret; + + rphy = sas_end_device_alloc(phy->port); + if (!rphy) + return -ENOMEM; + + rphy->identify.phy_identifier = phy_id; + child->rphy = rphy; + get_device(&rphy->dev); + + list_add_tail(&child->disco_list_node, &parent->port->disco_list); + + ret = sas_discover_sata(child); + if (ret) { + pr_notice("sas_discover_sata() for device %16llx at %016llx:%02d returned 0x%x\n", + SAS_ADDR(child->sas_addr), + SAS_ADDR(parent->sas_addr), phy_id, ret); + sas_rphy_free(child->rphy); + list_del(&child->disco_list_node); + return ret; + } + + return 0; +} + static void sas_ata_flush_pm_eh(struct asd_sas_port *port, const char *func) { struct domain_device *dev, *n; |
