Blame src/vma/dev/time_converter.cpp

Packit 6d2c1b
/*
Packit 6d2c1b
 * Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
Packit 6d2c1b
 *
Packit 6d2c1b
 * This software is available to you under a choice of one of two
Packit 6d2c1b
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit 6d2c1b
 * General Public License (GPL) Version 2, available from the file
Packit 6d2c1b
 * COPYING in the main directory of this source tree, or the
Packit 6d2c1b
 * BSD license below:
Packit 6d2c1b
 *
Packit 6d2c1b
 *     Redistribution and use in source and binary forms, with or
Packit 6d2c1b
 *     without modification, are permitted provided that the following
Packit 6d2c1b
 *     conditions are met:
Packit 6d2c1b
 *
Packit 6d2c1b
 *      - Redistributions of source code must retain the above
Packit 6d2c1b
 *        copyright notice, this list of conditions and the following
Packit 6d2c1b
 *        disclaimer.
Packit 6d2c1b
 *
Packit 6d2c1b
 *      - Redistributions in binary form must reproduce the above
Packit 6d2c1b
 *        copyright notice, this list of conditions and the following
Packit 6d2c1b
 *        disclaimer in the documentation and/or other materials
Packit 6d2c1b
 *        provided with the distribution.
Packit 6d2c1b
 *
Packit 6d2c1b
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 6d2c1b
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 6d2c1b
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 6d2c1b
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit 6d2c1b
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit 6d2c1b
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 6d2c1b
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit 6d2c1b
 * SOFTWARE.
Packit 6d2c1b
 */
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
#include "time_converter.h"
Packit 6d2c1b
Packit 6d2c1b
#include <stdlib.h>
Packit 6d2c1b
#include "vlogger/vlogger.h"
Packit 6d2c1b
#include "utils/rdtsc.h"
Packit 6d2c1b
Packit 6d2c1b
#include "vma/util/sys_vars.h"
Packit 6d2c1b
#include "vma/util/instrumentation.h"
Packit 6d2c1b
#include "vma/event/event_handler_manager.h"
Packit 6d2c1b
#include "vma/ib/base/verbs_extra.h"
Packit 6d2c1b
#include "vma/dev/net_device_table_mgr.h"
Packit 6d2c1b
Packit 6d2c1b
#define MODULE_NAME             "time_converter"
Packit 6d2c1b
Packit 6d2c1b
#define ibchtc_logerr __log_err
Packit 6d2c1b
#define ibchtc_logwarn __log_warn
Packit 6d2c1b
#define ibchtc_loginfo __log_info
Packit 6d2c1b
#define ibchtc_logdbg __log_dbg
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
#define IB_CTX_TC_DEVIATION_THRESHOLD 10
Packit 6d2c1b
Packit 6d2c1b
#define VMA_QUERY_DEVICE_SUPPORTED (1 << 0)
Packit 6d2c1b
#define VMA_QUERY_VALUES_SUPPORTED (1 << 1)
Packit 6d2c1b
Packit 6d2c1b
uint32_t time_converter::get_single_converter_status(struct ibv_context* ctx) {
Packit 6d2c1b
	uint32_t dev_status = 0;
Packit 6d2c1b
#ifdef DEFINED_IBV_CQ_TIMESTAMP
Packit 6d2c1b
	int rval;
Packit 6d2c1b
Packit 6d2c1b
	// Checking if ibv_exp_query_device() is valid
Packit 6d2c1b
	vma_ibv_device_attr_ex device_attr;
Packit 6d2c1b
	memset(&device_attr, 0, sizeof(device_attr));
Packit 6d2c1b
	device_attr.comp_mask = VMA_IBV_DEVICE_ATTR_HCA_CORE_CLOCK;
Packit 6d2c1b
Packit 6d2c1b
	if ((rval = vma_ibv_query_device(ctx ,&device_attr)) || !device_attr.hca_core_clock) {
Packit 6d2c1b
		ibchtc_logdbg("time_converter::get_single_converter_status :Error in querying hca core clock "
Packit 6d2c1b
				"(vma_ibv_query_device() return value=%d ) (ibv context %p) (errno=%d %m)\n", rval, ctx, errno);
Packit 6d2c1b
	} else {
Packit 6d2c1b
		dev_status |= VMA_QUERY_DEVICE_SUPPORTED;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	// Checking if ibv_exp_query_values() is valid
Packit 6d2c1b
	vma_ts_values queried_values;
Packit 6d2c1b
	memset(&queried_values, 0, sizeof(queried_values));
Packit 6d2c1b
	queried_values.comp_mask = VMA_IBV_VALUES_MASK_RAW_CLOCK;
Packit 6d2c1b
	if ((rval = vma_ibv_query_values(ctx, &queried_values)) || !vma_get_ts_val(queried_values)) {
Packit 6d2c1b
		ibchtc_logdbg("time_converter::get_single_converter_status :Error in querying hw clock, can't convert"
Packit 6d2c1b
				" hw time to system time (vma_ibv_query_values() return value=%d ) (ibv context %p) (errno=%d %m)\n", rval, ctx, errno);
Packit 6d2c1b
	} else {
Packit 6d2c1b
		dev_status |= VMA_QUERY_VALUES_SUPPORTED;
Packit 6d2c1b
	}
Packit 6d2c1b
#else
Packit 6d2c1b
	NOT_IN_USE(ctx);
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
	return dev_status;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
ts_conversion_mode_t time_converter::update_device_converters_status(net_device_map_t& net_devices)
Packit 6d2c1b
{
Packit 6d2c1b
	ibchtc_logdbg("Checking RX HW time stamp status for all devices [%d]", net_devices.size());
Packit 6d2c1b
	ts_conversion_mode_t ts_conversion_mode = TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
Packit 6d2c1b
	if (net_devices.empty()) {
Packit 6d2c1b
		ibchtc_logdbg("No supported devices was found, return");
Packit 6d2c1b
		return ts_conversion_mode;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
#ifdef DEFINED_IBV_CQ_TIMESTAMP
Packit 6d2c1b
Packit 6d2c1b
	if (safe_mce_sys().hw_ts_conversion_mode != TS_CONVERSION_MODE_DISABLE) {
Packit 6d2c1b
		uint32_t devs_status = VMA_QUERY_DEVICE_SUPPORTED | VMA_QUERY_VALUES_SUPPORTED;
Packit 6d2c1b
Packit 6d2c1b
		/* Get common time conversion mode for all devices */
Packit 6d2c1b
		for (net_device_map_index_t::iterator dev_iter = net_devices.begin(); dev_iter != net_devices.end(); dev_iter++) {
Packit 6d2c1b
			if (dev_iter->second->get_state() == net_device_val::RUNNING) {
Packit 6d2c1b
				slave_data_vector_t slaves = dev_iter->second->get_slave_array();
Packit 6d2c1b
				for (slave_data_vector_t::iterator slaves_iter = slaves.begin(); slaves_iter != slaves.end(); slaves_iter++) {
Packit 6d2c1b
					devs_status &= get_single_converter_status((*slaves_iter)->p_ib_ctx->get_ibv_context());
Packit 6d2c1b
				}
Packit 6d2c1b
			}
Packit 6d2c1b
		}
Packit 6d2c1b
Packit 6d2c1b
		switch (safe_mce_sys().hw_ts_conversion_mode) {
Packit 6d2c1b
		case TS_CONVERSION_MODE_RAW:
Packit 6d2c1b
			ts_conversion_mode = devs_status & VMA_QUERY_DEVICE_SUPPORTED ? TS_CONVERSION_MODE_RAW : TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
			break;
Packit 6d2c1b
		case TS_CONVERSION_MODE_BEST_POSSIBLE:
Packit 6d2c1b
			if (devs_status == (VMA_QUERY_DEVICE_SUPPORTED | VMA_QUERY_VALUES_SUPPORTED)) {
Packit 6d2c1b
				ts_conversion_mode = TS_CONVERSION_MODE_SYNC;
Packit 6d2c1b
			} else {
Packit 6d2c1b
				ts_conversion_mode = devs_status & VMA_QUERY_DEVICE_SUPPORTED ? TS_CONVERSION_MODE_RAW : TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
			}
Packit 6d2c1b
			break;
Packit 6d2c1b
		case TS_CONVERSION_MODE_SYNC:
Packit 6d2c1b
			ts_conversion_mode = devs_status == (VMA_QUERY_DEVICE_SUPPORTED | VMA_QUERY_VALUES_SUPPORTED) ? TS_CONVERSION_MODE_SYNC : TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
			break;
Packit 6d2c1b
		case TS_CONVERSION_MODE_PTP:
Packit 6d2c1b
			ts_conversion_mode = devs_status == (VMA_QUERY_DEVICE_SUPPORTED | VMA_QUERY_VALUES_SUPPORTED) ? TS_CONVERSION_MODE_PTP : TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
			break;
Packit 6d2c1b
		default:
Packit 6d2c1b
			ts_conversion_mode = TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
			break;
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
	ibchtc_logdbg("Conversion status was set to %d", ts_conversion_mode);
Packit 6d2c1b
Packit 6d2c1b
	for (net_device_map_index_t::iterator dev_iter = net_devices.begin(); dev_iter != net_devices.end(); dev_iter++) {
Packit 6d2c1b
		slave_data_vector_t slaves = dev_iter->second->get_slave_array();
Packit 6d2c1b
		for (slave_data_vector_t::iterator slaves_iter = slaves.begin(); slaves_iter != slaves.end(); slaves_iter++) {
Packit 6d2c1b
			ts_conversion_mode_t dev_ts_conversion_mode = dev_iter->second->get_state() == net_device_val::RUNNING ? ts_conversion_mode : TS_CONVERSION_MODE_DISABLE;
Packit 6d2c1b
			(*slaves_iter)->p_ib_ctx->set_ctx_time_converter_status(dev_ts_conversion_mode);
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	return ts_conversion_mode;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void time_converter::clean_obj()
Packit 6d2c1b
{
Packit 6d2c1b
	if (is_cleaned()) {
Packit 6d2c1b
		return ;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	set_cleaned();
Packit 6d2c1b
	m_timer_handle = NULL;
Packit 6d2c1b
	if (g_p_event_handler_manager->is_running()) {
Packit 6d2c1b
		g_p_event_handler_manager->unregister_timers_event_and_delete(this);
Packit 6d2c1b
	} else {
Packit 6d2c1b
		cleanable_obj::clean_obj();
Packit 6d2c1b
	}
Packit 6d2c1b
}