devtree_hba_disco.c revision f2e8686e6101ad6ab3df43205537e610151b5434
/*
* 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
*/
/*
*/
#include <sun_sas.h>
#include <inttypes.h>
#include <ctype.h>
/* free hba port info for the given hba */
static void
{
/* Free the nested structures (port and attached port) */
/* Free discovered port structure list. */
/* Free target mapping data list first. */
}
}
}
}
}
/*
* Internal routine for adding an HBA port
*/
static HBA_STATUS
{
const char ROUTINE[] = "add_hba_port_info";
struct sun_sas_port *port_ptr;
char *portDevpath;
int *propIntData;
char *propStringData;
int rval;
"Sun_sas handle ptr set to NULL.");
return (HBA_STATUS_ERROR_ARG);
}
sizeof (struct sun_sas_port))) == NULL) {
return (HBA_STATUS_ERROR);
}
== NULL) {
return (HBA_STATUS_ERROR);
}
"Unable to get device path from HBA Port Node.");
return (HBA_STATUS_ERROR);
}
/*
* Let's take a branch snap shot for pulling attributes.
* The attribute change doesn't invalidate devinfo cache snapshot.
* Phy info prop and num-phys can be obsolate when the same hba
* connected to the same expander(SIM) thus phy numbers are increased.
* Also the phy number may get decreased when a connection is removed
* while the iport still exist through another connection.
*/
if (branchNode == DI_NODE_NIL) {
/* something is wrong here. */
"Unable to take devinfoi branch snapshot on HBA port \"%s\""
return (HBA_STATUS_ERROR);
}
"HBA port node %s is either OFFLINE or DETACHED",
} else {
}
charptr++;
}
if (charptr[0] == 'c') {
} else {
}
} else {
}
"initiator-port", &propStringData);
if (rval < 0) {
"Unable to get initiator-port from HBA port node %s.",
return (HBA_STATUS_ERROR);
} else {
break;
}
}
if (*charptr != '\0') {
&tmpAddr, 8);
} else {
"No proper intiator-port prop value on HBA port %s",
}
}
"attached-port", &propStringData);
if (rval < 0) {
"Unable to get attached-port from HBA port node %s.",
return (HBA_STATUS_ERROR);
} else {
break;
}
}
if (*charptr != '\0') {
} else {
/* continue even if the attached port is NULL. */
"No proper attached-port prop value: "
"HBA port Local SAS Address(%016llx)",
}
}
"num-phys", &propIntData);
if (rval < 0) {
"Unable to get NumberofPhys from HBA port %s.",
return (HBA_STATUS_ERROR);
} else {
}
SASPort->NumberofPhys > 0) {
"Failed to get phy info on HBA port %s.",
return (HBA_STATUS_ERROR);
}
}
/* now done with prop checking. remove branchNode. */
/* Construct discovered target port. */
"Failed to get attached device info HBA port %s.",
return (HBA_STATUS_ERROR);
}
/* add new port onto hba handle list */
} else {
}
return (HBA_STATUS_OK);
}
{
const char ROUTINE[] = "refresh_hba";
int protocol = 0;
int *propIntData;
/*
* clean up existing hba port, discovered target, phy info.
* leave open handles intact.
*/
"HBA node doesn't have iport child.");
return (HBA_STATUS_ERROR);
}
"Unable to get supported-protocol from HBA node.");
} else {
protocol = *propIntData;
}
while (portNode != DI_NODE_NIL) {
"virtual-port", &propIntData) >= 0) {
if (*propIntData) {
/* ignore a virtual port. */
continue;
}
}
== HBA_STATUS_ERROR) {
return (HBA_STATUS_ERROR);
}
}
return (HBA_STATUS_OK);
}
/*
* Discover information for one HBA in the device tree.
* The di_node_t argument should be a node with smhba-supported prop set
* to true.
* Without iport support, the devinfo node will represent one port hba.
* This routine assumes the locks have been taken.
*/
{
const char ROUTINE[] = "devtree_get_one_hba";
int *propIntData = NULL;
char *hbaDevpath, *hba_driver;
int protocol = 0;
int hba_instance = -1;
if (hba_instance == -1) {
"portNode has instance of -1");
return (DI_WALK_CONTINUE);
}
"device path from hbaNode");
return (HBA_STATUS_ERROR);
}
/* check to see if this is a repeat HBA */
if (global_hba_head) {
for (hba_ptr = global_hba_head;
strlen(hbaDevpath))) == 0) {
" on hbaNode %s", hbaDevpath);
}
return (HBA_STATUS_OK);
}
}
}
/* this is a new hba */
sizeof (struct sun_sas_hba))) == NULL) {
return (HBA_STATUS_ERROR);
}
sizeof (new_hba->device_path));
/* Manufacturer */
} else {
}
/* SerialNumber */
} else {
}
/* Model */
} else {
}
/* FirmwareVersion */
"Property \"%s\" not found for device \"%s\"",
} else {
}
/* HardwareVersion */
"Property \"%s\" not found for device \"%s\"",
} else {
}
/* DriverVersion */
"Property \"%s\" not found for device \"%s\"",
} else {
}
"Unable to get supported-protocol from HBA node.");
} else {
protocol = *propIntData;
}
/* We don't use these */
} else {
"HBA driver name not found for device \"%s\"",
}
/*
* Name the adapter: like SUNW-pmcs-1
* Using di_instance number as the suffix for the name for persistent
* among rebooting.
*/
"HBA driver doesn't have iport child. \"%s\"",
/* continue on with an hba without any port. */
/*
* add newly created handle into global_hba_head list
*/
if (global_hba_head != NULL) {
/*
* Make sure to move the open_handles list to back to
* the head if it's there (for refresh scenario)
*/
if (global_hba_head->open_handles) {
}
/* Now bump the new one to the head of the list */
} else {
}
return (HBA_STATUS_OK);
}
while (portNode != DI_NODE_NIL) {
"virtual-port", &propIntData) >= 0) {
if (*propIntData) {
/* ignore a virtual port. */
continue;
}
}
== HBA_STATUS_ERROR) {
return (HBA_STATUS_ERROR);
}
}
/*
* add newly created handle into global_hba_head list
*/
if (global_hba_head != NULL) {
/*
* Make sure to move the open_handles list to back to the
* head if it's there (for refresh scenario)
*/
if (global_hba_head->open_handles) {
}
/* Now bump the new one to the head of the list */
} else {
}
return (HBA_STATUS_OK);
}
/*
* Discover information for all HBAs found on the system.
* The di_node_t argument should be the root of the device tree.
* This routine assumes the locks have been taken
*/
static int
{
const char ROUTINE[] = "lookup_smhba_sas_hba";
/* Skip stub(instance -1) nodes */
if (IS_STUB_NODE(node)) {
return (DI_WALK_CONTINUE);
}
"sm-hba-supported", &propData);
if (rval >= 0) {
if (*propData) {
/* add the hba to the hba list */
}
/* Found a node. No need to walk the child. */
return (DI_WALK_PRUNECHILD);
}
}
return (DI_WALK_CONTINUE);
}
/*
* Discover information for all HBAs found on the system.
* The di_node_t argument should be the root of the device tree.
* This routine assumes the locks have been taken
*/
{
const char ROUTINE[] = "devtree_get_all_hbas";
return (HBA_STATUS_ERROR);
}
if (rv == 0) {
/*
* Now determine what status code to return, taking
* partial failure scenarios into consideration.
*
* If we have at least one working HBA, then we return an
* OK status. If we have no good HBAs, but at least one
* failed HBA, we return an ERROR status. If we have
* no HBAs and no failures, we return OK.
*/
if (global_hba_head) {
/*
* We've got at least one HBA and possibly some
* failures.
*/
ret = HBA_STATUS_OK;
/* We have no HBAs but have failures */
} else {
/* We have no HBAs and no failures */
ret = HBA_STATUS_OK;
}
}
if (ret == HBA_STATUS_OK)
(void) registerSysevent();
return (ret);
}