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.
31 * Retrieves the statistics for a specified port.phy on an adapter
33 HBA_STATUS
Sun_sasGetPhyStatistics(HBA_HANDLE handle
,
34 HBA_UINT32 port
, HBA_UINT32 phy
, SMHBA_PHYSTATISTICS
*pStatistics
) {
35 const char ROUTINE
[] = "Sun_sasGetPhyStatistics";
36 HBA_STATUS status
= HBA_STATUS_OK
;
37 struct sun_sas_hba
*hba_ptr
;
38 struct sun_sas_port
*hba_port_ptr
;
39 struct phy_info
*phy_ptr
;
40 PSMHBA_SASPHYSTATISTICS psas
;
44 char *charptr
, path
[MAXPATHLEN
+ 1];
45 char *driver_name
, kstat_name
[256];
51 /* Validate the arguments */
52 if (pStatistics
== NULL
) {
53 log(LOG_DEBUG
, ROUTINE
,
54 "NULL Phy Statistics buffer of phyIndex: %08lx", phy
);
55 return (HBA_STATUS_ERROR_ARG
);
57 psas
= pStatistics
->SASPhyStatistics
;
59 log(LOG_DEBUG
, ROUTINE
,
60 "NULL SAS Phy Statistics buffer of phyIndex: %08lx", phy
);
61 return (HBA_STATUS_ERROR_ARG
);
66 if ((hba_ptr
= Retrieve_Sun_sasHandle(handle
)) == NULL
) {
67 log(LOG_DEBUG
, ROUTINE
,
68 "Invalid HBA handler %08lx of phyIndex: %08lx",
70 unlock(&all_hbas_lock
);
71 return (HBA_STATUS_ERROR_INVALID_HANDLE
);
74 /* Check for stale data */
75 status
= verifyAdapter(hba_ptr
);
76 if (status
!= HBA_STATUS_OK
) {
77 log(LOG_DEBUG
, ROUTINE
,
78 "Verify Adapter failed for phyIndex: %08lx", phy
);
79 unlock(&all_hbas_lock
);
83 for (hba_port_ptr
= hba_ptr
->first_port
;
85 hba_port_ptr
= hba_port_ptr
->next
) {
86 if (hba_port_ptr
->index
== port
) {
91 if (hba_port_ptr
== NULL
) {
92 log(LOG_DEBUG
, ROUTINE
,
93 "Invalid port index of phyIndex: %08lx", phy
);
94 unlock(&all_hbas_lock
);
95 return (HBA_STATUS_ERROR_ILLEGAL_INDEX
);
98 if (phy
>= hba_port_ptr
->port_attributes
.PortSpecificAttribute
.
99 SASPort
->NumberofPhys
) {
100 log(LOG_DEBUG
, ROUTINE
, "Invalid phy index %08lx", phy
);
101 unlock(&all_hbas_lock
);
102 return (HBA_STATUS_ERROR_ILLEGAL_INDEX
);
105 /* We need to find out the phy identifier. */
106 for (phy_ptr
= hba_port_ptr
->first_phy
;
108 phy_ptr
= phy_ptr
->next
) {
109 if (phy
== phy_ptr
->index
)
113 if (phy_ptr
== NULL
) {
114 log(LOG_DEBUG
, ROUTINE
, "Invalid phy index %08lx", phy
);
115 unlock(&all_hbas_lock
);
116 return (HBA_STATUS_ERROR_ILLEGAL_INDEX
);
120 * for statistics that are not supported, its bits should all be
123 (void) memset(pStatistics
->SASPhyStatistics
, 0xff,
124 sizeof (SMHBA_SASPHYSTATISTICS
));
127 /* First, we need the deivce path to locate the devinfo node. */
128 (void *) strlcpy(path
, hba_port_ptr
->device_path
,
130 charptr
= strrchr(path
, ':');
137 memset(kstat_name
, 0, sizeof (kstat_name
));
138 node
= di_init(path
, DINFOCPYONE
);
139 if (node
== DI_NODE_NIL
) {
141 log(LOG_DEBUG
, ROUTINE
,
142 "Unable to take devinfo snapshot on HBA \"%s\" "
143 "for phyIndex: %08lx due to %s",
144 path
, phy
, strerror(errno
));
145 unlock(&all_hbas_lock
);
146 return (HBA_STATUS_ERROR
);
150 * Then we could fetch the instance number and driver name of this
153 instance
= di_instance(node
);
154 if (instance
== -1) {
156 log(LOG_DEBUG
, ROUTINE
,
157 "An instance number has not been assigned to the "
158 "device \"%s\" when get phyIndex: %08lx", path
, phy
);
159 unlock(&all_hbas_lock
);
160 return (HBA_STATUS_ERROR
);
163 driver_name
= di_driver_name(node
);
164 if (driver_name
== NULL
) {
166 log(LOG_DEBUG
, ROUTINE
,
167 "No driver bound to this device \"%s\" "
168 "when get phyIndex: %08lx",
170 unlock(&all_hbas_lock
);
171 return (HBA_STATUS_ERROR
);
176 iport_wwn
= wwnConversion(hba_port_ptr
->port_attributes
.\
177 PortSpecificAttribute
.SASPort
->LocalSASAddress
.wwn
);
180 * Construct the kstat name here.
182 (void) snprintf(kstat_name
, sizeof (kstat_name
), "%s.%016llx.%u.%u",
183 driver_name
, iport_wwn
, instance
, phy_ptr
->phy
.PhyIdentifier
);
185 /* retrieve all the statistics from kstat. */
188 log(LOG_DEBUG
, ROUTINE
,
189 "kstat_open failed due to \"%s\" of phyIndex: %08lx",
190 strerror(errno
), phy
);
191 unlock(&all_hbas_lock
);
192 return (HBA_STATUS_ERROR
);
194 ksp
= kstat_lookup(kc
, NULL
, -1, kstat_name
);
196 log(LOG_DEBUG
, ROUTINE
,
197 "No matching kstat name found for \"%s\" "
198 "of phyIndex: %08lx",
200 unlock(&all_hbas_lock
);
201 (void) kstat_close(kc
);
202 return (HBA_STATUS_ERROR
);
204 /* Found the phy we're looking for. */
205 if (kstat_read(kc
, ksp
, NULL
) == -1) {
206 log(LOG_DEBUG
, ROUTINE
,
207 "error reading kstat data due to \"%s\" "
208 "of phyIndex: %08lx",
209 strerror(errno
), phy
);
210 unlock(&all_hbas_lock
);
211 (void) kstat_close(kc
);
212 return (HBA_STATUS_ERROR
);
215 kname
= (kstat_named_t
*)ksp
->ks_data
;
216 for (i
= 0; i
< ksp
->ks_ndata
; i
++, kname
++) {
217 if (strcmp(kname
->name
,
218 "SecondsSinceLastReset") == 0) {
219 psas
->SecondsSinceLastReset
= kname
->value
.ull
;
222 if (strcmp(kname
->name
, "TxFrames") == 0) {
223 psas
->TxFrames
= kname
->value
.ull
;
226 if (strcmp(kname
->name
, "RxFrames") == 0) {
227 psas
->RxFrames
= kname
->value
.ull
;
230 if (strcmp(kname
->name
, "TxWords") == 0) {
231 psas
->TxWords
= kname
->value
.ull
;
234 if (strcmp(kname
->name
, "RxWords") == 0) {
235 psas
->RxWords
= kname
->value
.ull
;
238 if (strcmp(kname
->name
, "InvalidDwordCount") == 0) {
239 psas
->InvalidDwordCount
= kname
->value
.ull
;
242 if (strcmp(kname
->name
, "RunningDisparityErrorCount") == 0) {
243 psas
->RunningDisparityErrorCount
= kname
->value
.ull
;
246 if (strcmp(kname
->name
, "LossofDwordSyncCount") == 0) {
247 psas
->LossofDwordSyncCount
= kname
->value
.ull
;
250 if (strcmp(kname
->name
, "PhyResetProblemCount") == 0) {
251 psas
->PhyResetProblemCount
= kname
->value
.ull
;
254 unlock(&all_hbas_lock
);
255 (void) kstat_close(kc
);
257 return (HBA_STATUS_OK
);