+++ /dev/null
-From 75e1dbd05bd2edcb5b32bc4919b8beafa12543bf Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 7 Mar 2024 14:14:12 +0000
-Subject: scsi: libsas: Add a helper sas_get_sas_addr_and_dev_type()
-
-From: Xingui Yang <yangxingui@huawei.com>
-
-[ Upstream commit a57345279fd311ba679b8083feb0eec5272c7729 ]
-
-Add a helper to get attached_sas_addr and device type from disc_resp.
-
-Suggested-by: John Garry <john.g.garry@oracle.com>
-Signed-off-by: Xingui Yang <yangxingui@huawei.com>
-Link: https://lore.kernel.org/r/20240307141413.48049-2-yangxingui@huawei.com
-Reviewed-by: John Garry <john.g.garry@oracle.com>
-Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-Stable-dep-of: 8e68a458bcf5 ("scsi: libsas: Fix disk not being scanned in after being removed")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/scsi/libsas/sas_expander.c | 19 ++++++++++++-------
- 1 file changed, 12 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
-index 1b608cb423e0c..6a61a84ce3453 100644
---- a/drivers/scsi/libsas/sas_expander.c
-+++ b/drivers/scsi/libsas/sas_expander.c
-@@ -1673,6 +1673,16 @@ int sas_discover_root_expander(struct domain_device *dev)
-
- /* ---------- Domain revalidation ---------- */
-
-+static void sas_get_sas_addr_and_dev_type(struct smp_disc_resp *disc_resp,
-+ u8 *sas_addr,
-+ enum sas_device_type *type)
-+{
-+ memcpy(sas_addr, disc_resp->disc.attached_sas_addr, SAS_ADDR_SIZE);
-+ *type = to_dev_type(&disc_resp->disc);
-+ if (*type == SAS_PHY_UNUSED)
-+ memset(sas_addr, 0, SAS_ADDR_SIZE);
-+}
-+
- static int sas_get_phy_discover(struct domain_device *dev,
- int phy_id, struct smp_disc_resp *disc_resp)
- {
-@@ -1726,13 +1736,8 @@ static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
- return -ENOMEM;
-
- res = sas_get_phy_discover(dev, phy_id, disc_resp);
-- if (res == 0) {
-- memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
-- SAS_ADDR_SIZE);
-- *type = to_dev_type(&disc_resp->disc);
-- if (*type == 0)
-- memset(sas_addr, 0, SAS_ADDR_SIZE);
-- }
-+ if (res == 0)
-+ sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, type);
- kfree(disc_resp);
- return res;
- }
---
-2.43.0
-
+++ /dev/null
-From 01ea12c830e461588628aacc292d8dd7c977a383 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 7 Mar 2024 14:14:13 +0000
-Subject: scsi: libsas: Fix disk not being scanned in after being removed
-
-From: Xingui Yang <yangxingui@huawei.com>
-
-[ Upstream commit 8e68a458bcf5b5cb9c3624598bae28f08251601f ]
-
-As of commit d8649fc1c5e4 ("scsi: libsas: Do discovery on empty PHY to
-update PHY info"), do discovery will send a new SMP_DISCOVER and update
-phy->phy_change_count. We found that if the disk is reconnected and phy
-change_count changes at this time, the disk scanning process will not be
-triggered.
-
-Therefore, call sas_set_ex_phy() to update the PHY info with the results of
-the last query. And because the previous phy info will be used when calling
-sas_unregister_devs_sas_addr(), sas_unregister_devs_sas_addr() should be
-called before sas_set_ex_phy().
-
-Fixes: d8649fc1c5e4 ("scsi: libsas: Do discovery on empty PHY to update PHY info")
-Signed-off-by: Xingui Yang <yangxingui@huawei.com>
-Link: https://lore.kernel.org/r/20240307141413.48049-3-yangxingui@huawei.com
-Reviewed-by: John Garry <john.g.garry@oracle.com>
-Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/scsi/libsas/sas_expander.c | 32 ++++++++++++++++++++----------
- 1 file changed, 22 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
-index 6a61a84ce3453..47043d582d0a3 100644
---- a/drivers/scsi/libsas/sas_expander.c
-+++ b/drivers/scsi/libsas/sas_expander.c
-@@ -1999,6 +1999,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
- struct expander_device *ex = &dev->ex_dev;
- struct ex_phy *phy = &ex->ex_phy[phy_id];
- enum sas_device_type type = SAS_PHY_UNUSED;
-+ struct smp_disc_resp *disc_resp;
- u8 sas_addr[SAS_ADDR_SIZE];
- char msg[80] = "";
- int res;
-@@ -2010,33 +2011,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
- 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);
-+ disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
-+ if (!disc_resp)
-+ return -ENOMEM;
-+
-+ res = sas_get_phy_discover(dev, phy_id, disc_resp);
- switch (res) {
- case SMP_RESP_NO_PHY:
- phy->phy_state = PHY_NOT_PRESENT;
- sas_unregister_devs_sas_addr(dev, phy_id, last);
-- return res;
-+ goto out_free_resp;
- case SMP_RESP_PHY_VACANT:
- phy->phy_state = PHY_VACANT;
- sas_unregister_devs_sas_addr(dev, phy_id, last);
-- return res;
-+ goto out_free_resp;
- case SMP_RESP_FUNC_ACC:
- break;
- case -ECOMM:
- break;
- default:
-- return res;
-+ goto out_free_resp;
- }
-
-+ if (res == 0)
-+ sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, &type);
-+
- 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.
-+ * Even though the PHY is empty, for convenience we update
-+ * the PHY info, like negotiated linkrate.
- */
-- sas_ex_phy_discover(dev, phy_id);
-- return res;
-+ if (res == 0)
-+ sas_set_ex_phy(dev, phy_id, disc_resp);
-+ goto out_free_resp;
- } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
- dev_type_flutter(type, phy->attached_dev_type)) {
- struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
-@@ -2048,7 +2057,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
- action = ", needs recovery";
- pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
- SAS_ADDR(dev->sas_addr), phy_id, action);
-- return res;
-+ goto out_free_resp;
- }
-
- /* we always have to delete the old device when we went here */
-@@ -2057,7 +2066,10 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
- SAS_ADDR(phy->attached_sas_addr));
- sas_unregister_devs_sas_addr(dev, phy_id, last);
-
-- return sas_discover_new(dev, phy_id);
-+ res = sas_discover_new(dev, phy_id);
-+out_free_resp:
-+ kfree(disc_resp);
-+ return res;
- }
-
- /**
---
-2.43.0
-
+++ /dev/null
-From eaf20826e6c756e966ee6a556fdf0e9ac9f0637e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 9 Jun 2022 11:24:54 +0900
-Subject: scsi: libsas: Introduce struct smp_disc_resp
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Damien Le Moal <damien.lemoal@opensource.wdc.com>
-
-[ Upstream commit c3752f44604f3bc4f3ce6e169fa32d16943ff70b ]
-
-When compiling with gcc 12, several warnings are thrown by gcc when
-compiling drivers/scsi/libsas/sas_expander.c, e.g.:
-
-In function ‘sas_get_phy_change_count’,
- inlined from ‘sas_find_bcast_phy.constprop’ at
-drivers/scsi/libsas/sas_expander.c:1737:9:
-drivers/scsi/libsas/sas_expander.c:1697:39: warning: array subscript
-‘struct smp_resp[0]’ is partly outside array bounds of ‘unsigned
-char[56]’ [-Warray-bounds]
- 1697 | *pcc = disc_resp->disc.change_count;
- | ~~~~~~~~~~~~~~~^~~~~~~~~~~~~
-
-This is due to the use of the struct smp_resp to aggregate all possible
-response types using a union but allocating a response buffer with a size
-exactly equal to the size of the response type needed. This leads to access
-to fields of struct smp_resp from an allocated memory area that is smaller
-than the size of struct smp_resp.
-
-Fix this by defining struct smp_disc_resp for sas discovery operations.
-Since this structure and the generic struct smp_resp are identical for
-the little endian and big endian archs, move the definition of these
-structures at the end of include/scsi/sas.h to avoid repeating their
-definition.
-
-Link: https://lore.kernel.org/r/20220609022456.409087-2-damien.lemoal@opensource.wdc.com
-Reviewed-by: John Garry <john.garry@huawei.com>
-Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
-Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-Stable-dep-of: 8e68a458bcf5 ("scsi: libsas: Fix disk not being scanned in after being removed")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/scsi/libsas/sas_expander.c | 32 +++++++++++++-----------------
- include/scsi/sas.h | 28 +++++++++++---------------
- 2 files changed, 26 insertions(+), 34 deletions(-)
-
-diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
-index 9ae35631135d8..1b608cb423e0c 100644
---- a/drivers/scsi/libsas/sas_expander.c
-+++ b/drivers/scsi/libsas/sas_expander.c
-@@ -192,13 +192,13 @@ static enum sas_device_type to_dev_type(struct discover_resp *dr)
- return dr->attached_dev_type;
- }
-
--static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
-+static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
-+ struct smp_disc_resp *disc_resp)
- {
- enum sas_device_type dev_type;
- enum sas_linkrate linkrate;
- u8 sas_addr[SAS_ADDR_SIZE];
-- struct smp_resp *resp = rsp;
-- struct discover_resp *dr = &resp->disc;
-+ struct discover_resp *dr = &disc_resp->disc;
- struct sas_ha_struct *ha = dev->port->ha;
- struct expander_device *ex = &dev->ex_dev;
- struct ex_phy *phy = &ex->ex_phy[phy_id];
-@@ -215,7 +215,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
- BUG_ON(!phy->phy);
- }
-
-- switch (resp->result) {
-+ switch (disc_resp->result) {
- case SMP_RESP_PHY_VACANT:
- phy->phy_state = PHY_VACANT;
- break;
-@@ -364,12 +364,13 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
- }
-
- #define DISCOVER_REQ_SIZE 16
--#define DISCOVER_RESP_SIZE 56
-+#define DISCOVER_RESP_SIZE sizeof(struct smp_disc_resp)
-
- static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
-- u8 *disc_resp, int single)
-+ struct smp_disc_resp *disc_resp,
-+ int single)
- {
-- struct discover_resp *dr;
-+ struct discover_resp *dr = &disc_resp->disc;
- int res;
-
- disc_req[9] = single;
-@@ -378,7 +379,6 @@ static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
- disc_resp, DISCOVER_RESP_SIZE);
- if (res)
- return res;
-- dr = &((struct smp_resp *)disc_resp)->disc;
- if (memcmp(dev->sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE) == 0) {
- pr_notice("Found loopback topology, just ignore it!\n");
- return 0;
-@@ -392,7 +392,7 @@ int sas_ex_phy_discover(struct domain_device *dev, int single)
- struct expander_device *ex = &dev->ex_dev;
- int res = 0;
- u8 *disc_req;
-- u8 *disc_resp;
-+ struct smp_disc_resp *disc_resp;
-
- disc_req = alloc_smp_req(DISCOVER_REQ_SIZE);
- if (!disc_req)
-@@ -1674,7 +1674,7 @@ int sas_discover_root_expander(struct domain_device *dev)
- /* ---------- Domain revalidation ---------- */
-
- static int sas_get_phy_discover(struct domain_device *dev,
-- int phy_id, struct smp_resp *disc_resp)
-+ int phy_id, struct smp_disc_resp *disc_resp)
- {
- int res;
- u8 *disc_req;
-@@ -1690,10 +1690,8 @@ static int sas_get_phy_discover(struct domain_device *dev,
- disc_resp, DISCOVER_RESP_SIZE);
- if (res)
- goto out;
-- else if (disc_resp->result != SMP_RESP_FUNC_ACC) {
-+ if (disc_resp->result != SMP_RESP_FUNC_ACC)
- res = disc_resp->result;
-- goto out;
-- }
- out:
- kfree(disc_req);
- return res;
-@@ -1703,7 +1701,7 @@ static int sas_get_phy_change_count(struct domain_device *dev,
- int phy_id, int *pcc)
- {
- int res;
-- struct smp_resp *disc_resp;
-+ struct smp_disc_resp *disc_resp;
-
- disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
- if (!disc_resp)
-@@ -1721,19 +1719,17 @@ static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
- u8 *sas_addr, enum sas_device_type *type)
- {
- int res;
-- struct smp_resp *disc_resp;
-- struct discover_resp *dr;
-+ struct smp_disc_resp *disc_resp;
-
- disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
- if (!disc_resp)
- return -ENOMEM;
-- dr = &disc_resp->disc;
-
- res = sas_get_phy_discover(dev, phy_id, disc_resp);
- if (res == 0) {
- memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
- SAS_ADDR_SIZE);
-- *type = to_dev_type(dr);
-+ *type = to_dev_type(&disc_resp->disc);
- if (*type == 0)
- memset(sas_addr, 0, SAS_ADDR_SIZE);
- }
-diff --git a/include/scsi/sas.h b/include/scsi/sas.h
-index 4726c1bbec659..2f73c24d4c9b9 100644
---- a/include/scsi/sas.h
-+++ b/include/scsi/sas.h
-@@ -460,18 +460,6 @@ struct report_phy_sata_resp {
- __be32 crc;
- } __attribute__ ((packed));
-
--struct smp_resp {
-- u8 frame_type;
-- u8 function;
-- u8 result;
-- u8 reserved;
-- union {
-- struct report_general_resp rg;
-- struct discover_resp disc;
-- struct report_phy_sata_resp rps;
-- };
--} __attribute__ ((packed));
--
- #elif defined(__BIG_ENDIAN_BITFIELD)
- struct sas_identify_frame {
- /* Byte 0 */
-@@ -691,6 +679,18 @@ struct report_phy_sata_resp {
- __be32 crc;
- } __attribute__ ((packed));
-
-+#else
-+#error "Bitfield order not defined!"
-+#endif
-+
-+struct smp_disc_resp {
-+ u8 frame_type;
-+ u8 function;
-+ u8 result;
-+ u8 reserved;
-+ struct discover_resp disc;
-+} __attribute__ ((packed));
-+
- struct smp_resp {
- u8 frame_type;
- u8 function;
-@@ -703,8 +703,4 @@ struct smp_resp {
- };
- } __attribute__ ((packed));
-
--#else
--#error "Bitfield order not defined!"
--#endif
--
- #endif /* _SAS_H_ */
---
-2.43.0
-