diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-08 10:12:46 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-08 10:12:46 -0700 |
commit | d1cd7c85f9e29740fddec6f25d8bf061937bf58d (patch) | |
tree | 6d1f8e555d3a416442856724b57dc414eac5d5a4 /drivers/scsi/libsas/sas_expander.c | |
parent | b3a5e648f5917ea508ecab9a629028b186d38eae (diff) | |
parent | d4023db71108375e4194e92730ba0d32d7f07813 (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This is mostly update of the usual drivers: qla2xxx, qedf, smartpqi,
hpsa, lpfc, ufs, mpt3sas, ibmvfc and hisi_sas. Plus number of minor
changes, spelling fixes and other trivia"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (298 commits)
scsi: qla2xxx: Avoid that lockdep complains about unsafe locking in tcm_qla2xxx_close_session()
scsi: qla2xxx: Avoid that qlt_send_resp_ctio() corrupts memory
scsi: qla2xxx: Fix hardirq-unsafe locking
scsi: qla2xxx: Complain loudly about reference count underflow
scsi: qla2xxx: Use __le64 instead of uint32_t[2] for sending DMA addresses to firmware
scsi: qla2xxx: Introduce the dsd32 and dsd64 data structures
scsi: qla2xxx: Check the size of firmware data structures at compile time
scsi: qla2xxx: Pass little-endian values to the firmware
scsi: qla2xxx: Fix race conditions in the code for aborting SCSI commands
scsi: qla2xxx: Use an on-stack completion in qla24xx_control_vp()
scsi: qla2xxx: Make qla24xx_async_abort_cmd() static
scsi: qla2xxx: Remove unnecessary locking from the target code
scsi: qla2xxx: Remove qla_tgt_cmd.released
scsi: qla2xxx: Complain if a command is released that is owned by the firmware
scsi: qla2xxx: target: Fix offline port handling and host reset handling
scsi: qla2xxx: Fix abort handling in tcm_qla2xxx_write_pending()
scsi: qla2xxx: Fix error handling in qlt_alloc_qfull_cmd()
scsi: qla2xxx: Simplify qlt_send_term_imm_notif()
scsi: qla2xxx: Fix use-after-free issues in qla2xxx_qpair_sp_free_dma()
scsi: qla2xxx: Fix a qla24xx_enable_msix() error path
...
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 83 |
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 17b45a0c7bc3..83f2fd70ce76 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -826,9 +826,14 @@ static struct domain_device *sas_ex_discover_end_dev( #ifdef CONFIG_SCSI_SAS_ATA if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) { 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 = parent->min_linkrate, + .minimum_linkrate = min_linkrate, }; int ret; @@ -865,7 +870,7 @@ static struct domain_device *sas_ex_discover_end_dev( res = sas_discover_sata(child); if (res) { - pr_notice("sas_discover_sata() for device %16llx at %016llx:0x%x returned 0x%x\n", + 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, res); goto out_list_del; @@ -890,7 +895,7 @@ static struct domain_device *sas_ex_discover_end_dev( res = sas_discover_end_dev(child); if (res) { - pr_notice("sas_discover_end_dev() for device %16llx at %016llx:0x%x returned 0x%x\n", + pr_notice("sas_discover_end_dev() for device %16llx at %016llx:%02d returned 0x%x\n", SAS_ADDR(child->sas_addr), SAS_ADDR(parent->sas_addr), phy_id, res); goto out_list_del; @@ -955,7 +960,7 @@ static struct domain_device *sas_ex_discover_expander( int res; if (phy->routing_attr == DIRECT_ROUTING) { - pr_warn("ex %016llx:0x%x:D <--> ex %016llx:0x%x is not allowed\n", + pr_warn("ex %016llx:%02d:D <--> ex %016llx:0x%x is not allowed\n", SAS_ADDR(parent->sas_addr), phy_id, SAS_ADDR(phy->attached_sas_addr), phy->attached_phy_id); @@ -1065,7 +1070,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE && ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE && ex_phy->attached_dev_type != SAS_SATA_PENDING) { - pr_warn("unknown device type(0x%x) attached to ex %016llx phy 0x%x\n", + pr_warn("unknown device type(0x%x) attached to ex %016llx phy%02d\n", ex_phy->attached_dev_type, SAS_ADDR(dev->sas_addr), phy_id); @@ -1081,7 +1086,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) } if (sas_ex_join_wide_port(dev, phy_id)) { - pr_debug("Attaching ex phy%d to wide port %016llx\n", + pr_debug("Attaching ex phy%02d to wide port %016llx\n", phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); return res; } @@ -1093,7 +1098,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) break; case SAS_FANOUT_EXPANDER_DEVICE: if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) { - pr_debug("second fanout expander %016llx phy 0x%x attached to ex %016llx phy 0x%x\n", + pr_debug("second fanout expander %016llx phy%02d attached to ex %016llx phy%02d\n", SAS_ADDR(ex_phy->attached_sas_addr), ex_phy->attached_phy_id, SAS_ADDR(dev->sas_addr), @@ -1126,7 +1131,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) SAS_ADDR(child->sas_addr)) { ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; if (sas_ex_join_wide_port(dev, i)) - pr_debug("Attaching ex phy%d to wide port %016llx\n", + pr_debug("Attaching ex phy%02d to wide port %016llx\n", i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); } } @@ -1151,7 +1156,7 @@ static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr) phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) && phy->routing_attr == SUBTRACTIVE_ROUTING) { - memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE); + memcpy(sub_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); return 1; } @@ -1163,7 +1168,7 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev) { struct expander_device *ex = &dev->ex_dev; struct domain_device *child; - u8 sub_addr[8] = {0, }; + u8 sub_addr[SAS_ADDR_SIZE] = {0, }; list_for_each_entry(child, &ex->children, siblings) { if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE && @@ -1173,7 +1178,7 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev) sas_find_sub_addr(child, sub_addr); continue; } else { - u8 s2[8]; + u8 s2[SAS_ADDR_SIZE]; if (sas_find_sub_addr(child, s2) && (SAS_ADDR(sub_addr) != SAS_ADDR(s2))) { @@ -1261,7 +1266,7 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev) else if (SAS_ADDR(sub_sas_addr) != SAS_ADDR(phy->attached_sas_addr)) { - pr_notice("ex %016llx phy 0x%x diverges(%016llx) on subtractive boundary(%016llx). Disabled\n", + pr_notice("ex %016llx phy%02d diverges(%016llx) on subtractive boundary(%016llx). Disabled\n", SAS_ADDR(dev->sas_addr), i, SAS_ADDR(phy->attached_sas_addr), SAS_ADDR(sub_sas_addr)); @@ -1282,7 +1287,7 @@ static void sas_print_parent_topology_bug(struct domain_device *child, }; struct domain_device *parent = child->parent; - pr_notice("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x has %c:%c routing link!\n", + pr_notice("%s ex %016llx phy%02d <--> %s ex %016llx phy%02d has %c:%c routing link!\n", ex_type[parent->dev_type], SAS_ADDR(parent->sas_addr), parent_phy->phy_id, @@ -1304,7 +1309,7 @@ static int sas_check_eeds(struct domain_device *child, if (SAS_ADDR(parent->port->disc.fanout_sas_addr) != 0) { res = -ENODEV; - pr_warn("edge ex %016llx phy S:0x%x <--> edge ex %016llx phy S:0x%x, while there is a fanout ex %016llx\n", + pr_warn("edge ex %016llx phy S:%02d <--> edge ex %016llx phy S:%02d, while there is a fanout ex %016llx\n", SAS_ADDR(parent->sas_addr), parent_phy->phy_id, SAS_ADDR(child->sas_addr), @@ -1327,7 +1332,7 @@ static int sas_check_eeds(struct domain_device *child, ; else { res = -ENODEV; - pr_warn("edge ex %016llx phy 0x%x <--> edge ex %016llx phy 0x%x link forms a third EEDS!\n", + pr_warn("edge ex %016llx phy%02d <--> edge ex %016llx phy%02d link forms a third EEDS!\n", SAS_ADDR(parent->sas_addr), parent_phy->phy_id, SAS_ADDR(child->sas_addr), @@ -1445,11 +1450,11 @@ static int sas_configure_present(struct domain_device *dev, int phy_id, goto out; res = rri_resp[2]; if (res == SMP_RESP_NO_INDEX) { - pr_warn("overflow of indexes: dev %016llx phy 0x%x index 0x%x\n", + pr_warn("overflow of indexes: dev %016llx phy%02d index 0x%x\n", SAS_ADDR(dev->sas_addr), phy_id, i); goto out; } else if (res != SMP_RESP_FUNC_ACC) { - pr_notice("%s: dev %016llx phy 0x%x index 0x%x result 0x%x\n", + pr_notice("%s: dev %016llx phy%02d index 0x%x result 0x%x\n", __func__, SAS_ADDR(dev->sas_addr), phy_id, i, res); goto out; @@ -1515,7 +1520,7 @@ static int sas_configure_set(struct domain_device *dev, int phy_id, goto out; res = cri_resp[2]; if (res == SMP_RESP_NO_INDEX) { - pr_warn("overflow of indexes: dev %016llx phy 0x%x index 0x%x\n", + pr_warn("overflow of indexes: dev %016llx phy%02d index 0x%x\n", SAS_ADDR(dev->sas_addr), phy_id, index); } out: @@ -1760,10 +1765,11 @@ static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, res = sas_get_phy_discover(dev, phy_id, disc_resp); if (res == 0) { - memcpy(sas_addr, disc_resp->disc.attached_sas_addr, 8); + memcpy(sas_addr, disc_resp->disc.attached_sas_addr, + SAS_ADDR_SIZE); *type = to_dev_type(dr); if (*type == 0) - memset(sas_addr, 0, 8); + memset(sas_addr, 0, SAS_ADDR_SIZE); } kfree(disc_resp); return res; @@ -1870,10 +1876,12 @@ static int sas_find_bcast_dev(struct domain_device *dev, if (phy_id != -1) { *src_dev = dev; ex->ex_change_count = ex_change_count; - pr_info("Expander phy change count has changed\n"); + pr_info("ex %016llx phy%02d change count has changed\n", + SAS_ADDR(dev->sas_addr), phy_id); return res; } else - pr_info("Expander phys DID NOT change\n"); + pr_info("ex %016llx phys DID NOT change\n", + SAS_ADDR(dev->sas_addr)); } list_for_each_entry(ch, &ex->children, siblings) { if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { @@ -1983,7 +1991,7 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) struct domain_device *child; int res; - pr_debug("ex %016llx phy%d new device attached\n", + pr_debug("ex %016llx phy%02d new device attached\n", SAS_ADDR(dev->sas_addr), phy_id); res = sas_ex_phy_discover(dev, phy_id); if (res) @@ -2022,15 +2030,23 @@ static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old) return false; } -static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) +static int sas_rediscover_dev(struct domain_device *dev, int phy_id, + bool last, int sibling) { struct expander_device *ex = &dev->ex_dev; struct ex_phy *phy = &ex->ex_phy[phy_id]; enum sas_device_type type = SAS_PHY_UNUSED; - u8 sas_addr[8]; + u8 sas_addr[SAS_ADDR_SIZE]; + char msg[80] = ""; int res; - memset(sas_addr, 0, 8); + if (!last) + sprintf(msg, ", part of a wide port with phy%02d", sibling); + + pr_debug("ex %016llx rediscovering phy%02d%s\n", + SAS_ADDR(dev->sas_addr), phy_id, msg); + + memset(sas_addr, 0, SAS_ADDR_SIZE); res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type); switch (res) { case SMP_RESP_NO_PHY: @@ -2052,6 +2068,11 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) { phy->phy_state = PHY_EMPTY; sas_unregister_devs_sas_addr(dev, phy_id, last); + /* + * Even though the PHY is empty, for convenience we discover + * the PHY to update the PHY info, like negotiated linkrate. + */ + sas_ex_phy_discover(dev, phy_id); return res; } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) && dev_type_flutter(type, phy->attached_dev_type)) { @@ -2062,13 +2083,13 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING) action = ", needs recovery"; - pr_debug("ex %016llx phy 0x%x broadcast flutter%s\n", + pr_debug("ex %016llx phy%02d broadcast flutter%s\n", SAS_ADDR(dev->sas_addr), phy_id, action); return res; } /* we always have to delete the old device when we went here */ - pr_info("ex %016llx phy 0x%x replace %016llx\n", + pr_info("ex %016llx phy%02d replace %016llx\n", SAS_ADDR(dev->sas_addr), phy_id, SAS_ADDR(phy->attached_sas_addr)); sas_unregister_devs_sas_addr(dev, phy_id, last); @@ -2098,7 +2119,7 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id) int i; bool last = true; /* is this the last phy of the port */ - pr_debug("ex %016llx phy%d originated BROADCAST(CHANGE)\n", + pr_debug("ex %016llx phy%02d originated BROADCAST(CHANGE)\n", SAS_ADDR(dev->sas_addr), phy_id); if (SAS_ADDR(changed_phy->attached_sas_addr) != 0) { @@ -2109,13 +2130,11 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id) continue; if (SAS_ADDR(phy->attached_sas_addr) == SAS_ADDR(changed_phy->attached_sas_addr)) { - pr_debug("phy%d part of wide port with phy%d\n", - phy_id, i); last = false; break; } } - res = sas_rediscover_dev(dev, phy_id, last); + res = sas_rediscover_dev(dev, phy_id, last, i); } else res = sas_discover_new(dev, phy_id); return res; |