xref: /titanic_51/usr/src/lib/sun_sas/common/Sun_sasGetPhyStatistics.c (revision 9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bb)
1*9e86db79SHyon Kim /*
2*9e86db79SHyon Kim  * CDDL HEADER START
3*9e86db79SHyon Kim  *
4*9e86db79SHyon Kim  * The contents of this file are subject to the terms of the
5*9e86db79SHyon Kim  * Common Development and Distribution License (the "License").
6*9e86db79SHyon Kim  * You may not use this file except in compliance with the License.
7*9e86db79SHyon Kim  *
8*9e86db79SHyon Kim  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9e86db79SHyon Kim  * or http://www.opensolaris.org/os/licensing.
10*9e86db79SHyon Kim  * See the License for the specific language governing permissions
11*9e86db79SHyon Kim  * and limitations under the License.
12*9e86db79SHyon Kim  *
13*9e86db79SHyon Kim  * When distributing Covered Code, include this CDDL HEADER in each
14*9e86db79SHyon Kim  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9e86db79SHyon Kim  * If applicable, add the following below this CDDL HEADER, with the
16*9e86db79SHyon Kim  * fields enclosed by brackets "[]" replaced with your own identifying
17*9e86db79SHyon Kim  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9e86db79SHyon Kim  *
19*9e86db79SHyon Kim  * CDDL HEADER END
20*9e86db79SHyon Kim  */
21*9e86db79SHyon Kim 
22*9e86db79SHyon Kim /*
23*9e86db79SHyon Kim  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*9e86db79SHyon Kim  * Use is subject to license terms.
25*9e86db79SHyon Kim  */
26*9e86db79SHyon Kim 
27*9e86db79SHyon Kim #include <kstat.h>
28*9e86db79SHyon Kim #include <sun_sas.h>
29*9e86db79SHyon Kim 
30*9e86db79SHyon Kim /*
31*9e86db79SHyon Kim  * Retrieves the statistics for a specified port.phy on an adapter
32*9e86db79SHyon Kim  */
33*9e86db79SHyon Kim HBA_STATUS Sun_sasGetPhyStatistics(HBA_HANDLE handle,
34*9e86db79SHyon Kim     HBA_UINT32 port, HBA_UINT32 phy, SMHBA_PHYSTATISTICS *pStatistics) {
35*9e86db79SHyon Kim 	const char	ROUTINE[] = "Sun_sasGetPhyStatistics";
36*9e86db79SHyon Kim 	HBA_STATUS		status = HBA_STATUS_OK;
37*9e86db79SHyon Kim 	struct sun_sas_hba	*hba_ptr;
38*9e86db79SHyon Kim 	struct sun_sas_port	*hba_port_ptr;
39*9e86db79SHyon Kim 	struct phy_info		*phy_ptr;
40*9e86db79SHyon Kim 	PSMHBA_SASPHYSTATISTICS	psas;
41*9e86db79SHyon Kim 	kstat_ctl_t		*kc;
42*9e86db79SHyon Kim 	kstat_t			*ksp;
43*9e86db79SHyon Kim 	kstat_named_t		*kname;
44*9e86db79SHyon Kim 	char			*charptr, path[MAXPATHLEN + 1];
45*9e86db79SHyon Kim 	char			*driver_name, kstat_name[256];
46*9e86db79SHyon Kim 	di_node_t		node;
47*9e86db79SHyon Kim 	int			instance = 0;
48*9e86db79SHyon Kim 	int			i;
49*9e86db79SHyon Kim 	uint64_t		iport_wwn;
50*9e86db79SHyon Kim 
51*9e86db79SHyon Kim 	/* Validate the arguments */
52*9e86db79SHyon Kim 	if (pStatistics == NULL) {
53*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
54*9e86db79SHyon Kim 		    "NULL Phy Statistics buffer of phyIndex: %08lx", phy);
55*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR_ARG);
56*9e86db79SHyon Kim 	}
57*9e86db79SHyon Kim 	psas = pStatistics->SASPhyStatistics;
58*9e86db79SHyon Kim 	if (psas == NULL) {
59*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
60*9e86db79SHyon Kim 		    "NULL SAS Phy Statistics buffer of phyIndex: %08lx", phy);
61*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR_ARG);
62*9e86db79SHyon Kim 	}
63*9e86db79SHyon Kim 
64*9e86db79SHyon Kim 	lock(&all_hbas_lock);
65*9e86db79SHyon Kim 
66*9e86db79SHyon Kim 	if ((hba_ptr = Retrieve_Sun_sasHandle(handle)) == NULL) {
67*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
68*9e86db79SHyon Kim 		    "Invalid HBA handler %08lx of phyIndex: %08lx",
69*9e86db79SHyon Kim 		    handle, phy);
70*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
71*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR_INVALID_HANDLE);
72*9e86db79SHyon Kim 	}
73*9e86db79SHyon Kim 
74*9e86db79SHyon Kim 	/* Check for stale data */
75*9e86db79SHyon Kim 	status = verifyAdapter(hba_ptr);
76*9e86db79SHyon Kim 	if (status != HBA_STATUS_OK) {
77*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
78*9e86db79SHyon Kim 		    "Verify Adapter failed for phyIndex: %08lx", phy);
79*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
80*9e86db79SHyon Kim 		return (status);
81*9e86db79SHyon Kim 	}
82*9e86db79SHyon Kim 
83*9e86db79SHyon Kim 	for (hba_port_ptr = hba_ptr->first_port;
84*9e86db79SHyon Kim 	    hba_port_ptr != NULL;
85*9e86db79SHyon Kim 	    hba_port_ptr = hba_port_ptr->next) {
86*9e86db79SHyon Kim 		if (hba_port_ptr->index == port) {
87*9e86db79SHyon Kim 			break;
88*9e86db79SHyon Kim 		}
89*9e86db79SHyon Kim 	}
90*9e86db79SHyon Kim 
91*9e86db79SHyon Kim 	if (hba_port_ptr == NULL) {
92*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
93*9e86db79SHyon Kim 		    "Invalid port index of phyIndex: %08lx", phy);
94*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
95*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
96*9e86db79SHyon Kim 	}
97*9e86db79SHyon Kim 
98*9e86db79SHyon Kim 	if (phy >= hba_port_ptr->port_attributes.PortSpecificAttribute.
99*9e86db79SHyon Kim 	    SASPort->NumberofPhys) {
100*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy);
101*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
102*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
103*9e86db79SHyon Kim 	}
104*9e86db79SHyon Kim 
105*9e86db79SHyon Kim 	/* We need to find out the phy identifier. */
106*9e86db79SHyon Kim 	for (phy_ptr = hba_port_ptr->first_phy;
107*9e86db79SHyon Kim 	    phy_ptr != NULL;
108*9e86db79SHyon Kim 	    phy_ptr = phy_ptr->next) {
109*9e86db79SHyon Kim 		if (phy == phy_ptr->index)
110*9e86db79SHyon Kim 			break;
111*9e86db79SHyon Kim 	}
112*9e86db79SHyon Kim 
113*9e86db79SHyon Kim 	if (phy_ptr == NULL) {
114*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy);
115*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
116*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
117*9e86db79SHyon Kim 	}
118*9e86db79SHyon Kim 
119*9e86db79SHyon Kim 	/*
120*9e86db79SHyon Kim 	 * for statistics that are not supported, its bits should all be
121*9e86db79SHyon Kim 	 * set to -1
122*9e86db79SHyon Kim 	 */
123*9e86db79SHyon Kim 	(void) memset(pStatistics->SASPhyStatistics, 0xff,
124*9e86db79SHyon Kim 	    sizeof (SMHBA_SASPHYSTATISTICS));
125*9e86db79SHyon Kim 
126*9e86db79SHyon Kim 
127*9e86db79SHyon Kim 	/* First, we need the deivce path to locate the devinfo node. */
128*9e86db79SHyon Kim 	(void *) strlcpy(path, hba_port_ptr->device_path,
129*9e86db79SHyon Kim 	    sizeof (path));
130*9e86db79SHyon Kim 	charptr = strrchr(path, ':');
131*9e86db79SHyon Kim 	if (charptr) {
132*9e86db79SHyon Kim 		*charptr = '\0';
133*9e86db79SHyon Kim 	}
134*9e86db79SHyon Kim 
135*9e86db79SHyon Kim 	errno = 0;
136*9e86db79SHyon Kim 
137*9e86db79SHyon Kim 	(void *) memset(kstat_name, 0, sizeof (kstat_name));
138*9e86db79SHyon Kim 	node = di_init(path, DINFOCPYONE);
139*9e86db79SHyon Kim 	if (node == DI_NODE_NIL) {
140*9e86db79SHyon Kim 		di_fini(node);
141*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
142*9e86db79SHyon Kim 		    "Unable to take devinfo snapshot on HBA \"%s\" "
143*9e86db79SHyon Kim 		    "for phyIndex: %08lx due to %s",
144*9e86db79SHyon Kim 		    path, phy, strerror(errno));
145*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
146*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
147*9e86db79SHyon Kim 	}
148*9e86db79SHyon Kim 
149*9e86db79SHyon Kim 	/*
150*9e86db79SHyon Kim 	 * Then we could fetch the instance number and driver name of this
151*9e86db79SHyon Kim 	 * device.
152*9e86db79SHyon Kim 	 */
153*9e86db79SHyon Kim 	instance = di_instance(node);
154*9e86db79SHyon Kim 	if (instance == -1) {
155*9e86db79SHyon Kim 		di_fini(node);
156*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
157*9e86db79SHyon Kim 		    "An instance number has not been assigned to the "
158*9e86db79SHyon Kim 		    "device \"%s\" when get phyIndex: %08lx", path, phy);
159*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
160*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
161*9e86db79SHyon Kim 	}
162*9e86db79SHyon Kim 
163*9e86db79SHyon Kim 	driver_name = di_driver_name(node);
164*9e86db79SHyon Kim 	if (driver_name == NULL) {
165*9e86db79SHyon Kim 		di_fini(node);
166*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
167*9e86db79SHyon Kim 		    "No driver bound to this device \"%s\" "
168*9e86db79SHyon Kim 		    "when get phyIndex: %08lx",
169*9e86db79SHyon Kim 		    path, phy);
170*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
171*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
172*9e86db79SHyon Kim 	}
173*9e86db79SHyon Kim 
174*9e86db79SHyon Kim 	di_fini(node);
175*9e86db79SHyon Kim 
176*9e86db79SHyon Kim 	iport_wwn = wwnConversion(hba_port_ptr->port_attributes.\
177*9e86db79SHyon Kim 	    PortSpecificAttribute.SASPort->LocalSASAddress.wwn);
178*9e86db79SHyon Kim 
179*9e86db79SHyon Kim 	/*
180*9e86db79SHyon Kim 	 * Construct the kstat name here.
181*9e86db79SHyon Kim 	 */
182*9e86db79SHyon Kim 	(void) snprintf(kstat_name, sizeof (kstat_name), "%s.%016llx.%u.%u",
183*9e86db79SHyon Kim 	    driver_name, iport_wwn, instance, phy_ptr->phy.PhyIdentifier);
184*9e86db79SHyon Kim 
185*9e86db79SHyon Kim 	/* retrieve all the statistics from kstat. */
186*9e86db79SHyon Kim 	kc = kstat_open();
187*9e86db79SHyon Kim 	if (kc == NULL) {
188*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
189*9e86db79SHyon Kim 		    "kstat_open failed due to \"%s\" of phyIndex: %08lx",
190*9e86db79SHyon Kim 		    strerror(errno), phy);
191*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
192*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
193*9e86db79SHyon Kim 	}
194*9e86db79SHyon Kim 	ksp = kstat_lookup(kc, NULL, -1, kstat_name);
195*9e86db79SHyon Kim 	if (ksp == NULL) {
196*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
197*9e86db79SHyon Kim 		    "No matching kstat name found for \"%s\" "
198*9e86db79SHyon Kim 		    "of phyIndex: %08lx",
199*9e86db79SHyon Kim 		    kstat_name, phy);
200*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
201*9e86db79SHyon Kim 		(void) kstat_close(kc);
202*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
203*9e86db79SHyon Kim 	}
204*9e86db79SHyon Kim 	/* Found the phy we're looking for. */
205*9e86db79SHyon Kim 	if (kstat_read(kc, ksp, NULL) == -1) {
206*9e86db79SHyon Kim 		log(LOG_DEBUG, ROUTINE,
207*9e86db79SHyon Kim 		    "error reading kstat data due to \"%s\" "
208*9e86db79SHyon Kim 		    "of phyIndex: %08lx",
209*9e86db79SHyon Kim 		    strerror(errno), phy);
210*9e86db79SHyon Kim 		unlock(&all_hbas_lock);
211*9e86db79SHyon Kim 		(void) kstat_close(kc);
212*9e86db79SHyon Kim 		return (HBA_STATUS_ERROR);
213*9e86db79SHyon Kim 	}
214*9e86db79SHyon Kim 
215*9e86db79SHyon Kim 	kname = (kstat_named_t *)ksp->ks_data;
216*9e86db79SHyon Kim 	for (i = 0; i < ksp->ks_ndata; i++, kname++) {
217*9e86db79SHyon Kim 		if (strcmp(kname->name,
218*9e86db79SHyon Kim 		    "SecondsSinceLastReset") == 0) {
219*9e86db79SHyon Kim 		    psas->SecondsSinceLastReset = kname->value.ull;
220*9e86db79SHyon Kim 			continue;
221*9e86db79SHyon Kim 		}
222*9e86db79SHyon Kim 		if (strcmp(kname->name, "TxFrames") == 0) {
223*9e86db79SHyon Kim 			psas->TxFrames = kname->value.ull;
224*9e86db79SHyon Kim 			continue;
225*9e86db79SHyon Kim 		}
226*9e86db79SHyon Kim 		if (strcmp(kname->name, "RxFrames") == 0) {
227*9e86db79SHyon Kim 			psas->RxFrames = kname->value.ull;
228*9e86db79SHyon Kim 			continue;
229*9e86db79SHyon Kim 		}
230*9e86db79SHyon Kim 		if (strcmp(kname->name, "TxWords") == 0) {
231*9e86db79SHyon Kim 			psas->TxWords = kname->value.ull;
232*9e86db79SHyon Kim 			continue;
233*9e86db79SHyon Kim 		}
234*9e86db79SHyon Kim 		if (strcmp(kname->name, "RxWords") == 0) {
235*9e86db79SHyon Kim 			psas->RxWords = kname->value.ull;
236*9e86db79SHyon Kim 			continue;
237*9e86db79SHyon Kim 		}
238*9e86db79SHyon Kim 		if (strcmp(kname->name, "InvalidDwordCount") == 0) {
239*9e86db79SHyon Kim 			psas->InvalidDwordCount = kname->value.ull;
240*9e86db79SHyon Kim 			continue;
241*9e86db79SHyon Kim 		}
242*9e86db79SHyon Kim 		if (strcmp(kname->name, "RunningDisparityErrorCount") == 0) {
243*9e86db79SHyon Kim 			psas->RunningDisparityErrorCount = kname->value.ull;
244*9e86db79SHyon Kim 			continue;
245*9e86db79SHyon Kim 		}
246*9e86db79SHyon Kim 		if (strcmp(kname->name, "LossofDwordSyncCount") == 0) {
247*9e86db79SHyon Kim 			psas->LossofDwordSyncCount = kname->value.ull;
248*9e86db79SHyon Kim 			continue;
249*9e86db79SHyon Kim 		}
250*9e86db79SHyon Kim 		if (strcmp(kname->name, "PhyResetProblemCount") == 0) {
251*9e86db79SHyon Kim 			psas->PhyResetProblemCount = kname->value.ull;
252*9e86db79SHyon Kim 		}
253*9e86db79SHyon Kim 	}
254*9e86db79SHyon Kim 	unlock(&all_hbas_lock);
255*9e86db79SHyon Kim 	(void) kstat_close(kc);
256*9e86db79SHyon Kim 
257*9e86db79SHyon Kim 	return (HBA_STATUS_OK);
258*9e86db79SHyon Kim }
259