File Index
Files and directories
Sign in
FILE

tout.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c C
  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	[MLX5_TO_RESET_UNLOAD_MS] = 300000
 29};
 30
 31static void tout_set(struct mlx5_core_dev *dev, u64 val, enum mlx5_timeouts_types type)
 32{
 33	dev->timeouts->to[type] = val;
 34}
 35
 36int mlx5_tout_init(struct mlx5_core_dev *dev)
 37{
 38	int i;
 39
 40	dev->timeouts = kmalloc(sizeof(*dev->timeouts), GFP_KERNEL);
 41	if (!dev->timeouts)
 42		return -ENOMEM;
 43
 44	for (i = 0; i < MAX_TIMEOUT_TYPES; i++)
 45		tout_set(dev, tout_def_sw_val[i], i);
 46
 47	return 0;
 48}
 49
 50void mlx5_tout_cleanup(struct mlx5_core_dev *dev)
 51{
 52	kfree(dev->timeouts);
 53}
 54
 55/* Time register consists of two fields to_multiplier(time out multiplier)
 56 * and to_value(time out value). to_value is the quantity of the time units and
 57 * to_multiplier is the type and should be one off these four values.
 58 * 0x0: millisecond
 59 * 0x1: seconds
 60 * 0x2: minutes
 61 * 0x3: hours
 62 * this function converts the time stored in the two register fields into
 63 * millisecond.
 64 */
 65static u64 tout_convert_reg_field_to_ms(u32 to_mul, u32 to_val)
 66{
 67	u64 msec = to_val;
 68
 69	to_mul &= 0x3;
 70	/* convert hours/minutes/seconds to miliseconds */
 71	if (to_mul)
 72		msec *= 1000 * int_pow(60, to_mul - 1);
 73
 74	return msec;
 75}
 76
 77static u64 tout_convert_iseg_to_ms(u32 iseg_to)
 78{
 79	return tout_convert_reg_field_to_ms(iseg_to >> 29, iseg_to & 0xfffff);
 80}
 81
 82static bool tout_is_supported(struct mlx5_core_dev *dev)
 83{
 84	return !!ioread32be(&dev->iseg->cmd_q_init_to);
 85}
 86
 87void mlx5_tout_query_iseg(struct mlx5_core_dev *dev)
 88{
 89	u32 to;
 90
 91	if (!tout_is_supported(dev))
 92		return;
 93
 94	to = ioread32be(&dev->iseg->cmd_q_init_to);
 95	tout_set(dev, tout_convert_iseg_to_ms(to), MLX5_TO_FW_INIT_MS);
 96
 97	to = ioread32be(&dev->iseg->cmd_exec_to);
 98	tout_set(dev, tout_convert_iseg_to_ms(to), MLX5_TO_CMD_MS);
 99}
100
101u64 _mlx5_tout_ms(struct mlx5_core_dev *dev, enum mlx5_timeouts_types type)
102{
103	return dev->timeouts->to[type];
104}
105
106#define MLX5_TIMEOUT_QUERY(fld, reg_out) \
107	({ \
108	struct mlx5_ifc_default_timeout_bits *time_field; \
109	u32 to_multi, to_value; \
110	u64 to_val_ms; \
111	\
112	time_field = MLX5_ADDR_OF(dtor_reg, reg_out, fld); \
113	to_multi = MLX5_GET(default_timeout, time_field, to_multiplier); \
114	to_value = MLX5_GET(default_timeout, time_field, to_value); \
115	to_val_ms = tout_convert_reg_field_to_ms(to_multi, to_value); \
116	to_val_ms; \
117	})
118
119#define MLX5_TIMEOUT_FILL(fld, reg_out, dev, to_type, to_extra) \
120	({ \
121	u64 fw_to = MLX5_TIMEOUT_QUERY(fld, reg_out); \
122	if (fw_to) \
123		tout_set(dev, fw_to + (to_extra), to_type); \
124	fw_to; \
125	})
126
127static int tout_query_dtor(struct mlx5_core_dev *dev)
128{
129	u64 pcie_toggle_to_val, tear_down_to_val;
130	u32 out[MLX5_ST_SZ_DW(dtor_reg)] = {};
131	u32 in[MLX5_ST_SZ_DW(dtor_reg)] = {};
132	int err;
133
134	err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_DTOR, 0, 0);
135	if (err)
136		return err;
137
138	pcie_toggle_to_val = MLX5_TIMEOUT_FILL(pcie_toggle_to, out, dev, MLX5_TO_PCI_TOGGLE_MS, 0);
139	MLX5_TIMEOUT_FILL(fw_reset_to, out, dev, MLX5_TO_FW_RESET_MS, pcie_toggle_to_val);
140
141	tear_down_to_val = MLX5_TIMEOUT_FILL(tear_down_to, out, dev, MLX5_TO_TEARDOWN_MS, 0);
142	MLX5_TIMEOUT_FILL(pci_sync_update_to, out, dev, MLX5_TO_PCI_SYNC_UPDATE_MS,
143			  tear_down_to_val);
144
145	MLX5_TIMEOUT_FILL(health_poll_to, out, dev, MLX5_TO_HEALTH_POLL_INTERVAL_MS, 0);
146	MLX5_TIMEOUT_FILL(full_crdump_to, out, dev, MLX5_TO_FULL_CRDUMP_MS, 0);
147	MLX5_TIMEOUT_FILL(flush_on_err_to, out, dev, MLX5_TO_FLUSH_ON_ERROR_MS, 0);
148	MLX5_TIMEOUT_FILL(fsm_reactivate_to, out, dev, MLX5_TO_FSM_REACTIVATE_MS, 0);
149	MLX5_TIMEOUT_FILL(reclaim_pages_to, out, dev, MLX5_TO_RECLAIM_PAGES_MS, 0);
150	MLX5_TIMEOUT_FILL(reclaim_vfs_pages_to, out, dev, MLX5_TO_RECLAIM_VFS_PAGES_MS, 0);
151	MLX5_TIMEOUT_FILL(reset_unload_to, out, dev, MLX5_TO_RESET_UNLOAD_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}
~/ Read-only file preview.