cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tout.c (4609B)


      1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
      2/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
      3
      4#include <linux/mlx5/driver.h>
      5#include "lib/tout.h"
      6
      7struct mlx5_timeouts {
      8	u64 to[MAX_TIMEOUT_TYPES];
      9};
     10
     11static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = {
     12	[MLX5_TO_FW_PRE_INIT_TIMEOUT_MS] = 120000,
     13	[MLX5_TO_FW_PRE_INIT_ON_RECOVERY_TIMEOUT_MS] = 7200000,
     14	[MLX5_TO_FW_PRE_INIT_WARN_MESSAGE_INTERVAL_MS] = 20000,
     15	[MLX5_TO_FW_PRE_INIT_WAIT_MS] = 2,
     16	[MLX5_TO_FW_INIT_MS] = 2000,
     17	[MLX5_TO_CMD_MS] = 60000,
     18	[MLX5_TO_PCI_TOGGLE_MS] =  2000,
     19	[MLX5_TO_HEALTH_POLL_INTERVAL_MS] =  2000,
     20	[MLX5_TO_FULL_CRDUMP_MS] = 60000,
     21	[MLX5_TO_FW_RESET_MS] = 60000,
     22	[MLX5_TO_FLUSH_ON_ERROR_MS] = 2000,
     23	[MLX5_TO_PCI_SYNC_UPDATE_MS] = 5000,
     24	[MLX5_TO_TEARDOWN_MS] = 3000,
     25	[MLX5_TO_FSM_REACTIVATE_MS] = 5000,
     26	[MLX5_TO_RECLAIM_PAGES_MS] = 5000,
     27	[MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000
     28};
     29
     30static void tout_set(struct mlx5_core_dev *dev, u64 val, enum mlx5_timeouts_types type)
     31{
     32	dev->timeouts->to[type] = val;
     33}
     34
     35void mlx5_tout_set_def_val(struct mlx5_core_dev *dev)
     36{
     37	int i;
     38
     39	for (i = 0; i < MAX_TIMEOUT_TYPES; i++)
     40		tout_set(dev, tout_def_sw_val[i], i);
     41}
     42
     43int mlx5_tout_init(struct mlx5_core_dev *dev)
     44{
     45	dev->timeouts = kmalloc(sizeof(*dev->timeouts), GFP_KERNEL);
     46	if (!dev->timeouts)
     47		return -ENOMEM;
     48
     49	return 0;
     50}
     51
     52void mlx5_tout_cleanup(struct mlx5_core_dev *dev)
     53{
     54	kfree(dev->timeouts);
     55}
     56
     57/* Time register consists of two fields to_multiplier(time out multiplier)
     58 * and to_value(time out value). to_value is the quantity of the time units and
     59 * to_multiplier is the type and should be one off these four values.
     60 * 0x0: millisecond
     61 * 0x1: seconds
     62 * 0x2: minutes
     63 * 0x3: hours
     64 * this function converts the time stored in the two register fields into
     65 * millisecond.
     66 */
     67static u64 tout_convert_reg_field_to_ms(u32 to_mul, u32 to_val)
     68{
     69	u64 msec = to_val;
     70
     71	to_mul &= 0x3;
     72	/* convert hours/minutes/seconds to miliseconds */
     73	if (to_mul)
     74		msec *= 1000 * int_pow(60, to_mul - 1);
     75
     76	return msec;
     77}
     78
     79static u64 tout_convert_iseg_to_ms(u32 iseg_to)
     80{
     81	return tout_convert_reg_field_to_ms(iseg_to >> 29, iseg_to & 0xfffff);
     82}
     83
     84static bool tout_is_supported(struct mlx5_core_dev *dev)
     85{
     86	return !!ioread32be(&dev->iseg->cmd_q_init_to);
     87}
     88
     89void mlx5_tout_query_iseg(struct mlx5_core_dev *dev)
     90{
     91	u32 to;
     92
     93	if (!tout_is_supported(dev))
     94		return;
     95
     96	to = ioread32be(&dev->iseg->cmd_q_init_to);
     97	tout_set(dev, tout_convert_iseg_to_ms(to), MLX5_TO_FW_INIT_MS);
     98
     99	to = ioread32be(&dev->iseg->cmd_exec_to);
    100	tout_set(dev, tout_convert_iseg_to_ms(to), MLX5_TO_CMD_MS);
    101}
    102
    103u64 _mlx5_tout_ms(struct mlx5_core_dev *dev, enum mlx5_timeouts_types type)
    104{
    105	return dev->timeouts->to[type];
    106}
    107
    108#define MLX5_TIMEOUT_QUERY(fld, reg_out) \
    109	({ \
    110	struct mlx5_ifc_default_timeout_bits *time_field; \
    111	u32 to_multi, to_value; \
    112	u64 to_val_ms; \
    113	\
    114	time_field = MLX5_ADDR_OF(dtor_reg, reg_out, fld); \
    115	to_multi = MLX5_GET(default_timeout, time_field, to_multiplier); \
    116	to_value = MLX5_GET(default_timeout, time_field, to_value); \
    117	to_val_ms = tout_convert_reg_field_to_ms(to_multi, to_value); \
    118	to_val_ms; \
    119	})
    120
    121#define MLX5_TIMEOUT_FILL(fld, reg_out, dev, to_type, to_extra) \
    122	({ \
    123	u64 fw_to = MLX5_TIMEOUT_QUERY(fld, reg_out); \
    124	tout_set(dev, fw_to + (to_extra), to_type); \
    125	fw_to; \
    126	})
    127
    128static int tout_query_dtor(struct mlx5_core_dev *dev)
    129{
    130	u64 pcie_toggle_to_val, tear_down_to_val;
    131	u32 out[MLX5_ST_SZ_DW(dtor_reg)] = {};
    132	u32 in[MLX5_ST_SZ_DW(dtor_reg)] = {};
    133	int err;
    134
    135	err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_DTOR, 0, 0);
    136	if (err)
    137		return err;
    138
    139	pcie_toggle_to_val = MLX5_TIMEOUT_FILL(pcie_toggle_to, out, dev, MLX5_TO_PCI_TOGGLE_MS, 0);
    140	MLX5_TIMEOUT_FILL(fw_reset_to, out, dev, MLX5_TO_FW_RESET_MS, pcie_toggle_to_val);
    141
    142	tear_down_to_val = MLX5_TIMEOUT_FILL(tear_down_to, out, dev, MLX5_TO_TEARDOWN_MS, 0);
    143	MLX5_TIMEOUT_FILL(pci_sync_update_to, out, dev, MLX5_TO_PCI_SYNC_UPDATE_MS,
    144			  tear_down_to_val);
    145
    146	MLX5_TIMEOUT_FILL(health_poll_to, out, dev, MLX5_TO_HEALTH_POLL_INTERVAL_MS, 0);
    147	MLX5_TIMEOUT_FILL(full_crdump_to, out, dev, MLX5_TO_FULL_CRDUMP_MS, 0);
    148	MLX5_TIMEOUT_FILL(flush_on_err_to, out, dev, MLX5_TO_FLUSH_ON_ERROR_MS, 0);
    149	MLX5_TIMEOUT_FILL(fsm_reactivate_to, out, dev, MLX5_TO_FSM_REACTIVATE_MS, 0);
    150	MLX5_TIMEOUT_FILL(reclaim_pages_to, out, dev, MLX5_TO_RECLAIM_PAGES_MS, 0);
    151	MLX5_TIMEOUT_FILL(reclaim_vfs_pages_to, out, dev, MLX5_TO_RECLAIM_VFS_PAGES_MS, 0);
    152
    153	return 0;
    154}
    155
    156int mlx5_tout_query_dtor(struct mlx5_core_dev *dev)
    157{
    158	if (tout_is_supported(dev))
    159		return tout_query_dtor(dev);
    160
    161	return 0;
    162}