From fc47b78329be9218ee69ff22a460a40cf48d7818 Mon Sep 17 00:00:00 2001 From: yongkang Date: Thu, 23 Oct 2025 04:08:47 -0400 Subject: [PATCH] scsi: mpi3mr: Reduce stack usage in mpi3mr_refresh_sas_ports() mainline inclusion from mainline-v6.12 commit 5cc2da0b60e5b4daf6cf7442ee66f1f91878c0b5 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID37WW Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5cc2da0b60e5b4daf6cf7442ee66f1f91878c0b5 -------------------------------- SAS5116 controllers supports maximum 48 physical PHYs. Modify driver to accommodate up to 64 PHYs (though current need is to support 48 PHYs). Doubling the number of PHYs also doubled the stack usage of this function, exceeding the 32-bit limit of 1024 bytes: drivers/scsi/mpi3mr/mpi3mr_transport.c: In function 'mpi3mr_refresh_sas_ports': drivers/scsi/mpi3mr/mpi3mr_transport.c:1818:1: error: the frame size of 1636 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] Since the sas_io_unit_pg0 structure is already allocated dynamically, use the same method here. The size of the allocation can be smaller based on the actual number of phys now, so use this as an upper bound. Signed-off-by: Sumit Saxena Link: https://lore.kernel.org/r/20231123160132.4155-4-sumit.saxena@broadcom.com Signed-off-by: Martin K. Petersen Signed-off-by: Ranjan Kumar Signed-off-by: yongkang --- commit.log | 29 ++++++++++++++++++++++++++ drivers/scsi/mpi3mr/mpi3mr.h | 2 +- drivers/scsi/mpi3mr/mpi3mr_transport.c | 21 ++++++++++++------- 3 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 commit.log diff --git a/commit.log b/commit.log new file mode 100644 index 000000000000..0613d4667134 --- /dev/null +++ b/commit.log @@ -0,0 +1,29 @@ +mainline inclusion +from mainline-v6.6 +commit 82b2fb52d6ecc3c902b46b3f9bb4325ab3f6d50d +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/ID2S6E + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=82b2fb52d6ecc3c902b46b3f9bb4325ab3f6d50d + +-------------------------------- + +scsi: mpi3mr: Split off bus_reset function from host_reset +SCSI EH host reset is the final callback in the escalation chain; once we +reach this we need to reset the controller. As such it defeats the purpose +to skip controller reset if no I/Os are pending and the RAID device is to +be reset; especially after kexec there might be stale commands pending in +firmware for which we have no reference whatsoever. So this patch splits +off the check for pending I/O into a 'bus_reset' function, and leaves the +actual controller reset to the host reset. + +Signed-off-by: Hannes Reinecke +Link: https://lore.kernel.org/r/20231002154328.43718-19-hare@suse.de +Cc: Kashyap Desai +Cc: Sathya Prakash Veerichetty +Cc: Sumit Saxena +Cc: Sreekanth Reddy +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Signed-off-by: Martin K. Petersen +Signed-off-by: yongkang diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 7022435c21e9..b905e32b2173 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -504,7 +504,7 @@ struct mpi3mr_sas_port { u8 num_phys; u8 marked_responding; int lowest_phy; - u32 phy_mask; + u64 phy_mask; struct mpi3mr_hba_port *hba_port; struct sas_identify remote_identify; struct sas_rphy *rphy; diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 0072bbdb265b..5d261c2f2d20 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -1597,7 +1597,7 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, */ struct host_port { u64 sas_address; - u32 phy_mask; + u64 phy_mask; u16 handle; u8 iounit_port_id; u8 used; @@ -1621,7 +1621,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, struct mpi3mr_sas_port *mr_sas_port) { struct mpi3mr_sas_phy *mr_sas_phy; - u32 phy_mask_xor; + u64 phy_mask_xor; u64 phys_to_be_added, phys_to_be_removed; int i; @@ -1629,7 +1629,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, mr_sas_port->marked_responding = 1; dev_info(&mr_sas_port->port->dev, - "sas_address(0x%016llx), old: port_id %d phy_mask 0x%x, new: port_id %d phy_mask:0x%x\n", + "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n", mr_sas_port->remote_identify.sas_address, mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask, h_port->iounit_port_id, h_port->phy_mask); @@ -1647,7 +1647,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, * if these phys are previously registered with another port * then delete these phys from that port first. */ - for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u32)) { + for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) { mr_sas_phy = &mrioc->sas_hba.phy[i]; if (mr_sas_phy->phy_belongs_to_port) mpi3mr_del_phy_from_an_existing_port(mrioc, @@ -1659,7 +1659,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, } /* Delete the phys which are not part of current mr_sas_port's port. */ - for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u32)) { + for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) { mr_sas_phy = &mrioc->sas_hba.phy[i]; if (mr_sas_phy->phy_belongs_to_port) mpi3mr_del_phy_from_an_existing_port(mrioc, @@ -1681,7 +1681,7 @@ mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port, void mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) { - struct host_port h_port[32]; + struct host_port *h_port = NULL; int i, j, found, host_port_count = 0, port_idx; u16 sz, attached_handle, ioc_status; struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL; @@ -1695,6 +1695,10 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL); if (!sas_io_unit_pg0) return; + h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL); + if (!h_port) + goto out; + if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) { ioc_err(mrioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -1752,7 +1756,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list, port_list) { ioc_info(mrioc, - "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n", + "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n", mr_sas_port->hba_port->port_id, mr_sas_port->remote_identify.sas_address, mr_sas_port->phy_mask, mr_sas_port->lowest_phy); @@ -1761,7 +1765,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) ioc_info(mrioc, "Host port details after reset\n"); for (i = 0; i < host_port_count; i++) { ioc_info(mrioc, - "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%x), lowest phy id:%d\n", + "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n", h_port[i].iounit_port_id, h_port[i].sas_address, h_port[i].phy_mask, h_port[i].lowest_phy); } @@ -1824,6 +1828,7 @@ mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc) } } out: + kfree(h_port); kfree(sas_io_unit_pg0); } -- Gitee