19e86db79SHyon Kim /*
29e86db79SHyon Kim  * CDDL HEADER START
39e86db79SHyon Kim  *
49e86db79SHyon Kim  * The contents of this file are subject to the terms of the
59e86db79SHyon Kim  * Common Development and Distribution License (the "License").
69e86db79SHyon Kim  * You may not use this file except in compliance with the License.
79e86db79SHyon Kim  *
89e86db79SHyon Kim  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e86db79SHyon Kim  * or http://www.opensolaris.org/os/licensing.
109e86db79SHyon Kim  * See the License for the specific language governing permissions
119e86db79SHyon Kim  * and limitations under the License.
129e86db79SHyon Kim  *
139e86db79SHyon Kim  * When distributing Covered Code, include this CDDL HEADER in each
149e86db79SHyon Kim  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e86db79SHyon Kim  * If applicable, add the following below this CDDL HEADER, with the
169e86db79SHyon Kim  * fields enclosed by brackets "[]" replaced with your own identifying
179e86db79SHyon Kim  * information: Portions Copyright [yyyy] [name of copyright owner]
189e86db79SHyon Kim  *
199e86db79SHyon Kim  * CDDL HEADER END
209e86db79SHyon Kim  */
219e86db79SHyon Kim 
229e86db79SHyon Kim /*
239e86db79SHyon Kim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249e86db79SHyon Kim  * Use is subject to license terms.
259e86db79SHyon Kim  */
2600f453f4SRob Johnston /*
2700f453f4SRob Johnston  * Copyright 2019 Joyent, Inc.
2800f453f4SRob Johnston  */
299e86db79SHyon Kim 
309e86db79SHyon Kim #include <sun_sas.h>
319e86db79SHyon Kim 
329e86db79SHyon Kim /*
339e86db79SHyon Kim  * Frees the HBA Library.  Must be called after all HBA library functions
349e86db79SHyon Kim  * to free all resources
359e86db79SHyon Kim  */
3600f453f4SRob Johnston HBA_STATUS
Sun_sasFreeLibrary(void)3700f453f4SRob Johnston Sun_sasFreeLibrary(void)
3800f453f4SRob Johnston {
3900f453f4SRob Johnston 	HBA_STATUS status;
409e86db79SHyon Kim 
419e86db79SHyon Kim 	lock(&all_hbas_lock);
429e86db79SHyon Kim 
439e86db79SHyon Kim 	status = FreeHBA(global_hba_head);
449e86db79SHyon Kim 
459e86db79SHyon Kim 	/* re-initialize all global variables */
469e86db79SHyon Kim 	global_hba_head = NULL;
479e86db79SHyon Kim 	hba_count = 0;
489e86db79SHyon Kim 	open_handle_index = 1;
499e86db79SHyon Kim 	unlock(&all_hbas_lock);
509e86db79SHyon Kim 	(void) mutex_destroy(&all_hbas_lock);
51*c1ba8596SToomas Soome 	(void) mutex_destroy(&open_handles_lock);
529e86db79SHyon Kim 
539e86db79SHyon Kim 	/* free sysevent handle. */
549e86db79SHyon Kim 	if (gSysEventHandle != NULL)
559e86db79SHyon Kim 		sysevent_unbind_handle(gSysEventHandle);
569e86db79SHyon Kim 
579e86db79SHyon Kim 	/* Reset our load count so we can be reloaded now */
589e86db79SHyon Kim 	loadCount = 0;
599e86db79SHyon Kim 
609e86db79SHyon Kim 	return (status);
619e86db79SHyon Kim }
629e86db79SHyon Kim 
639e86db79SHyon Kim /*
649e86db79SHyon Kim  * Internal routine to free up hba_ptr's (and all sub-structures)
659e86db79SHyon Kim  */
6600f453f4SRob Johnston HBA_STATUS
FreeHBA(struct sun_sas_hba * hba)6700f453f4SRob Johnston FreeHBA(struct sun_sas_hba *hba)
6800f453f4SRob Johnston {
699e86db79SHyon Kim 	struct sun_sas_hba	*hba_ptr = NULL;
709e86db79SHyon Kim 	struct sun_sas_hba	*last_hba_ptr = NULL;
719e86db79SHyon Kim 	struct sun_sas_port	*hba_port = NULL;
729e86db79SHyon Kim 	struct sun_sas_port	*last_hba_port = NULL;
739e86db79SHyon Kim 	struct sun_sas_port	*tgt_port = NULL;
749e86db79SHyon Kim 	struct sun_sas_port	*last_tgt_port = NULL;
759e86db79SHyon Kim 	struct ScsiEntryList	*scsi_info = NULL;
769e86db79SHyon Kim 	struct ScsiEntryList	*last_scsi_info = NULL;
779e86db79SHyon Kim 	struct phy_info		*phy_ptr = NULL;
789e86db79SHyon Kim 	struct phy_info		*last_phy = NULL;
799e86db79SHyon Kim 	struct open_handle	*open_handle = NULL;
809e86db79SHyon Kim 	struct open_handle	*last_open_handle = NULL;
819e86db79SHyon Kim 
829e86db79SHyon Kim 	last_hba_ptr = NULL;
839e86db79SHyon Kim 	/* walk through global_hba_head list freeing each handle */
8400f453f4SRob Johnston 	for (hba_ptr = hba; hba_ptr != NULL; hba_ptr = hba_ptr->next) {
859e86db79SHyon Kim 		/* Free the nested structures (port and attached port) */
869e86db79SHyon Kim 		hba_port = hba_ptr->first_port;
879e86db79SHyon Kim 		while (hba_port != NULL) {
8800f453f4SRob Johnston 			/* Free discovered port structure list. */
8900f453f4SRob Johnston 			tgt_port = hba_port->first_attached_port;
9000f453f4SRob Johnston 			while (tgt_port != NULL) {
9100f453f4SRob Johnston 				/* Free target mapping data list first. */
9200f453f4SRob Johnston 				scsi_info = tgt_port->scsiInfo;
9300f453f4SRob Johnston 				while (scsi_info != NULL) {
9400f453f4SRob Johnston 					last_scsi_info = scsi_info;
9500f453f4SRob Johnston 					scsi_info = scsi_info->next;
9600f453f4SRob Johnston 					free(last_scsi_info);
9700f453f4SRob Johnston 				}
9800f453f4SRob Johnston 				last_tgt_port = tgt_port;
9900f453f4SRob Johnston 				tgt_port = tgt_port->next;
10000f453f4SRob Johnston 				free(last_tgt_port->port_attributes.\
10100f453f4SRob Johnston 				    PortSpecificAttribute.SASPort);
10200f453f4SRob Johnston 				free(last_tgt_port);
10300f453f4SRob Johnston 			}
10400f453f4SRob Johnston 
10500f453f4SRob Johnston 			phy_ptr = hba_port->first_phy;
10600f453f4SRob Johnston 			while (phy_ptr != NULL) {
10700f453f4SRob Johnston 				last_phy = phy_ptr;
10800f453f4SRob Johnston 				phy_ptr = phy_ptr->next;
10900f453f4SRob Johnston 				free(last_phy);
11000f453f4SRob Johnston 			}
11100f453f4SRob Johnston 
11200f453f4SRob Johnston 			last_hba_port = hba_port;
11300f453f4SRob Johnston 			hba_port = hba_port->next;
11400f453f4SRob Johnston 			free(last_hba_port->port_attributes.\
1159e86db79SHyon Kim 			    PortSpecificAttribute.SASPort);
11600f453f4SRob Johnston 			free(last_hba_port);
1179e86db79SHyon Kim 		}
1189e86db79SHyon Kim 
1199e86db79SHyon Kim 		open_handle = hba_ptr->open_handles;
1209e86db79SHyon Kim 		while (open_handle != NULL) {
12100f453f4SRob Johnston 			last_open_handle = open_handle;
12200f453f4SRob Johnston 			open_handle = open_handle->next;
12300f453f4SRob Johnston 			free(last_open_handle);
1249e86db79SHyon Kim 		}
1259e86db79SHyon Kim 		/* Free up the top level HBA structure from the last spin */
1269e86db79SHyon Kim 		if (last_hba_ptr != NULL) {
12700f453f4SRob Johnston 			free(last_hba_ptr);
1289e86db79SHyon Kim 		}
1299e86db79SHyon Kim 		last_hba_ptr = hba_ptr;
1309e86db79SHyon Kim 	}
1319e86db79SHyon Kim 	if (last_hba_ptr != NULL) {
13200f453f4SRob Johnston 		free(last_hba_ptr);
1339e86db79SHyon Kim 	}
1349e86db79SHyon Kim 
1359e86db79SHyon Kim 	return (HBA_STATUS_OK);
1369e86db79SHyon Kim }
137