1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include "rge.h"
27
28 #define RGE_DBG RGE_DBG_STATS /* debug flag for this code */
29
30 /*
31 * Local datatype for defining tables of (Offset, Name) pairs
32 */
33 typedef struct {
34 offset_t index;
35 char *name;
36 } rge_ksindex_t;
37
38 static const rge_ksindex_t rge_driverinfo[] = {
39 { 0, "rx_ring_addr" },
40 { 1, "rx_next" },
41 { 2, "rx_free" },
42 { 3, "rx_bcopy" },
43 { 4, "tx_ring_addr" },
44 { 5, "tx_next" },
45 { 6, "tx_free" },
46 { 7, "tx_flow" },
47 { 8, "resched_needed" },
48 { 9, "watchdog" },
49 { 10, "rx_config" },
50 { 11, "tx_config" },
51 { 12, "mac_ver" },
52 { 13, "phy_ver" },
53 { 14, "chip_reset" },
54 { 15, "phy_reset" },
55 { 16, "loop_mode" },
56 { -1, NULL }
57 };
58
59 static int
rge_driverinfo_update(kstat_t * ksp,int flag)60 rge_driverinfo_update(kstat_t *ksp, int flag)
61 {
62 rge_t *rgep;
63 kstat_named_t *knp;
64
65 if (flag != KSTAT_READ)
66 return (EACCES);
67
68 rgep = ksp->ks_private;
69 knp = ksp->ks_data;
70
71 (knp++)->value.ui64 = rgep->dma_area_rxdesc.cookie.dmac_laddress;
72 (knp++)->value.ui64 = rgep->rx_next;
73 (knp++)->value.ui64 = rgep->rx_free;
74 (knp++)->value.ui64 = rgep->rx_bcopy;
75 (knp++)->value.ui64 = rgep->dma_area_txdesc.cookie.dmac_laddress;
76 (knp++)->value.ui64 = rgep->tx_next;
77 (knp++)->value.ui64 = rgep->tx_free;
78 (knp++)->value.ui64 = rgep->tx_flow;
79 (knp++)->value.ui64 = rgep->resched_needed;
80 (knp++)->value.ui64 = rgep->watchdog;
81 (knp++)->value.ui64 = rgep->chipid.rxconfig;
82 (knp++)->value.ui64 = rgep->chipid.txconfig;
83 (knp++)->value.ui64 = rgep->chipid.mac_ver;
84 (knp++)->value.ui64 = rgep->chipid.phy_ver;
85 (knp++)->value.ui64 = rgep->stats.chip_reset;
86 (knp++)->value.ui64 = rgep->stats.phy_reset;
87 (knp++)->value.ui64 = rgep->param_loop_mode;
88
89 return (0);
90 }
91
92 static kstat_t *
rge_setup_named_kstat(rge_t * rgep,int instance,char * name,const rge_ksindex_t * ksip,size_t size,int (* update)(kstat_t *,int))93 rge_setup_named_kstat(rge_t *rgep, int instance, char *name,
94 const rge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
95 {
96 kstat_t *ksp;
97 kstat_named_t *knp;
98 char *np;
99 int type;
100
101 size /= sizeof (rge_ksindex_t);
102 ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
103 KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
104 if (ksp == NULL)
105 return (NULL);
106
107 ksp->ks_private = rgep;
108 ksp->ks_update = update;
109 for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
110 switch (*np) {
111 default:
112 type = KSTAT_DATA_UINT64;
113 break;
114 case '%':
115 np += 1;
116 type = KSTAT_DATA_UINT32;
117 break;
118 case '$':
119 np += 1;
120 type = KSTAT_DATA_STRING;
121 break;
122 case '&':
123 np += 1;
124 type = KSTAT_DATA_CHAR;
125 break;
126 }
127 kstat_named_init(knp, np, type);
128 }
129 kstat_install(ksp);
130
131 return (ksp);
132 }
133
134 void
rge_init_kstats(rge_t * rgep,int instance)135 rge_init_kstats(rge_t *rgep, int instance)
136 {
137 rgep->rge_kstats[RGE_KSTAT_DRIVER] = rge_setup_named_kstat(rgep,
138 instance, "driverinfo", rge_driverinfo,
139 sizeof (rge_driverinfo), rge_driverinfo_update);
140 }
141
142 void
rge_fini_kstats(rge_t * rgep)143 rge_fini_kstats(rge_t *rgep)
144 {
145 int i;
146
147 for (i = RGE_KSTAT_COUNT; --i >= 0; )
148 if (rgep->rge_kstats[i] != NULL) {
149 kstat_delete(rgep->rge_kstats[i]);
150 }
151 }
152
153 int
rge_m_stat(void * arg,uint_t stat,uint64_t * val)154 rge_m_stat(void *arg, uint_t stat, uint64_t *val)
155 {
156 rge_t *rgep = arg;
157 rge_hw_stats_t *bstp;
158
159 mutex_enter(rgep->genlock);
160 rge_hw_stats_dump(rgep);
161 mutex_exit(rgep->genlock);
162 bstp = rgep->hw_stats;
163
164 switch (stat) {
165 case MAC_STAT_IFSPEED:
166 *val = rgep->param_link_speed * 1000000ull;
167 break;
168
169 case MAC_STAT_MULTIRCV:
170 *val = RGE_BSWAP_32(bstp->multi_rcv);
171 break;
172
173 case MAC_STAT_BRDCSTRCV:
174 *val = RGE_BSWAP_64(bstp->brdcst_rcv);
175 break;
176
177 case MAC_STAT_NORCVBUF:
178 *val = RGE_BSWAP_16(bstp->in_discards);
179 break;
180
181 case MAC_STAT_IERRORS:
182 *val = RGE_BSWAP_32(bstp->rcv_err);
183 break;
184
185 case MAC_STAT_OERRORS:
186 *val = RGE_BSWAP_64(bstp->xmt_err);
187 break;
188
189 case MAC_STAT_COLLISIONS:
190 *val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
191 break;
192
193 case MAC_STAT_RBYTES:
194 *val = rgep->stats.rbytes;
195 break;
196
197 case MAC_STAT_IPACKETS:
198 *val = RGE_BSWAP_64(bstp->rcv_ok);
199 break;
200
201 case MAC_STAT_OBYTES:
202 *val = rgep->stats.obytes;
203 break;
204
205 case MAC_STAT_OPACKETS:
206 *val = RGE_BSWAP_64(bstp->xmt_ok);
207 break;
208
209 case ETHER_STAT_ALIGN_ERRORS:
210 *val = RGE_BSWAP_16(bstp->frame_err);
211 break;
212
213 case ETHER_STAT_FIRST_COLLISIONS:
214 *val = RGE_BSWAP_32(bstp->xmt_1col);
215 break;
216
217 case ETHER_STAT_MULTI_COLLISIONS:
218 *val = RGE_BSWAP_32(bstp->xmt_mcol);
219 break;
220
221 case ETHER_STAT_DEFER_XMTS:
222 *val = rgep->stats.defer;
223 break;
224
225 case ETHER_STAT_XCVR_ADDR:
226 *val = rgep->phy_mii_addr;
227 break;
228
229 case ETHER_STAT_XCVR_ID:
230 mutex_enter(rgep->genlock);
231 *val = rge_mii_get16(rgep, MII_PHYIDH);
232 *val <<= 16;
233 *val |= rge_mii_get16(rgep, MII_PHYIDL);
234 mutex_exit(rgep->genlock);
235 break;
236
237 case ETHER_STAT_XCVR_INUSE:
238 *val = XCVR_1000T;
239 break;
240
241 case ETHER_STAT_CAP_1000FDX:
242 *val = 1;
243 break;
244
245 case ETHER_STAT_CAP_1000HDX:
246 *val = 0;
247 break;
248
249 case ETHER_STAT_CAP_100FDX:
250 *val = 1;
251 break;
252
253 case ETHER_STAT_CAP_100HDX:
254 *val = 1;
255 break;
256
257 case ETHER_STAT_CAP_10FDX:
258 *val = 1;
259 break;
260
261 case ETHER_STAT_CAP_10HDX:
262 *val = 1;
263 break;
264
265 case ETHER_STAT_CAP_ASMPAUSE:
266 *val = 1;
267 break;
268
269 case ETHER_STAT_CAP_PAUSE:
270 *val = 1;
271 break;
272
273 case ETHER_STAT_CAP_AUTONEG:
274 *val = 1;
275 break;
276
277 case ETHER_STAT_ADV_CAP_1000FDX:
278 *val = rgep->param_adv_1000fdx;
279 break;
280
281 case ETHER_STAT_ADV_CAP_1000HDX:
282 *val = rgep->param_adv_1000hdx;
283 break;
284
285 case ETHER_STAT_ADV_CAP_100FDX:
286 *val = rgep->param_adv_100fdx;
287 break;
288
289 case ETHER_STAT_ADV_CAP_100HDX:
290 *val = rgep->param_adv_100hdx;
291 break;
292
293 case ETHER_STAT_ADV_CAP_10FDX:
294 *val = rgep->param_adv_10fdx;
295 break;
296
297 case ETHER_STAT_ADV_CAP_10HDX:
298 *val = rgep->param_adv_10hdx;
299 break;
300
301 case ETHER_STAT_ADV_CAP_ASMPAUSE:
302 *val = rgep->param_adv_asym_pause;
303 break;
304
305 case ETHER_STAT_ADV_CAP_PAUSE:
306 *val = rgep->param_adv_pause;
307 break;
308
309 case ETHER_STAT_ADV_CAP_AUTONEG:
310 *val = rgep->param_adv_autoneg;
311 break;
312
313 case ETHER_STAT_LINK_DUPLEX:
314 *val = rgep->param_link_duplex;
315 break;
316
317 default:
318 return (ENOTSUP);
319 }
320
321 return (0);
322 }
323