9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER START
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The contents of this file are subject to the terms of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Common Development and Distribution License (the "License").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You may not use this file except in compliance with the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * See the License for the specific language governing permissions
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and limitations under the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When distributing Covered Code, include this CDDL HEADER in each
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If applicable, add the following below this CDDL HEADER, with the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER END
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Use is subject to license terms.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor IB Performance Statistics routines
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements all the routines necessary for setting up, querying, and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (later) tearing down all the kstats necessary for implementing to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the interfaces necessary to provide busstat(1M) access.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic kstat_t *tavor_kstat_picN_create(tavor_state_t *state, int num_pic,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic kstat_t *tavor_kstat_cntr_create(tavor_state_t *state, int num_pic,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_kstat_cntr_update(kstat_t *ksp, int rw);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalavoid tavor_kstat_perfcntr64_create(tavor_state_t *state, uint_t port_num);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalastatic int tavor_kstat_perfcntr64_read(tavor_state_t *state, uint_t port,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalastatic void tavor_kstat_perfcntr64_thread_exit(tavor_ks_info_t *ksi);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalastatic int tavor_kstat_perfcntr64_update(kstat_t *ksp, int rw);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor IB Performance Events structure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This structure is read-only and is used to setup the individual kstats
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and to initialize the tki_ib_perfcnt[] array for each Tavor instance.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_ks_mask_t tavor_ib_perfcnt_list[TAVOR_CNTR_NUMENTRIES] = {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_xmit_data", TAVOR_HW_PMEG_PORTXMITDATA_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFFFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_recv_data", TAVOR_HW_PMEG_PORTRECVDATA_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFFFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_xmit_pkts", TAVOR_HW_PMEG_PORTXMITPKTS_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFFFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_recv_pkts", TAVOR_HW_PMEG_PORTRECVPKTS_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFFFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_recv_err", TAVOR_HW_PMEG_PORTRECVERR_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_xmit_discards", TAVOR_HW_PMEG_PORTXMITDISCARD_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"vl15_dropped", TAVOR_HW_PMEG_VL15DROPPED_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_xmit_wait", TAVOR_HW_PMEG_PORTXMITWAIT_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFFFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_recv_remote_phys_err", TAVOR_HW_PMEG_PORTRECVREMPHYSERR_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_xmit_constraint_err", TAVOR_HW_PMEG_PORTXMITCONSTERR_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"port_recv_constraint_err", TAVOR_HW_PMEG_PORTRECVCONSTERR_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"symbol_err_counter", TAVOR_HW_PMEG_SYMBOLERRCNT_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"link_err_recovery_cnt", TAVOR_HW_PMEG_LINKERRRECOVERCNT_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xFFFF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"link_downed_cnt", TAVOR_HW_PMEG_LINKDOWNEDCNT_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"excessive_buffer_overruns", TAVOR_HW_PMEG_EXCESSBUFOVERRUN_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, 0xF, 0, 0},
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"local_link_integrity_err", TAVOR_HW_PMEG_LOCALLINKINTERR_OFFSET,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {"clear_pic", 0, 0, 0, 0}
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Return the maximum of (x) and (y)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala#define MAX(x, y) (((x) > (y)) ? (x) : (y))
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Set (x) to the maximum of (x) and (y)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if ((x) < (y)) \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_kstat_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate a kstat info structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ksi = (tavor_ks_info_t *)kmem_zalloc(sizeof (tavor_ks_info_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_kstat_init_kma_fail, TAVOR_TNF_ERROR, "");
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Create as many "pic" and perfcntr64 kstats as we have IB ports.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Enable all of the events specified in the "tavor_ib_perfcnt_list"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < numports; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ksi->tki_picN_ksp[i] = tavor_kstat_picN_create(state, i,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala tavor_kstat_perfcntr64_create(state, i + 1);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (ksi->tki_perfcntr64[i].tki64_ksp == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Create the "counters" kstat too */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ksi->tki_cntr_ksp = tavor_kstat_cntr_create(state, numports,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_kstat_init_cntr_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the control register and initial counter values */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize the Tavor tki_ib_perfcnt[] array values using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * default values in tavor_ib_perfcnt_list[]
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < TAVOR_CNTR_NUMENTRIES; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ksi->tki_ib_perfcnt[i] = tavor_ib_perfcnt_list[i];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala mutex_init(&ksi->tki_perfcntr64_lock, NULL, MUTEX_DRIVER, NULL);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala cv_init(&ksi->tki_perfcntr64_cv, NULL, CV_DRIVER, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Delete all the previously created kstats */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < numports; i++) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (ksi->tki_perfcntr64[i].tki64_ksp != NULL) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_delete(ksi->tki_perfcntr64[i].tki64_ksp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the kstat info structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_kstat_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get pointer to kstat info */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Signal the perfcntr64_update_thread to exit and wait until the
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * thread exits.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* Delete all the "pic" and perfcntr64 kstats (one per port) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < numports; i++) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (ksi->tki_perfcntr64[i].tki64_ksp != NULL) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_delete(ksi->tki_perfcntr64[i].tki64_ksp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Delete the "counter" kstats (one per port) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the kstat info structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_kstat_picN_create()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_kstat_picN_create(tavor_state_t *state, int num_pic, int num_evt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Create the "picN" kstat. In the steps, below we will attach
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all of our named event types to it.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_name = (char *)ddi_driver_name(state->ts_dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor picN_ksp = kstat_create(drv_name, drv_instance, pic_name, "bus",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pic_named_data = (struct kstat_named *)(picN_ksp->ks_data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Write event names and their associated pcr masks. The last entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in the array (clear_pic) is added separately below (as its pic
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * value must be inverted).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kstat_named_init(&pic_named_data[i], ev_array[i].ks_evt_name,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Add the "clear_pic" entry */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ~((uint64_t)TAVOR_CNTR_MASK << (num_pic * TAVOR_CNTR_SIZE));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kstat_named_init(&pic_named_data[i], ev_array[i].ks_evt_name,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Install the kstat */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_kstat_cntr_create()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_kstat_cntr_create(tavor_state_t *state, int num_pic,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Create the "counters" kstat. In the steps, below we will attach
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all of our "pic" to it. Note: The size of this kstat is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * num_pic + 1 because it also contains the "%pcr".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_name = (char *)ddi_driver_name(state->ts_dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cntr_ksp = kstat_create(drv_name, drv_instance, "counters", "bus",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KSTAT_TYPE_NAMED, num_pic + 1, KSTAT_FLAG_WRITABLE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cntr_named_data = (struct kstat_named *)(cntr_ksp->ks_data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize the named kstats (for the "pcr" and for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * individual "pic" kstats)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kstat_named_init(&cntr_named_data[0], "pcr", KSTAT_DATA_UINT64);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < num_pic; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kstat_named_init(&cntr_named_data[i+1], pic_str,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Store the Tavor softstate pointer in the kstat's private field so
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that it is available to the update function.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Install the kstat */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_kstat_cntr_update()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Called from the kstat context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Extract the Tavor softstate pointer, kstat data, pointer to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * kstat info structure, and pointer to the tki_ib_perfcnt[] array
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from the input parameters. Note: For warlock purposes, these
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * parameters are all accessed only in this routine and are,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * therefore, protected by the lock used by the kstat framework.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Depending on whether we are reading the "pic" counters or
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * writing the "pcr" control register, we need to handle and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fill in the kstat data appropriately.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is a write to the "pcr", then extract the value from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the kstat data and store it in the kstat info structure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise, if this is a read of the "pic" counter(s), then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * extract the register offset, size, and mask values from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ib_perf[] array. Then read the corresponding register and store
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it into the kstat data. Note: We only read/fill in pic1 if more
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * than one port is configured.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update the stored "pcr" value */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Get the current "pcr" value and extract the lower
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * portion (corresponding to the counters for "pic0")
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the "pic0" counter, corresponding to port 1.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This involves reading in the current value in the register
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and calculating how many events have happened since this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register was last polled. Then we save away the current
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * value for the counter and increment the "pic0" total by
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the number of new events.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pic0 = ddi_get32(state->ts_reg_cmdhdl, (uint32_t *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uintptr_t)((uintptr_t)state->ts_reg_cmd_baseaddr +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If necessary, fill in the "pic1" counter for port 2.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This works the same as above except that we extract the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * upper bits (corresponding to the counters for "pic1")
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pic1 = ddi_get32(state->ts_reg_cmdhdl, (uint32_t *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uintptr_t)((uintptr_t)state->ts_reg_cmd_baseaddr +
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * 64 bit kstats for performance counters:
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Since the hardware as of now does not support 64 bit performance counters,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * we maintain 64 bit performance counters in software using the 32 bit
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * hardware counters.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * We create a thread that, every one second, reads the values of 32 bit
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * hardware counters and adds them to the 64 bit software counters. Immediately
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * after reading, it resets the 32 bit hardware counters to zero (so that they
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * start counting from zero again). At any time the current value of a counter
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * is going to be the sum of the 64 bit software counter and the 32 bit
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * hardware counter.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Since this work need not be done if there is no consumer, by default
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * we do not maintain 64 bit software counters. To enable this the consumer
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * needs to write a non-zero value to the "enable" component of the of
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * perf_counters kstat. Writing zero to this component will disable this work.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * If performance monitor is enabled in subnet manager, the SM could
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * periodically reset the hardware counters by sending perf-MADs. So only
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * one of either our software 64 bit counters or the SM performance monitor
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * could be enabled at the same time. However, if both of them are enabled at
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * the same time we still do our best by keeping track of the values of the
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * last read 32 bit hardware counters. If the current read of a 32 bit hardware
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * counter is less than the last read of the counter, we ignore the current
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * value and go with the last read value.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_create()
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Context: Only called from attach() path context
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Create "port#/perf_counters" kstat for the specified port number.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalatavor_kstat_perfcntr64_create(tavor_state_t *state, uint_t port_num)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala drv_name = (char *)ddi_driver_name(state->ts_dip);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala drv_instance = ddi_get_instance(state->ts_dip);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala (void) snprintf(kname, sizeof (kname), "port%u/perf_counters",
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala cntr_ksp = kstat_create(drv_name, drv_instance, kname, "ib",
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala KSTAT_TYPE_NAMED, TAVOR_PERFCNTR64_NUM_COUNTERS,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala cntr_named_data = (struct kstat_named *)(cntr_ksp->ks_data);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_named_init(&cntr_named_data[TAVOR_PERFCNTR64_ENABLE_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_named_init(&cntr_named_data[TAVOR_PERFCNTR64_XMIT_DATA_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_named_init(&cntr_named_data[TAVOR_PERFCNTR64_RECV_DATA_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_named_init(&cntr_named_data[TAVOR_PERFCNTR64_XMIT_PKTS_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala kstat_named_init(&cntr_named_data[TAVOR_PERFCNTR64_RECV_PKTS_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi->tki_perfcntr64[port_num - 1].tki64_ksp = cntr_ksp;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi->tki_perfcntr64[port_num - 1].tki64_port_num = port_num;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi->tki_perfcntr64[port_num - 1].tki64_state = state;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala cntr_ksp->ks_private = &ksi->tki_perfcntr64[port_num - 1];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala cntr_ksp->ks_update = tavor_kstat_perfcntr64_update;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* Install the kstat */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_read()
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Read the values of 32 bit hardware counters.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * If reset is true, reset the 32 bit hardware counters. Add the values of the
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * 32 bit hardware counters to the 64 bit software counters.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * If reset is false, just save the values read from the 32 bit hardware
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * counters in tki64_last_read[].
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * See the general comment on the 64 bit performance counters
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * regarding the use of last read 32 bit hardware counter values.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalatavor_kstat_perfcntr64_read(tavor_state_t *state, uint_t port, int reset)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala tavor_perfcntr64_ks_info_t *ksi64 = &ksi->tki_perfcntr64[port - 1];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ASSERT(MUTEX_HELD(&ksi->tki_perfcntr64_lock));
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* read the 32 bit hardware counters */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala status = tavor_getperfcntr_cmd_post(state, port,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* reset the hardware counters */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala status = tavor_getperfcntr_cmd_post(state, port,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Update 64 bit software counters
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_XMIT_DATA_IDX]);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_XMIT_DATA_IDX] += tmp;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_RECV_DATA_IDX]);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_RECV_DATA_IDX] += tmp;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_XMIT_PKTS_IDX]);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_XMIT_PKTS_IDX] += tmp;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_RECV_PKTS_IDX]);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_RECV_PKTS_IDX] += tmp;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala for (i = 0; i < TAVOR_PERFCNTR64_NUM_COUNTERS; i++)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Update ksi64->tki64_last_read[]
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_XMIT_DATA_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_RECV_DATA_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_XMIT_PKTS_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_RECV_PKTS_IDX],
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_update_thread()
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Context: Entry point for a kernel thread
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Maintain 64 bit performance counters in software using the 32 bit
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * hardware counters.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalatavor_kstat_perfcntr64_update_thread(void *arg)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala tavor_state_t *state = (tavor_state_t *)arg;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Every one second update the values 64 bit software counters
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * for all ports. Exit if TAVOR_PERFCNTR64_THREAD_EXIT flag is set.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala while (!(ksi->tki_perfcntr64_flags & TAVOR_PERFCNTR64_THREAD_EXIT)) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala for (i = 0; i < state->ts_cfg_profile->cp_num_ports; i++) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (ksi->tki_perfcntr64[i].tki64_enabled) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* sleep for a second */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala (void) cv_timedwait(&ksi->tki_perfcntr64_cv,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_thread_create()
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Context: Called from the kstat context
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Create a thread that maintains 64 bit performance counters in software.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalatavor_kstat_perfcntr64_thread_create(tavor_state_t *state)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ASSERT(MUTEX_HELD(&ksi->tki_perfcntr64_lock));
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * One thread per tavor instance. Don't create a thread if already
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (!(ksi->tki_perfcntr64_flags & TAVOR_PERFCNTR64_THREAD_CREATED)) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi->tki_perfcntr64_thread_id = thr->t_did;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi->tki_perfcntr64_flags |= TAVOR_PERFCNTR64_THREAD_CREATED;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_thread_exit()
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Context: Called from attach, detach or kstat context
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalatavor_kstat_perfcntr64_thread_exit(tavor_ks_info_t *ksi)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ASSERT(MUTEX_HELD(&ksi->tki_perfcntr64_lock));
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (ksi->tki_perfcntr64_flags & TAVOR_PERFCNTR64_THREAD_CREATED) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Signal the thread to exit and wait until the thread exits.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi->tki_perfcntr64_flags |= TAVOR_PERFCNTR64_THREAD_EXIT;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_update()
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Context: Called from the kstat context
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * See the general comment on 64 bit kstats for performance counters:
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummalatavor_kstat_perfcntr64_update(kstat_t *ksp, int rw)
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data = (struct kstat_named *)(ksp->ks_data);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * 64 bit performance counters maintained by the software is not
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * enabled by default. Enable them upon a writing a non-zero value
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * to "enable" kstat. Disable them upon a writing zero to the
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * "enable" kstat.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (data[TAVOR_PERFCNTR64_ENABLE_IDX].value.ui32) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Reset the hardware counters to ensure that
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * the hardware counter doesn't max out
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * (and hence stop counting) before we get
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * a chance to reset the counter in
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * tavor_kstat_perfcntr64_update_thread.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* Enable 64 bit software counters */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala tavor_kstat_perfcntr64_thread_create(state);
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* Disable 64 bit software counters */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala for (i = 0; i < state->ts_cfg_profile->cp_num_ports;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (ksi->tki_perfcntr64[i].tki64_enabled) {
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala * Read the counters and update kstats.
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala if (tavor_kstat_perfcntr64_read(state, ksi64->tki64_port_num,
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data[TAVOR_PERFCNTR64_ENABLE_IDX].value.ui32 = 1;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data[TAVOR_PERFCNTR64_XMIT_DATA_IDX].value.ui64 =
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_XMIT_DATA_IDX] +
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_XMIT_DATA_IDX];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data[TAVOR_PERFCNTR64_RECV_DATA_IDX].value.ui64 =
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_RECV_DATA_IDX] +
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_RECV_DATA_IDX];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data[TAVOR_PERFCNTR64_XMIT_PKTS_IDX].value.ui64 =
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_XMIT_PKTS_IDX] +
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_XMIT_PKTS_IDX];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data[TAVOR_PERFCNTR64_RECV_PKTS_IDX].value.ui64 =
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_counters[TAVOR_PERFCNTR64_RECV_PKTS_IDX] +
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala ksi64->tki64_last_read[TAVOR_PERFCNTR64_RECV_PKTS_IDX];
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala /* return 0 in kstats if not enabled */
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala data[TAVOR_PERFCNTR64_ENABLE_IDX].value.ui32 = 0;
e9dc6bff6e018821c8c8ac7fe3e3b42e621e93aeRamaswamy Tummala for (i = 1; i < TAVOR_PERFCNTR64_NUM_COUNTERS; i++)