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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include <sys/byteorder.h>
32 * creates a handle each time Sun_sas_OpenAdapter() is called.
34 * a open_handle_struct was created to keep track of which handles are currently
35 * open. This prevents a user from using an old handle that corresponds to
36 * an hba that has already been closed.
39 CreateHandle(int adapterIndex
)
41 const char ROUTINE
[] = "CreateHandle";
42 struct open_handle
*new_open_handle
;
43 HBA_UINT32 new_handle_index
;
44 HBA_UINT8 max_handle_wrap
= 0;
46 if (global_hba_head
== NULL
) {
47 log(LOG_DEBUG
, ROUTINE
,
48 "an error as occurred. global_hba_head is "
49 "NULL. Library may not be loaded yet.");
50 return (HANDLE_ERROR
);
53 while (RetrieveIndex(open_handle_index
) != -1) {
54 open_handle_index
= open_handle_index
+ 1;
55 if (open_handle_index
== 0) {
57 * If open_handle_index wraps back to zero again,
58 * that means all handles are currently in use.
59 * Spec only allows for 16 bits of handles
61 if (max_handle_wrap
== 1) {
62 log(LOG_DEBUG
, ROUTINE
,
63 "Max number of handles reached.");
64 return (HANDLE_ERROR
);
66 open_handle_index
= 1;
71 new_handle_index
= open_handle_index
;
72 if ((new_open_handle
= (struct open_handle
*)calloc(1,
73 sizeof (struct open_handle
))) == NULL
) {
74 OUT_OF_MEMORY(ROUTINE
);
75 return (HANDLE_ERROR
);
77 (void) memset(new_open_handle
, 0, sizeof (struct open_handle
));
78 new_open_handle
->adapterIndex
= adapterIndex
;
79 new_open_handle
->handle
= new_handle_index
;
81 lock(&open_handles_lock
);
83 /* add new open handle struct to the open_handles list */
84 if (global_hba_head
->open_handles
== NULL
) {
85 global_hba_head
->open_handles
= new_open_handle
;
87 new_open_handle
->next
= global_hba_head
->open_handles
;
88 global_hba_head
->open_handles
= new_open_handle
;
91 unlock(&open_handles_lock
);
92 open_handle_index
= open_handle_index
+ 1;
93 if (open_handle_index
== 0) {
94 open_handle_index
= 1;
97 return (new_handle_index
);
101 * given a handle, returns the adapterIndex number.
103 * This functions checkes to see if the given handle corresponds to an open
104 * HBA. If it does, the adapterIndex is returned.
107 RetrieveIndex(HBA_HANDLE handle
)
110 struct open_handle
*open_handle_ptr
;
112 lock(&open_handles_lock
);
114 open_handle_ptr
= RetrieveOpenHandle(handle
);
116 unlock(&open_handles_lock
);
117 if (open_handle_ptr
== NULL
) {
121 return (open_handle_ptr
->adapterIndex
);
124 * Given a handle, returns the open_handle structure
125 * The routine assumes that the open_handles_lock has already
129 RetrieveOpenHandle(HBA_HANDLE handle
)
132 const char ROUTINE
[] = "RetrieveOpenHandle";
133 struct open_handle
*open_handle_ptr
= NULL
;
135 if (global_hba_head
== NULL
) {
136 log(LOG_DEBUG
, ROUTINE
, "No adapter is found.");
140 for (open_handle_ptr
= global_hba_head
->open_handles
;
141 open_handle_ptr
!= NULL
;
142 open_handle_ptr
= open_handle_ptr
->next
) {
143 if (open_handle_ptr
->handle
== handle
) {
148 return (open_handle_ptr
);
152 * Given an adapterIndex, this functions returns a pointer to the handle
153 * structure. This handle structure holds the hba's information
154 * Caller must take all_hbas_lock first.
157 RetrieveHandle(int index
)
159 struct sun_sas_hba
*hba_ptr
= NULL
;
161 for (hba_ptr
= global_hba_head
; hba_ptr
!= NULL
;
162 hba_ptr
= hba_ptr
->next
) {
163 if (hba_ptr
->index
== index
)
171 * Given an adapterIndex, this functions returns a pointer to the handle
172 * structure and extracts it from the global list.
174 * all_hbas_lock must be taken already.
177 ExtractHandle(int index
)
179 struct sun_sas_hba
*last
= NULL
;
180 struct sun_sas_hba
*hba_ptr
= NULL
;
182 for (hba_ptr
= global_hba_head
;
184 last
= hba_ptr
, hba_ptr
= hba_ptr
->next
) {
185 if (hba_ptr
->index
== index
) {
187 last
->next
= hba_ptr
->next
;
189 /* Hmm, must be the head of the list. */
190 global_hba_head
= hba_ptr
->next
;
192 hba_ptr
->next
= NULL
; /* Zap it to be safe */
202 * Given an handle, this functions returns a pointer to the handle structure
205 * Caller must take all_hbas_lock first.
208 Retrieve_Sun_sasHandle(HBA_HANDLE handle
)
210 const char ROUTINE
[] = "Retrieve_Sun_sasHandle";
211 struct sun_sas_hba
*handle_struct
= NULL
;
214 /* Retrieve fp device path from handle */
215 index
= RetrieveIndex(handle
);
217 log(LOG_DEBUG
, ROUTINE
,
218 "handle could not be found.");
219 return (handle_struct
);
221 lock(&open_handles_lock
);
222 handle_struct
= RetrieveHandle(index
);
223 if (handle_struct
== NULL
) {
224 log(LOG_DEBUG
, ROUTINE
,
225 "could not find index in the handle list.");
226 unlock(&open_handles_lock
);
227 return (handle_struct
);
229 unlock(&open_handles_lock
);
231 return (handle_struct
);
235 * Take a mutex lock. The routine will try, and if it fails,
236 * it will loop for a while and retry. If it fails many times,
237 * it will start writing to the log file.
244 const char ROUTINE
[] = "lock";
248 status
= mutex_trylock(mp
);
253 log(LOG_DEBUG
, ROUTINE
,
254 "Lock failed: fault 0x%x", mp
);
257 log(LOG_DEBUG
, ROUTINE
,
258 "Lock failed: invalid 0x%x", mp
);
261 if (loop
> DEADLOCK_WARNING
) {
262 log(LOG_DEBUG
, ROUTINE
,
263 "Lock busy, possible deadlock:0x%x",
268 log(LOG_DEBUG
, ROUTINE
,
269 "Lock failed: owner dead 0x%x",
273 log(LOG_DEBUG
, ROUTINE
,
274 "Lock failed: unmapped 0x%x",
277 case ENOTRECOVERABLE
:
278 log(LOG_DEBUG
, ROUTINE
,
279 "Lock failed: not recoverable 0x%x", mp
);
281 if (loop
> DEADLOCK_WARNING
) {
282 log(LOG_DEBUG
, ROUTINE
,
283 "Lock failed: %s 0x%x",
284 strerror(status
), mp
);
290 (void) sleep(LOCK_SLEEP
);
297 * Unlock a mutex lock.
302 (void) mutex_unlock(mp
);
307 * Get the Port WWN of the first adapter port. This routine
308 * is used by the old V1 interfaces so that they can call
309 * the new V2 interfaces and exhibit the same behavior.
310 * In the event of error the WWN will be zero.
312 * This function will transition to PAA state but it will not
313 * verfiy whether data is stale or not
316 getFirstAdapterPortWWN(HBA_HANDLE handle
)
318 const char ROUTINE
[] = "getFirstAdapterPortWWN";
319 HBA_WWN pwwn
= {0, 0, 0, 0, 0, 0, 0, 0};
320 struct sun_sas_hba
*hba_ptr
= NULL
;
324 lock(&all_hbas_lock
);
325 index
= RetrieveIndex(handle
);
326 lock(&open_handles_lock
);
327 hba_ptr
= RetrieveHandle(index
);
328 if (hba_ptr
== NULL
) {
329 log(LOG_DEBUG
, ROUTINE
, "Invalid handle %08lx", handle
);
330 unlock(&open_handles_lock
);
331 unlock(&all_hbas_lock
);
332 return (pwwn
); /* zero WWN */
335 /* Check for stale data */
336 status
= verifyAdapter(hba_ptr
);
337 if (status
!= HBA_STATUS_OK
) {
338 log(LOG_DEBUG
, ROUTINE
, "Verify adapter failed");
339 unlock(&open_handles_lock
);
340 unlock(&all_hbas_lock
);
344 if (hba_ptr
->first_port
== NULL
) {
345 /* This is probably an internal failure of the library */
346 if (hba_ptr
->device_path
) {
347 log(LOG_DEBUG
, ROUTINE
,
348 "Internal failure: Adapter %s contains no "
349 "port data", hba_ptr
->device_path
);
351 log(LOG_DEBUG
, ROUTINE
,
352 "Internal failure: Adapter at index %d contains "
353 " no support data", hba_ptr
->index
);
355 unlock(&open_handles_lock
);
356 unlock(&all_hbas_lock
);
357 return (pwwn
); /* zero WWN */
359 /* Set the WWN now and return it */
360 pwwn
= hba_ptr
->first_port
->port_attributes
.PortSpecificAttribute
.\
361 SASPort
->LocalSASAddress
;
362 unlock(&open_handles_lock
);
363 unlock(&all_hbas_lock
);
369 wwnConversion(uchar_t
*wwn
)
372 (void) memcpy(&tmp
, wwn
, sizeof (u_longlong_t
));
378 * Using ioctl to send uscsi command out
381 send_uscsi_cmd(const char *devpath
, struct uscsi_cmd
*ucmd
)
383 const char ROUTINE
[] = "send_uscsi_cmd";
387 /* set default timeout to 200 */
388 ucmd
->uscsi_timeout
= 200;
392 if ((fd
= open(devpath
, O_RDONLY
| O_NDELAY
)) == -1) {
393 log(LOG_DEBUG
, ROUTINE
,
394 "open devpath %s failed: %s", devpath
, strerror(errno
));
395 return (HBA_STATUS_ERROR
);
398 if (ioctl(fd
, USCSICMD
, ucmd
) == -1) {
399 if (errno
== EBUSY
) {
400 ret
= HBA_STATUS_ERROR_BUSY
;
401 } else if (errno
== EAGAIN
) {
402 ret
= HBA_STATUS_ERROR_TRY_AGAIN
;
404 ret
= HBA_STATUS_ERROR
;
406 log(LOG_DEBUG
, ROUTINE
,
407 "ioctl send uscsi to devpath: %s failed: %s",
408 devpath
, strerror(errno
));
415 return (HBA_STATUS_OK
);
419 * Check whether the given Domain Address is valid.
422 validateDomainAddress(struct sun_sas_port
*hba_port_ptr
, HBA_WWN DomainAddr
)
424 if (hba_port_ptr
->first_phy
!= NULL
&&
425 wwnConversion(hba_port_ptr
->first_phy
->
426 phy
.domainPortWWN
.wwn
) ==
427 wwnConversion(DomainAddr
.wwn
)) {
428 return (HBA_STATUS_OK
);
430 return (HBA_STATUS_ERROR
);