Skip to content

Commit 91202a0

Browse files
sreekanthbrcmmartinkpetersen
authored andcommitted
scsi: mpt3sas: Fix system going into read-only mode
While determining the SAS address of a drive, the driver checks whether the handle number is less than the HBA phy count or not. If the handle number is less than the HBA phy count then driver assumes that this handle belongs to HBA and hence it assigns the HBA SAS address. During IOC firmware downgrade operation, if the number of HBA phys is reduced and the OS drive's device handle drops below the phy count while determining the drive's SAS address, the driver ends up using the HBA's SAS address. This leads to a mismatch of drive's SAS address and hence the driver unregisters the OS drive and the system goes into read-only mode. Update the IOC's num_phys to the HBA phy count provided by actual loaded firmware. Link: https://lore.kernel.org/r/[email protected] Fixes: a5e99fd ("scsi: mpt3sas: Update hba_port objects after host reset") Signed-off-by: Sreekanth Reddy <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 0ee4ba1 commit 91202a0

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

drivers/scsi/mpt3sas/mpt3sas_base.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@
142142

143143
#define MPT_MAX_CALLBACKS 32
144144

145+
#define MPT_MAX_HBA_NUM_PHYS 32
146+
145147
#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
146148
/* reserved for issuing internally framed scsi io cmds */
147149
#define INTERNAL_SCSIIO_CMDS_COUNT 3
@@ -798,6 +800,7 @@ struct _sas_phy {
798800
* @enclosure_handle: handle for this a member of an enclosure
799801
* @device_info: bitwise defining capabilities of this sas_host/expander
800802
* @responding: used in _scsih_expander_device_mark_responding
803+
* @nr_phys_allocated: Allocated memory for this many count phys
801804
* @phy: a list of phys that make up this sas_host/expander
802805
* @sas_port_list: list of ports attached to this sas_host/expander
803806
* @port: hba port entry containing node's port number info
@@ -813,6 +816,7 @@ struct _sas_node {
813816
u16 enclosure_handle;
814817
u64 enclosure_logical_id;
815818
u8 responding;
819+
u8 nr_phys_allocated;
816820
struct hba_port *port;
817821
struct _sas_phy *phy;
818822
struct list_head sas_port_list;

drivers/scsi/mpt3sas/mpt3sas_scsih.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6406,11 +6406,26 @@ _scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc)
64066406
int i, j, count = 0, lcount = 0;
64076407
int ret;
64086408
u64 sas_addr;
6409+
u8 num_phys;
64096410

64106411
drsprintk(ioc, ioc_info(ioc,
64116412
"updating ports for sas_host(0x%016llx)\n",
64126413
(unsigned long long)ioc->sas_hba.sas_address));
64136414

6415+
mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
6416+
if (!num_phys) {
6417+
ioc_err(ioc, "failure at %s:%d/%s()!\n",
6418+
__FILE__, __LINE__, __func__);
6419+
return;
6420+
}
6421+
6422+
if (num_phys > ioc->sas_hba.nr_phys_allocated) {
6423+
ioc_err(ioc, "failure at %s:%d/%s()!\n",
6424+
__FILE__, __LINE__, __func__);
6425+
return;
6426+
}
6427+
ioc->sas_hba.num_phys = num_phys;
6428+
64146429
port_table = kcalloc(ioc->sas_hba.num_phys,
64156430
sizeof(struct hba_port), GFP_KERNEL);
64166431
if (!port_table)
@@ -6611,6 +6626,30 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
66116626
ioc->sas_hba.phy[i].hba_vphy = 1;
66126627
}
66136628

6629+
/*
6630+
* Add new HBA phys to STL if these new phys got added as part
6631+
* of HBA Firmware upgrade/downgrade operation.
6632+
*/
6633+
if (!ioc->sas_hba.phy[i].phy) {
6634+
if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply,
6635+
&phy_pg0, i))) {
6636+
ioc_err(ioc, "failure at %s:%d/%s()!\n",
6637+
__FILE__, __LINE__, __func__);
6638+
continue;
6639+
}
6640+
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6641+
MPI2_IOCSTATUS_MASK;
6642+
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6643+
ioc_err(ioc, "failure at %s:%d/%s()!\n",
6644+
__FILE__, __LINE__, __func__);
6645+
continue;
6646+
}
6647+
ioc->sas_hba.phy[i].phy_id = i;
6648+
mpt3sas_transport_add_host_phy(ioc,
6649+
&ioc->sas_hba.phy[i], phy_pg0,
6650+
ioc->sas_hba.parent_dev);
6651+
continue;
6652+
}
66146653
ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
66156654
attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
66166655
AttachedDevHandle);
@@ -6622,6 +6661,19 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
66226661
attached_handle, i, link_rate,
66236662
ioc->sas_hba.phy[i].port);
66246663
}
6664+
/*
6665+
* Clear the phy details if this phy got disabled as part of
6666+
* HBA Firmware upgrade/downgrade operation.
6667+
*/
6668+
for (i = ioc->sas_hba.num_phys;
6669+
i < ioc->sas_hba.nr_phys_allocated; i++) {
6670+
if (ioc->sas_hba.phy[i].phy &&
6671+
ioc->sas_hba.phy[i].phy->negotiated_linkrate >=
6672+
SAS_LINK_RATE_1_5_GBPS)
6673+
mpt3sas_transport_update_links(ioc,
6674+
ioc->sas_hba.sas_address, 0, i,
6675+
MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED, NULL);
6676+
}
66256677
out:
66266678
kfree(sas_iounit_pg0);
66276679
}
@@ -6654,7 +6706,10 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
66546706
__FILE__, __LINE__, __func__);
66556707
return;
66566708
}
6657-
ioc->sas_hba.phy = kcalloc(num_phys,
6709+
6710+
ioc->sas_hba.nr_phys_allocated = max_t(u8,
6711+
MPT_MAX_HBA_NUM_PHYS, num_phys);
6712+
ioc->sas_hba.phy = kcalloc(ioc->sas_hba.nr_phys_allocated,
66586713
sizeof(struct _sas_phy), GFP_KERNEL);
66596714
if (!ioc->sas_hba.phy) {
66606715
ioc_err(ioc, "failure at %s:%d/%s()!\n",

0 commit comments

Comments
 (0)