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