xref: /illumos-gate/usr/src/lib/sun_sas/common/Sun_sasFreeLibrary.c (revision 7801e5e8b5bc4af34929c54a02cfb78398da08dd)
1  /*
2   * CDDL HEADER START
3   *
4   * The contents of this file are subject to the terms of the
5   * Common Development and Distribution License (the "License").
6   * You may not use this file except in compliance with the License.
7   *
8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9   * or http://www.opensolaris.org/os/licensing.
10   * See the License for the specific language governing permissions
11   * and limitations under the License.
12   *
13   * When distributing Covered Code, include this CDDL HEADER in each
14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15   * If applicable, add the following below this CDDL HEADER, with the
16   * fields enclosed by brackets "[]" replaced with your own identifying
17   * information: Portions Copyright [yyyy] [name of copyright owner]
18   *
19   * CDDL HEADER END
20   */
21  
22  /*
23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24   * Use is subject to license terms.
25   */
26  
27  
28  #include <sun_sas.h>
29  
30  /*
31   * Frees the HBA Library.  Must be called after all HBA library functions
32   * to free all resources
33   */
34  HBA_STATUS Sun_sasFreeLibrary() {
35  	HBA_STATUS 	status;
36  
37  	lock(&all_hbas_lock);
38  
39  	status = FreeHBA(global_hba_head);
40  
41  	/* re-initialize all global variables */
42  	global_hba_head = NULL;
43  	hba_count = 0;
44  	open_handle_index = 1;
45  	unlock(&all_hbas_lock);
46  	(void) mutex_destroy(&all_hbas_lock);
47  
48  	/* free sysevent handle. */
49  	if (gSysEventHandle != NULL)
50  		sysevent_unbind_handle(gSysEventHandle);
51  
52  	/* Reset our load count so we can be reloaded now */
53  	loadCount = 0;
54  
55  	return (status);
56  }
57  
58  /*
59   * Internal routine to free up hba_ptr's (and all sub-structures)
60   */
61  HBA_STATUS FreeHBA(struct sun_sas_hba *hba) {
62  	struct sun_sas_hba	*hba_ptr = NULL;
63  	struct sun_sas_hba	*last_hba_ptr = NULL;
64  	struct sun_sas_port	*hba_port = NULL;
65  	struct sun_sas_port	*last_hba_port = NULL;
66  	struct sun_sas_port	*tgt_port = NULL;
67  	struct sun_sas_port	*last_tgt_port = NULL;
68  	struct ScsiEntryList	*scsi_info = NULL;
69  	struct ScsiEntryList	*last_scsi_info = NULL;
70  	struct phy_info		*phy_ptr = NULL;
71  	struct phy_info		*last_phy = NULL;
72  	struct open_handle	*open_handle = NULL;
73  	struct open_handle	*last_open_handle = NULL;
74  
75  	last_hba_ptr = NULL;
76  	/* walk through global_hba_head list freeing each handle */
77  	for (hba_ptr = hba;
78  	    hba_ptr != NULL;
79  	    hba_ptr = hba_ptr->next) {
80  		/* Free the nested structures (port and attached port) */
81  		hba_port = hba_ptr->first_port;
82  		while (hba_port != NULL) {
83  		    /* Free discovered port structure list. */
84  		    tgt_port = hba_port->first_attached_port;
85  		    while (tgt_port != NULL) {
86  			    /* Free target mapping data list first. */
87  			    scsi_info = tgt_port->scsiInfo;
88  			    while (scsi_info != NULL) {
89  				    last_scsi_info = scsi_info;
90  				    scsi_info = scsi_info->next;
91  				    free(last_scsi_info);
92  			    }
93  			last_tgt_port = tgt_port;
94  			tgt_port = tgt_port->next;
95  			free(last_tgt_port->port_attributes.\
96  			    PortSpecificAttribute.SASPort);
97  			free(last_tgt_port);
98  		    }
99  
100  		    phy_ptr = hba_port->first_phy;
101  		    while (phy_ptr != NULL) {
102  			last_phy = phy_ptr;
103  			phy_ptr = phy_ptr->next;
104  			free(last_phy);
105  		    }
106  
107  		    last_hba_port = hba_port;
108  		    hba_port = hba_port->next;
109  		    free(last_hba_port->port_attributes.\
110  			PortSpecificAttribute.SASPort);
111  		    free(last_hba_port);
112  		}
113  
114  		open_handle = hba_ptr->open_handles;
115  		while (open_handle != NULL) {
116  		    last_open_handle = open_handle;
117  		    open_handle = open_handle->next;
118  		    free(last_open_handle);
119  		}
120  		/* Free up the top level HBA structure from the last spin */
121  		if (last_hba_ptr != NULL) {
122  		    free(last_hba_ptr);
123  		}
124  		last_hba_ptr = hba_ptr;
125  	}
126  	if (last_hba_ptr != NULL) {
127  	    free(last_hba_ptr);
128  	}
129  
130  	return (HBA_STATUS_OK);
131  }
132