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 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/sunddi.h>
29 #include <sys/sunndi.h>
30 #include <sys/kstat.h>
31 #include <fpc.h>
32
33 /*
34 * CLEAR_PIC is needed by busstat to extract the current event type of a PIC.
35 * There will be an entry for CLEAR_PIC in each fi_kev_mask_t table below, but
36 * they are different from the other entries in that busstat won't show them to
37 * the user.
38 */
39 #define DEVICE_NAME_LEN 4
40 #define PIC_STR_LEN 12
41
42 /*
43 * Data structure used to build array of event-names and pcr-mask values
44 */
45 typedef struct fi_kev_mask {
46 char *event_name;
47 uint64_t pcr_mask;
48 } fi_kev_mask_t;
49
50 typedef struct fi_ksinfo {
51 uint32_t pic_num_events;
52 uint32_t pic_leaf_id;
53 uint8_t pic_sel_shift[NUM_MAX_COUNTERS];
54 kstat_t *pic_name_ksp[NUM_MAX_COUNTERS];
55 kstat_t *cntr_ksp;
56 fire_perfcnt_t pic_reg_group;
57 } fi_ksinfo_t;
58
59 static fi_ksinfo_t *fi_imu_kstats[NUM_LEAVES];
60 static fi_ksinfo_t *fi_mmu_kstats[NUM_LEAVES];
61 static fi_ksinfo_t *fi_tlu_kstats[NUM_LEAVES];
62 static fi_ksinfo_t *fi_lpu_kstats[NUM_LEAVES];
63 static fi_ksinfo_t *fi_jbc_kstat;
64
65 static int fpc_create_name_kstat(char *name, fi_ksinfo_t *pp, fi_kev_mask_t *ev,
66 int base, int num_cntrs);
67 static void fpc_delete_name_kstat(fi_ksinfo_t *pp);
68 static kstat_t *fpc_create_cntr_kstat(char *name, int instance,
69 int (*update)(kstat_t *, int), void *ksinfop, int num_pics);
70 static int fpc_cntr_kstat_update(kstat_t *ksp, int rw);
71 static int fpc_dev_kstat(fire_perfcnt_t reg_group, uint8_t num_inst);
72 static kstat_t *fpc_create_picN_kstat(char *mod_name, int pic,
73 int pic_sel_shift, int num_ev, fi_kev_mask_t *ev_array);
74 /*
75 * Below are event lists, which map an event name specified on the commandline
76 * with a value to program the event register with.
77 *
78 * The last entry will be the mask of the entire event field for the PIC and
79 * counter type.
80 */
81
82 /*
83 * JBC performance events.
84 */
85 static fi_kev_mask_t
86 fire_jbc_events[] = {
87 {JBC01_S_EVT_NONE, JBC01_EVT_NONE},
88 {JBC01_S_EVT_CLK, JBC01_EVT_CLK},
89 {JBC01_S_EVT_IDLE, JBC01_EVT_IDLE},
90 {JBC01_S_EVT_FIRE, JBC01_EVT_FIRE},
91 {JBC01_S_EVT_READ_LATENCY, JBC01_EVT_READ_LATENCY},
92 {JBC01_S_EVT_READ_SAMPLE, JBC01_EVT_READ_SAMPLE},
93 {JBC01_S_EVT_I2C_PIO, JBC01_EVT_I2C_PIO},
94 {JBC01_S_EVT_EBUS_PIO, JBC01_EVT_EBUS_PIO},
95 {JBC01_S_EVT_RINGA_PIO, JBC01_EVT_RINGA_PIO},
96 {JBC01_S_EVT_RINGB_PIO, JBC01_EVT_RINGB_PIO},
97 {JBC01_S_EVT_PARTIAL_WR, JBC01_EVT_PARTIAL_WR},
98 {JBC01_S_EVT_TOTAL_WR, JBC01_EVT_TOTAL_WR},
99 {JBC01_S_EVT_TOTAL_RD, JBC01_EVT_TOTAL_RD},
100 {JBC01_S_EVT_AOKOFF, JBC01_EVT_AOKOFF},
101 {JBC01_S_EVT_DOKOFF, JBC01_EVT_DOKOFF},
102 {JBC01_S_EVT_DAOKOFF, JBC01_EVT_DAOKOFF},
103 {JBC01_S_EVT_JBUS_COH_XACT, JBC01_EVT_JBUS_COH_XACT},
104 {JBC01_S_EVT_FIRE_COH_XACT, JBC01_EVT_FIRE_COH_XACT},
105 {JBC01_S_EVT_JBUS_NCOH_XACT, JBC01_EVT_JBUS_NCOH_XACT},
106 {JBC01_S_EVT_FGN_IO_HIT, JBC01_EVT_FGN_IO_HIT},
107 {JBC01_S_EVT_FIRE_WBS, JBC01_EVT_FIRE_WBS},
108 {JBC01_S_EVT_PCIEA_PIO_WR, JBC01_EVT_PCIEA_PIO_WR},
109 {JBC01_S_EVT_PCIEA_PIO_RD, JBC01_EVT_PCIEA_PIO_RD},
110 {JBC01_S_EVT_PCIEB_PIO_WR, JBC01_EVT_PCIEB_PIO_WR},
111 {JBC01_S_EVT_PCIEB_PIO_RD, JBC01_EVT_PCIEB_PIO_RD},
112 {COMMON_S_CLEAR_PIC, JBC01_EVT_MASK}
113 };
114
115 /*
116 * IMU performance events
117 */
118 static fi_kev_mask_t
119 fire_imu_events[] = {
120 {IMU01_S_EVT_NONE, IMU01_EVT_NONE},
121 {IMU01_S_EVT_CLK, IMU01_EVT_CLK},
122 {IMU01_S_EVT_MONDO, IMU01_EVT_MONDO},
123 {IMU01_S_EVT_MSI, IMU01_EVT_MSI},
124 {IMU01_S_EVT_MONDO_NAKS, IMU01_EVT_MONDO_NAKS},
125 {IMU01_S_EVT_EQ_WR, IMU01_EVT_EQ_WR},
126 {IMU01_S_EVT_EQ_MONDO, IMU01_EVT_EQ_MONDO},
127 {COMMON_S_CLEAR_PIC, IMU01_EVT_MASK}
128 };
129
130 /*
131 * MMU performance events
132 */
133 static fi_kev_mask_t
134 fire_mmu_events[] = {
135 {MMU01_S_EVT_NONE, MMU01_EVT_NONE},
136 {MMU01_S_EVT_CLK, MMU01_EVT_CLK},
137 {MMU01_S_EVT_TRANS, MMU01_EVT_TRANSL},
138 {MMU01_S_EVT_STALL, MMU01_EVT_STALL},
139 {MMU01_S_EVT_TRANSL_MISS, MMU01_EVT_TRANSL_MISS},
140 {MMU01_S_EVT_TBLWLK_STALL, MMU01_EVT_TBLWLK_STALL},
141 {MMU01_S_EVT_BYPASS_TRANSL, MMU01_EVT_BYPASS_TRANSL},
142 {MMU01_S_EVT_TRANSL_TRANSL, MMU01_EVT_TRANSL_TRANSL},
143 {MMU01_S_EVT_FLOW_CNTL_STALL, MMU01_EVT_FLOW_CNTL_STALL},
144 {MMU01_S_EVT_FLUSH_CACHE_ENT, MMU01_EVT_FLUSH_CACHE_ENT},
145 {COMMON_S_CLEAR_PIC, MMU01_EVT_MASK}
146 };
147
148 /*
149 * TLU performance events for counters 0 and 1
150 */
151 static fi_kev_mask_t
152 fire_tlu_events[] = {
153 {TLU01_S_EVT_NONE, TLU01_EVT_NONE},
154 {TLU01_S_EVT_CLK, TLU01_EVT_CLK},
155 {TLU01_S_EVT_COMPL, TLU01_EVT_COMPL},
156 {TLU01_S_EVT_XMT_POST_CR_UNAV, TLU01_EVT_XMT_POST_CR_UNAV},
157 {TLU01_S_EVT_XMT_NPOST_CR_UNAV, TLU01_EVT_XMT_NPOST_CR_UNAV},
158 {TLU01_S_EVT_XMT_CMPL_CR_UNAV, TLU01_EVT_XMT_CMPL_CR_UNAV},
159 {TLU01_S_EVT_XMT_ANY_CR_UNAV, TLU01_EVT_XMT_ANY_CR_UNAV},
160 {TLU01_S_EVT_RETRY_CR_UNAV, TLU01_EVT_RETRY_CR_UNAV},
161 {TLU01_S_EVT_MEMRD_PKT_RCVD, TLU01_EVT_MEMRD_PKT_RCVD},
162 {TLU01_S_EVT_MEMWR_PKT_RCVD, TLU01_EVT_MEMWR_PKT_RCVD},
163 {TLU01_S_EVT_RCV_CR_THRESH, TLU01_EVT_RCV_CR_THRESH},
164 {TLU01_S_EVT_RCV_PST_HDR_CR_EXH, TLU01_EVT_RCV_PST_HDR_CR_EXH},
165 {TLU01_S_EVT_RCV_PST_DA_CR_MPS, TLU01_EVT_RCV_PST_DA_CR_MPS},
166 {TLU01_S_EVT_RCV_NPST_HDR_CR_EXH, TLU01_EVT_RCV_NPST_HDR_CR_EXH},
167 {TLU01_S_EVT_RCVR_L0S, TLU01_EVT_RCVR_L0S},
168 {TLU01_S_EVT_RCVR_L0S_TRANS, TLU01_EVT_RCVR_L0S_TRANS},
169 {TLU01_S_EVT_XMTR_L0S, TLU01_EVT_XMTR_L0S},
170 {TLU01_S_EVT_XMTR_L0S_TRANS, TLU01_EVT_XMTR_L0S_TRANS},
171 {TLU01_S_EVT_RCVR_ERR, TLU01_EVT_RCVR_ERR},
172 {TLU01_S_EVT_BAD_TLP, TLU01_EVT_BAD_TLP},
173 {TLU01_S_EVT_BAD_DLLP, TLU01_EVT_BAD_DLLP},
174 {TLU01_S_EVT_REPLAY_ROLLOVER, TLU01_EVT_REPLAY_ROLLOVER},
175 {TLU01_S_EVT_REPLAY_TMO, TLU01_EVT_REPLAY_TMO},
176 {COMMON_S_CLEAR_PIC, TLU01_EVT_MASK}
177 };
178
179 /*
180 * TLU performance events for counter 2
181 */
182 static fi_kev_mask_t
183 fire_tlu2_events[] = {
184 {TLU2_S_EVT_NONE, TLU2_EVT_NONE},
185 {TLU2_S_EVT_NON_POST_COMPL_TIME, TLU2_EVT_NON_POST_COMPL_TIME},
186 {TLU2_S_EVT_XMT_DATA_WORD, TLU2_EVT_XMT_DATA_WORD},
187 {TLU2_S_EVT_RCVD_DATA_WORD, TLU2_EVT_RCVD_DATA_WORD},
188 {COMMON_S_CLEAR_PIC, TLU2_EVT_MASK}
189 };
190
191 /*
192 * LPU performance events
193 */
194 static fi_kev_mask_t
195 fire_lpu_events[] = {
196 {LPU12_S_EVT_RESET, LPU12_EVT_RESET},
197 {LPU12_S_EVT_TLP_RCVD, LPU12_EVT_TLP_RCVD},
198 {LPU12_S_EVT_DLLP_RCVD, LPU12_EVT_DLLP_RCVD},
199 {LPU12_S_EVT_ACK_DLLP_RCVD, LPU12_EVT_ACK_DLLP_RCVD},
200 {LPU12_S_EVT_NAK_DLLP_RCVD, LPU12_EVT_NAK_DLLP_RCVD},
201 {LPU12_S_EVT_RETRY_START, LPU12_EVT_RETRY_START},
202 {LPU12_S_EVT_REPLAY_TMO, LPU12_EVT_REPLAY_TMO},
203 {LPU12_S_EVT_ACK_NAK_LAT_TMO, LPU12_EVT_ACK_NAK_LAT_TMO},
204 {LPU12_S_EVT_BAD_DLLP, LPU12_EVT_BAD_DLLP},
205 {LPU12_S_EVT_BAD_TLP, LPU12_EVT_BAD_TLP},
206 {LPU12_S_EVT_NAK_DLLP_SENT, LPU12_EVT_NAK_DLLP_SENT},
207 {LPU12_S_EVT_ACK_DLLP_SENT, LPU12_EVT_ACK_DLLP_SENT},
208 {LPU12_S_EVT_RCVR_ERROR, LPU12_EVT_RCVR_ERROR},
209 {LPU12_S_EVT_LTSSM_RECOV_ENTRY, LPU12_EVT_LTSSM_RECOV_ENTRY},
210 {LPU12_S_EVT_REPLAY_IN_PROG, LPU12_EVT_REPLAY_IN_PROG},
211 {LPU12_S_EVT_TLP_XMT_IN_PROG, LPU12_EVT_TLP_XMT_IN_PROG},
212 {LPU12_S_EVT_CLK_CYC, LPU12_EVT_CLK_CYC},
213 {LPU12_S_EVT_TLP_DLLP_XMT_PROG, LPU12_EVT_TLP_DLLP_XMT_PROG},
214 {LPU12_S_EVT_TLP_DLLP_RCV_PROG, LPU12_EVT_TLP_DLLP_RCV_PROG},
215 {COMMON_S_CLEAR_PIC, LPU12_EVT_MASK}
216 };
217
218 int
fpc_kstat_init(dev_info_t * dip)219 fpc_kstat_init(dev_info_t *dip)
220 {
221 fire_perfcnt_t i;
222 int avail;
223 uint8_t num_inst = 0;
224
225 if (fpc_perfcnt_module_init(dip, &avail) != DDI_SUCCESS)
226 return (DDI_FAILURE);
227
228 if (avail & PCIE_A_REGS_AVAIL)
229 num_inst++;
230 if (avail & PCIE_B_REGS_AVAIL)
231 num_inst++;
232
233 for (i = jbc; i < MAX_REG_TYPES; i++) {
234 if (i == jbc) {
235 if (avail & JBUS_REGS_AVAIL) {
236 if (fpc_dev_kstat(i, 1) != SUCCESS)
237 return (DDI_FAILURE);
238 }
239 } else {
240 if (!num_inst)
241 break;
242 if (fpc_dev_kstat(i, num_inst) != SUCCESS)
243 return (DDI_FAILURE);
244 }
245 }
246
247 return (DDI_SUCCESS);
248 }
249
250 static int
fpc_dev_kstat(fire_perfcnt_t reg_group,uint8_t num_inst)251 fpc_dev_kstat(fire_perfcnt_t reg_group, uint8_t num_inst)
252 {
253 int i, base_cntrid, num_cntrs;
254 uint32_t num_events, num_events2;
255 char dev_name[DEVICE_NAME_LEN];
256 fi_ksinfo_t *ksinfop;
257 fi_kev_mask_t *fire_events, *fire_events2;
258
259 switch (reg_group) {
260 case imu:
261 (void) strncpy(dev_name, "imu", sizeof (dev_name));
262 num_events = sizeof (fire_imu_events) / sizeof (fi_kev_mask_t);
263 fire_events = fire_imu_events;
264 num_cntrs = NUM_IMU_COUNTERS;
265 break;
266 case mmu:
267 (void) strncpy(dev_name, "mmu", sizeof (dev_name));
268 num_events = sizeof (fire_mmu_events) / sizeof (fi_kev_mask_t);
269 fire_events = fire_mmu_events;
270 num_cntrs = NUM_MMU_COUNTERS;
271 break;
272 case lpu:
273 (void) strncpy(dev_name, "lpu", sizeof (dev_name));
274 num_events = sizeof (fire_lpu_events) / sizeof (fi_kev_mask_t);
275 fire_events = fire_lpu_events;
276 num_cntrs = NUM_LPU_COUNTERS;
277 break;
278 case tlu:
279 (void) strncpy(dev_name, "tlu", sizeof (dev_name));
280 num_events = sizeof (fire_tlu_events) / sizeof (fi_kev_mask_t);
281 num_events2 = sizeof (fire_tlu2_events) /
282 sizeof (fi_kev_mask_t);
283 fire_events = fire_tlu_events;
284 fire_events2 = fire_tlu2_events;
285 num_cntrs = NUM_TLU_COUNTERS;
286 break;
287 case jbc:
288 (void) strncpy(dev_name, "jbc", sizeof (dev_name));
289 num_events = sizeof (fire_jbc_events) / sizeof (fi_kev_mask_t);
290 fire_events = fire_jbc_events;
291 num_cntrs = NUM_JBC_COUNTERS;
292 break;
293 default:
294 return (FAILURE);
295 }
296
297 for (i = 0; i < num_inst; i++) {
298 ksinfop = kmem_zalloc(sizeof (fi_ksinfo_t), KM_SLEEP);
299
300 ksinfop->pic_num_events = num_events;
301 ksinfop->pic_reg_group = reg_group;
302 ksinfop->pic_leaf_id = i;
303 ksinfop->pic_sel_shift[0] = PIC0_EVT_SEL_SHIFT;
304
305 if (reg_group == lpu)
306 ksinfop->pic_sel_shift[1] = PIC2_EVT_SEL_SHIFT;
307 else
308 ksinfop->pic_sel_shift[1] = PIC1_EVT_SEL_SHIFT;
309
310 /*
311 * All error cleanup (deleting kstats and freeing memory) is
312 * done in fire_kstat_fini. So we need to save the ksinfop
313 * pointer before any possible error exit so fire_kstat_fini
314 * can find it.
315 */
316 if (reg_group == imu)
317 fi_imu_kstats[i] = ksinfop;
318 else if (reg_group == mmu)
319 fi_mmu_kstats[i] = ksinfop;
320 else if (reg_group == lpu)
321 fi_lpu_kstats[i] = ksinfop;
322 else if (reg_group == tlu)
323 fi_tlu_kstats[i] = ksinfop;
324 else if (reg_group == jbc)
325 fi_jbc_kstat = ksinfop;
326
327 /* Create basic pic event-type pair (only once) */
328 if (i == 0) {
329 base_cntrid = 0;
330
331 /* The extra counter for TLU is handled separately */
332 if (reg_group == tlu)
333 num_cntrs--;
334
335 if (fpc_create_name_kstat(dev_name, ksinfop,
336 fire_events, base_cntrid, num_cntrs) != SUCCESS)
337 goto err;
338
339 /*
340 * extra counter for TLU. The events associated with
341 * this third counter are different from the events
342 * for the first and second counters.
343 */
344 if (reg_group == tlu) {
345 ksinfop->pic_sel_shift[2] = PIC2_EVT_SEL_SHIFT;
346 base_cntrid += num_cntrs;
347 num_cntrs = 1;
348 ksinfop->pic_num_events = num_events2;
349 if (fpc_create_name_kstat(dev_name, ksinfop,
350 fire_events2, base_cntrid, num_cntrs)
351 != SUCCESS)
352 goto err;
353
354 num_cntrs = NUM_TLU_COUNTERS;
355 }
356
357 }
358
359 /* create counter kstats */
360 ksinfop->cntr_ksp = fpc_create_cntr_kstat(dev_name, i,
361 fpc_cntr_kstat_update, ksinfop, num_cntrs);
362 if (ksinfop->cntr_ksp == NULL)
363 goto err;
364
365 }
366 return (SUCCESS);
367 err:
368 return (FAILURE);
369
370 }
371
372 static int
fpc_create_name_kstat(char * name,fi_ksinfo_t * pp,fi_kev_mask_t * ev,int base,int num_cntrs)373 fpc_create_name_kstat(char *name, fi_ksinfo_t *pp, fi_kev_mask_t *ev,
374 int base, int num_cntrs)
375 {
376 int i;
377
378 #ifdef DEBUG
379 FPC_DBG2("fpc_create_name_kstat: name: %s\n", name);
380 #endif
381
382 for (i = base; i < (base + num_cntrs); i++) {
383 pp->pic_name_ksp[i] = fpc_create_picN_kstat(name, i,
384 pp->pic_sel_shift[i], pp->pic_num_events, ev);
385
386 if (pp->pic_name_ksp[i] == NULL)
387 return (FAILURE);
388 }
389 return (SUCCESS);
390 }
391
392 /*
393 * Create the picN kstat. Returns a pointer to the
394 * kstat which the driver must store to allow it
395 * to be deleted when necessary.
396 */
397 static kstat_t *
fpc_create_picN_kstat(char * mod_name,int pic,int pic_sel_shift,int num_ev,fi_kev_mask_t * ev_array)398 fpc_create_picN_kstat(char *mod_name, int pic, int pic_sel_shift, int num_ev,
399 fi_kev_mask_t *ev_array)
400 {
401 int event;
402 char pic_name[PIC_STR_LEN];
403 kstat_t *picN_ksp = NULL;
404 struct kstat_named *pic_named_data;
405
406 (void) snprintf(pic_name, sizeof (pic_name), "pic%d", pic);
407 if ((picN_ksp = kstat_create(mod_name, 0, pic_name,
408 "bus", KSTAT_TYPE_NAMED, num_ev, 0)) == NULL) {
409 cmn_err(CE_WARN, "%s %s : kstat create failed",
410 mod_name, pic_name);
411 return (NULL);
412 }
413
414 pic_named_data = (struct kstat_named *)picN_ksp->ks_data;
415
416 /*
417 * Fill up data section of the kstat
418 * Write event names and their associated pcr masks.
419 * num_ev - 1 is because CLEAR_PIC is added separately.
420 */
421 for (event = 0; event < num_ev - 1; event++) {
422 pic_named_data[event].value.ui64 =
423 (ev_array[event].pcr_mask << pic_sel_shift);
424
425 kstat_named_init(&pic_named_data[event],
426 ev_array[event].event_name, KSTAT_DATA_UINT64);
427 }
428
429 /*
430 * add the clear_pic entry
431 */
432 pic_named_data[event].value.ui64 =
433 (uint64_t)~(ev_array[event].pcr_mask << pic_sel_shift);
434
435 kstat_named_init(&pic_named_data[event], ev_array[event].event_name,
436 KSTAT_DATA_UINT64);
437
438 kstat_install(picN_ksp);
439
440 #ifdef DEBUG
441 FPC_DBG2("fpc_create_picN_kstat: name %s, pic %d, num_ev %d, "
442 "pic_sel_shift %d\n", mod_name, pic, num_ev, pic_sel_shift);
443 #endif
444
445 return (picN_ksp);
446 }
447
448 /*
449 * Create the "counters" kstat.
450 */
451 static kstat_t *
fpc_create_cntr_kstat(char * name,int instance,int (* update)(kstat_t *,int),void * ksinfop,int num_pics)452 fpc_create_cntr_kstat(char *name, int instance, int (*update)(kstat_t *, int),
453 void *ksinfop, int num_pics)
454 {
455 int i;
456 char pic_str[PIC_STR_LEN];
457 struct kstat *counters_ksp;
458 struct kstat_named *counters_named_data;
459
460 #ifdef DEBUG
461 FPC_DBG1("fpc_create_cntr_kstat: name: %s instance: %d\n",
462 name, instance);
463 #endif
464
465 /*
466 * Size of kstat is num_pics + 1. extra one for pcr.
467 */
468 if ((counters_ksp = kstat_create(name, instance, "counters", "bus",
469 KSTAT_TYPE_NAMED, num_pics + 1, KSTAT_FLAG_WRITABLE)) == NULL) {
470 cmn_err(CE_WARN, "kstat_create for %s%d failed",
471 name, instance);
472 return (NULL);
473 }
474
475 counters_named_data = (struct kstat_named *)(counters_ksp->ks_data);
476 kstat_named_init(&counters_named_data[0], "pcr", KSTAT_DATA_UINT64);
477
478 for (i = 0; i < num_pics; i++) {
479 (void) snprintf(pic_str, sizeof (pic_str), "pic%d", i);
480
481 kstat_named_init(&counters_named_data[i+1], pic_str,
482 KSTAT_DATA_UINT64);
483 }
484
485 /*
486 * Store the reg type and other info. in the kstat's private field
487 * so that they are available to the update function.
488 */
489 counters_ksp->ks_private = (void *)ksinfop;
490 counters_ksp->ks_update = update;
491
492 kstat_install(counters_ksp);
493
494 return (counters_ksp);
495 }
496
497 /*
498 * kstat update function. Handles reads/writes
499 * from/to kstat.
500 */
501 static int
fpc_cntr_kstat_update(kstat_t * ksp,int rw)502 fpc_cntr_kstat_update(kstat_t *ksp, int rw)
503 {
504 struct kstat_named *data_p;
505 fi_ksinfo_t *ksinfop = ksp->ks_private;
506 uint64_t counters[NUM_MAX_COUNTERS];
507 uint64_t event;
508
509 data_p = (struct kstat_named *)ksp->ks_data;
510
511 if (rw == KSTAT_WRITE) {
512 #ifdef DEBUG
513 FPC_DBG2("fpc_cntr_kstat_update: wr %ld\n",
514 data_p[0].value.ui64);
515 #endif
516
517 if (fpc_perfcnt_program(ksinfop->pic_leaf_id,
518 ksinfop->pic_reg_group, data_p[0].value.ui64) != SUCCESS)
519 return (EIO);
520 } else {
521 counters[2] = 0;
522 if (fpc_perfcnt_read(ksinfop->pic_leaf_id,
523 ksinfop->pic_reg_group, &event, counters) != SUCCESS)
524 return (EIO);
525
526 data_p[0].value.ui64 = event;
527 data_p[1].value.ui64 = counters[0];
528 data_p[2].value.ui64 = counters[1];
529
530 if (ksinfop->pic_reg_group == tlu) {
531 data_p[3].value.ui64 = counters[2];
532 }
533 #ifdef DEBUG
534 FPC_DBG2("fpc_cntr_kstat_update: rd event %ld, cntr0"
535 " %ld, cntr1 %ld, cntr2 %ld\n", data_p[0].value.ui64,
536 counters[0], counters[1], counters[2]);
537 #endif
538 }
539 return (0);
540 }
541
542 void
fpc_kstat_fini(dev_info_t * dip)543 fpc_kstat_fini(dev_info_t *dip)
544 {
545 int i;
546
547 #ifdef DEBUG
548 FPC_DBG1("fpc_kstat_fini called\n");
549 #endif
550
551 for (i = 0; i < NUM_LEAVES; i++) {
552 /* IMU */
553 if (fi_imu_kstats[i] != NULL) {
554 fpc_delete_name_kstat(fi_imu_kstats[i]);
555 if (fi_imu_kstats[i]->cntr_ksp != NULL)
556 kstat_delete(fi_imu_kstats[i]->cntr_ksp);
557 kmem_free(fi_imu_kstats[i], sizeof (fi_ksinfo_t));
558 fi_imu_kstats[i] = NULL;
559 }
560
561 /* MMU */
562 if (fi_mmu_kstats[i] != NULL) {
563 fpc_delete_name_kstat(fi_mmu_kstats[i]);
564 if (fi_mmu_kstats[i]->cntr_ksp != NULL)
565 kstat_delete(fi_mmu_kstats[i]->cntr_ksp);
566 kmem_free(fi_mmu_kstats[i], sizeof (fi_ksinfo_t));
567 fi_mmu_kstats[i] = NULL;
568 }
569
570 /* LPU */
571 if (fi_lpu_kstats[i] != NULL) {
572 fpc_delete_name_kstat(fi_lpu_kstats[i]);
573 if (fi_lpu_kstats[i]->cntr_ksp != NULL)
574 kstat_delete(fi_lpu_kstats[i]->cntr_ksp);
575 kmem_free(fi_lpu_kstats[i], sizeof (fi_ksinfo_t));
576 fi_lpu_kstats[i] = NULL;
577 }
578
579 /* TLU */
580 if (fi_tlu_kstats[i] != NULL) {
581 fpc_delete_name_kstat(fi_tlu_kstats[i]);
582 if (fi_tlu_kstats[i]->cntr_ksp != NULL)
583 kstat_delete(fi_tlu_kstats[i]->cntr_ksp);
584 kmem_free(fi_tlu_kstats[i], sizeof (fi_ksinfo_t));
585 fi_tlu_kstats[i] = NULL;
586 }
587 }
588
589 /* JBC */
590 if (fi_jbc_kstat != NULL) {
591 fpc_delete_name_kstat(fi_jbc_kstat);
592 if (fi_jbc_kstat->cntr_ksp != NULL)
593 kstat_delete(fi_jbc_kstat->cntr_ksp);
594 kmem_free(fi_jbc_kstat, sizeof (fi_ksinfo_t));
595 fi_jbc_kstat = NULL;
596 }
597
598 (void) fpc_perfcnt_module_fini(dip);
599 }
600
601 static void
fpc_delete_name_kstat(fi_ksinfo_t * pp)602 fpc_delete_name_kstat(fi_ksinfo_t *pp)
603 {
604 int i;
605
606 if (pp != NULL) {
607 for (i = 0; i < NUM_MAX_COUNTERS; i++) {
608 if (pp->pic_name_ksp[i] != NULL)
609 kstat_delete(pp->pic_name_ksp[i]);
610 }
611 }
612 }
613