devtree_device_disco.c revision b045990893825c31e176b319ae8cc4ef32115d17
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
#include <sun_sas.h>
#include <inttypes.h>
#include <ctype.h>
#include <libdevid.h>
/*
* Get the preferred minor node for the given path.
* ":n" for tapes, ":c,raw" for disks,
* and ":0" for enclosures.
*/
static void
{
const char ROUTINE[] = "get_minor";
char fullpath[MAXPATHLEN];
int fd;
"/enclosure@"))) {
devpath, ":0");
/* reset errno to 0 */
errno = 0;
/*
* :0 minor doesn't exist. assume bound to sgen driver
* and :ses minor exist.
*/
}
} else {
}
} else {
devpath);
minor[0] = '\0';
}
}
/*
* Free the attached port allocation.
*/
static void
{
/* Free target mapping data list first. */
}
}
}
/*
* Fill domainPortWWN.
* should be called after completing discovered port discovery.
*/
void
{
const char ROUTINE[] = "fillDomainPortWWN";
struct sun_sas_port *disco_port_ptr;
uint64_t domainPort = 0;
struct ScsiEntryList *mapping_ptr;
LocalSASAddress.wwn)) {
(void) memcpy(&domainPort,
break;
}
}
if (domainPort == 0) {
if (port_ptr->first_attached_port) {
/*
* there is no expander device attached on an HBA port
* domainPortWWN should not stay to 0 since multiple
* hba ports can have the same LocalSASAddres within
* the same HBA.
* Set the SAS address of direct attached target.
*/
LocalSASAddress.wwn) ==
(void) memcpy(&domainPort,
} else {
/*
* SAS address is not upstream connected.
* domainPortWWN stays as 0.
*/
"DomainPortWWN is not set. "
"Device(s) are visible on the HBA port "
"but there is no expander or directly "
"attached port with matching upsteam "
"attached SAS address for "
"HBA port (Local SAS Address: %016llx).",
return;
}
} else {
/*
* There existss an iport without properly configured
* child smp ndoes or child node or pathinfo.
* domainPortWWN stays as 0.
*/
"DomainPortWWN is not set. No properly "
"configured smp or directly attached port "
"found on HBA port(Local SAS Address: %016llx).",
return;
}
}
/* fill up phy info */
}
/* fill up target mapping */
mapping_ptr != NULL;
}
}
}
/*
* Finds attached device(target) from devinfo node.
*/
static HBA_STATUS
{
const char ROUTINE[] = "get_attached_devices_info";
char *propStringData = NULL;
int *propIntData = NULL;
char *guidStr;
char *unit_address;
char *charptr;
struct ScsiEntryList *mapping_ptr;
struct sun_sas_port *disco_port_ptr;
int port_state = HBA_PORTSTATE_ONLINE;
return (HBA_STATUS_ERROR);
}
"Device in device tree has no path. Skipping.");
return (HBA_STATUS_ERROR);
}
"dev node (%s) returned instance of -1 or is retired. "
" Skipping.", devpath);
return (HBA_STATUS_OK);
}
/* when node is not attached and online, set the state to offline. */
"dev node (%s) is either OFFLINE or DETACHED",
devpath);
}
/* add the "/devices" in the begining at the end */
*charptr = '\0';
}
break;
}
}
if (*charptr != '\0') {
} else {
"No proper target port info on unit address of %s",
fullpath);
return (HBA_STATUS_ERROR);
}
} else {
"Fail to get unit address of %s.",
fullpath);
return (HBA_STATUS_ERROR);
}
&propStringData) != -1) {
break;
}
}
if (*charptr != '\0') {
/* check the attached address of hba port. */
&tmpAddr, 8) == 0) {
/*
* When attached-port is set from iport
* attached-port prop, we do the cross check
* with device's own SAS address.
*
* If not set, we store device's own SAS
* address to iport attached SAS address.
*/
/* verify the Attaached SAS Addr. */
/* indentation move begin. */
"iport attached-port(%016llx) do not"
" match with level 1 Local"
" SAS address(%016llx).",
return (HBA_STATUS_ERROR);
/* indentation move ends. */
}
} else {
}
}
} else {
"No proper attached SAS address value on device %s",
fullpath);
return (HBA_STATUS_ERROR);
}
} else {
"Property AttachedSASAddress not found for device \"%s\"",
fullpath);
return (HBA_STATUS_ERROR);
}
/*
* walk the disco list to make sure that there isn't a matching
* port and node wwn or a matching device path
*/
portfound = 0;
disco_port_ptr != NULL;
/*
* found matching disco_port
* look for matching device path
*/
portfound = 1;
mapping_ptr != NULL;
OSDeviceName, devpath) != 0) {
"Found an already discovered "
"device %s.", fullpath);
return (HBA_STATUS_OK);
}
}
if (portfound == 1) {
break;
}
}
}
if (portfound == 0) {
/*
* there are no matching SAS address.
* this must be a new device
*/
sizeof (struct sun_sas_port))) == NULL) {
return (HBA_STATUS_ERROR);
}
sizeof (struct SMHBA_SAS_Port))) == NULL) {
OUT_OF_MEMORY("add_hba_port_info");
return (HBA_STATUS_ERROR);
}
/* Default to unknown until we figure out otherwise */
"variant", &propStringData);
if (rval < 0) {
/* check if it is SMP target */
/* indentation changed here. */
/* indentation change ends here. */
} else {
/* indentation changed here. */
/* indentation change ends here. */
}
} else {
}
} else {
} else {
"Unexpected variant prop value %s found on",
/*
* Port type will be 0
* which is not valid type.
*/
}
}
/* SMP device was handled already */
/* indentation change due to ctysle check on sizeof. */
}
/* add new discovered port into the list */
disco_port_ptr->index = 0;
} else {
}
}
/* No mapping data for expander device. return ok here. */
return (HBA_STATUS_OK);
}
return (HBA_STATUS_ERROR);
}
&propIntData) != -1) {
} else {
charptr++;
} else {
"Failed to get LUN from the unit address of device "
" %s.", fullpath);
return (HBA_STATUS_ERROR);
}
}
/* get TargetLun(SAM-LUN). */
&propInt64Data) != -1) {
&samLun, 8);
} else {
"No lun64 prop found on device %s.", fullpath);
return (HBA_STATUS_ERROR);
}
} else {
}
/* get ScsiBusNumber */
/* Store the devices path for now. We'll convert to /dev later */
/* reset errno to 0 */
errno = 0;
&propStringData) != -1) {
} else {
/*
* Note:
* if logical unit associated page 83 id
* descriptor is not avaialble for the device
* devid_to_guid returns NULL with errno 0.
*/
"failed to get devid guid on (%s) : %s",
}
} else {
/*
* device may not support proper page 83 id descriptor.
* leave LUID attribute to NULL and continue.
*/
"failed to decode devid prop on (%s) : %s",
}
} else {
/* leave LUID attribute to NULL and continue. */
"failed to get devid prop on (%s) : %s",
}
} else {
}
return (HBA_STATUS_OK);
}
/*
* Finds attached device(target) from pathinfo node.
*/
static HBA_STATUS
{
char ROUTINE[] = "get_attached_paths_info";
char *propStringData = NULL;
int *propIntData = NULL;
char *guidStr;
char *unit_address;
char *charptr;
char *clientdevpath = NULL;
char *pathdevpath = NULL;
struct ScsiEntryList *mapping_ptr;
struct sun_sas_port *disco_port_ptr;
di_path_state_t state = 0;
int port_state = HBA_PORTSTATE_ONLINE;
return (HBA_STATUS_ERROR);
}
/* if not null, free before return. */
/* when node is not attached and online, set the state to offline. */
if ((state == DI_PATH_STATE_OFFLINE) ||
(state == DI_PATH_STATE_FAULT)) {
"path node (%s) is either OFFLINE or FAULT state",
}
if (di_retired(clientnode)) {
"client node of path (%s) is retired. Skipping.",
"(missing device path)");
return (HBA_STATUS_OK);
}
"Client device of path (%s) has no path. Skipping.",
"(missing device path)");
return (HBA_STATUS_ERROR);
}
} else {
"Failed to get client device from a path (%s).",
"(missing device path)");
return (HBA_STATUS_ERROR);
}
/* add the "/devices" in the begining and the :devctl at the end */
*charptr = '\0';
}
break;
}
}
if (charptr != '\0') {
} else {
"No proper target port info on unit address of "
"(missing device path)");
return (HBA_STATUS_ERROR);
}
} else {
"(missing device path)");
return (HBA_STATUS_ERROR);
}
&propStringData) != -1) {
break;
}
}
if (*charptr != '\0') {
/* check the attached address of hba port. */
/* verify the attaached SAS Addr. */
/* indentation move begin. */
"iport attached-port(%016llx) do not"
" match with level 1 Local"
" SAS address(%016llx).",
if (pathdevpath)
return (HBA_STATUS_ERROR);
/* indentation move ends. */
}
} else {
/* store the Attaached SAS Addr. */
}
}
} else {
"No proper attached SAS address value of path (%s)",
"(missing device path)");
return (HBA_STATUS_ERROR);
}
} else {
"Property attached-port not found for path (%s)",
"(missing device path)");
return (HBA_STATUS_ERROR);
}
/*
* walk the disco list to make sure that there isn't a matching
* port and node wwn or a matching device path
*/
portfound = 0;
disco_port_ptr != NULL;
/*
* found matching disco_port
* look for matching device path
*/
portfound = 1;
mapping_ptr != NULL;
OSDeviceName, clientdevpath) != 0) {
"Found an already discovered "
"device %s.", clientdevpath);
if (pathdevpath)
return (HBA_STATUS_OK);
}
}
if (portfound == 1) {
break;
}
}
}
if (portfound == 0) {
/*
* there are no matching SAS address.
* this must be a new device
*/
sizeof (struct sun_sas_port))) == NULL) {
return (HBA_STATUS_ERROR);
}
sizeof (struct SMHBA_SAS_Port))) == NULL) {
OUT_OF_MEMORY("add_hba_port_info");
return (HBA_STATUS_ERROR);
}
/* Default to unknown until we figure out otherwise */
&propStringData) != -1) {
} else {
"Unexpected variant prop value %s found on",
" path (%s)", propStringData,
"(missing device path)");
/*
* Port type will be 0
* which is not valid type.
*/
}
} else {
}
/* indentation change due to ctysle check on sizeof. */
if (pathdevpath != NULL) {
}
}
/* add new discovered port into the list */
disco_port_ptr->index = 0;
} else {
}
}
return (HBA_STATUS_ERROR);
}
} else {
charptr++;
} else {
"Failed to get LUN from unit address of path(%s).",
"(missing device path)");
return (HBA_STATUS_ERROR);
}
}
/* Get TargetLun(SAM LUN). */
&samLun, 8);
} else {
"(missing device path)");
return (HBA_STATUS_ERROR);
}
} else {
}
/* get ScsiBusNumber */
/* Store the devices path for now. We'll convert to /dev later */
/* get luid. */
errno = 0; /* reset errno to 0 */
&propStringData) != -1) {
} else {
/*
* Note:
* if logical unit associated page 83 id
* descriptor is not avaialble for the device
* devid_to_guid returns NULL with errno 0.
*/
"failed to get devid guid on (%s)",
" associated with path(%s) : %s",
"(missing device path)",
}
} else {
/*
* device may not support proper page 83 id descriptor.
* leave LUID attribute to NULL and continue.
*/
"failed to decode devid prop on (%s)",
" associated with path(%s) : %s",
"(missing device path)",
}
} else {
/* leave LUID attribute to NULL and continue. */
" associated with path(%s) : %s", clientdevpath,
}
} else {
}
return (HBA_STATUS_OK);
}
/*
* walks the devinfo tree retrieving all hba information
*/
extern HBA_STATUS
{
const char ROUTINE[] = "devtree_attached_devices";
/* child should be device */
"No devinfo child on the HBA port node.");
}
DI_PATH_NIL) {
"No pathinfo node on the HBA port node.");
}
return (HBA_STATUS_OK);
}
while (nodechild != DI_NODE_NIL) {
!= HBA_STATUS_OK) {
break;
}
}
while (path != DI_PATH_NIL) {
!= HBA_STATUS_OK) {
break;
}
}
return (HBA_STATUS_OK);
}