scsi: libsas: Add rollback handling when an error occurs

In sas_register_phys(), if an error is triggered in the loop process, we
need to roll back the resources that have already been requested.

Add sas_unregister_phys() when an error occurs in sas_register_ha().

[mkp: a few coding style tweaks and address John's comment]

Signed-off-by: Chaohai Chen <wdhh6@aliyun.com>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251206060616.69216-1-wdhh6@aliyun.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by Chaohai Chen and committed by Martin K. Petersen 362432e9 fd81bc5c

Changed files
+32 -3
drivers
+1
drivers/scsi/libsas/sas_init.c
··· 141 141 Undo_ports: 142 142 sas_unregister_ports(sas_ha); 143 143 Undo_phys: 144 + sas_unregister_phys(sas_ha); 144 145 145 146 return error; 146 147 }
+1
drivers/scsi/libsas/sas_internal.h
··· 54 54 void sas_scsi_recover_host(struct Scsi_Host *shost); 55 55 56 56 int sas_register_phys(struct sas_ha_struct *sas_ha); 57 + void sas_unregister_phys(struct sas_ha_struct *sas_ha); 57 58 58 59 struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, gfp_t gfp_flags); 59 60 void sas_free_event(struct asd_sas_event *event);
+30 -3
drivers/scsi/libsas/sas_phy.c
··· 116 116 int sas_register_phys(struct sas_ha_struct *sas_ha) 117 117 { 118 118 int i; 119 + int err; 119 120 120 121 /* Now register the phys. */ 121 122 for (i = 0; i < sas_ha->num_phys; i++) { ··· 133 132 phy->frame_rcvd_size = 0; 134 133 135 134 phy->phy = sas_phy_alloc(&sas_ha->shost->shost_gendev, i); 136 - if (!phy->phy) 137 - return -ENOMEM; 135 + if (!phy->phy) { 136 + err = -ENOMEM; 137 + goto rollback; 138 + } 138 139 139 140 phy->phy->identify.initiator_port_protocols = 140 141 phy->iproto; ··· 149 146 phy->phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN; 150 147 phy->phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; 151 148 152 - sas_phy_add(phy->phy); 149 + err = sas_phy_add(phy->phy); 150 + if (err) { 151 + sas_phy_free(phy->phy); 152 + goto rollback; 153 + } 153 154 } 154 155 155 156 return 0; 157 + rollback: 158 + for (i-- ; i >= 0 ; i--) { 159 + struct asd_sas_phy *phy = sas_ha->sas_phy[i]; 160 + 161 + sas_phy_delete(phy->phy); 162 + sas_phy_free(phy->phy); 163 + } 164 + return err; 165 + } 166 + 167 + void sas_unregister_phys(struct sas_ha_struct *sas_ha) 168 + { 169 + int i; 170 + 171 + for (i = 0 ; i < sas_ha->num_phys ; i++) { 172 + struct asd_sas_phy *phy = sas_ha->sas_phy[i]; 173 + 174 + sas_phy_delete(phy->phy); 175 + sas_phy_free(phy->phy); 176 + } 156 177 } 157 178 158 179 const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {