1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2022 Cisco Systems, Inc.
3 * Copyright (c) 2022 Intel and/or its affiliates.
9 #include <vlib/pci/pci.h>
10 #include <vlib/dma/dma.h>
11 #include <vnet/plugin/plugin.h>
12 #include <vpp/app/version.h>
13 #include <vppinfra/linux/sysfs.h>
14 #include <dma_intel/dsa_intel.h>
16 VLIB_REGISTER_LOG_CLASS (intel_dsa_log, static) = {
17 .class_name = "intel_dsa",
20 intel_dsa_main_t intel_dsa_main;
23 intel_dsa_assign_channels (vlib_main_t *vm)
25 intel_dsa_main_t *idm = &intel_dsa_main;
26 intel_dsa_channel_t *ch, **chv = 0;
30 vec_foreach_index (n, idm->channels)
31 vec_append (chv, idm->channels[n]);
33 vec_validate (idm->dsa_threads, vlib_get_n_threads () - 1);
35 if (vec_len (chv) == 0)
37 dsa_log_debug ("No DSA channels found");
41 if (vec_len (chv) >= vlib_get_n_threads ())
44 n_threads = vlib_get_n_threads () % vec_len (chv) ?
45 vlib_get_n_threads () / vec_len (chv) + 1 :
46 vlib_get_n_threads () / vec_len (chv);
48 for (int i = 0; i < vlib_get_n_threads (); i++)
50 vlib_main_t *tvm = vlib_get_main_by_index (i);
51 ch = *vec_elt_at_index (chv, i / n_threads);
52 idm->dsa_threads[i].ch = ch;
53 ch->n_threads = n_threads;
54 dsa_log_debug ("Assigning channel %u/%u to thread %u (numa %u)", ch->did,
55 ch->qid, i, tvm->numa_node);
64 intel_dsa_map_region (intel_dsa_channel_t *ch)
66 static clib_error_t *error = NULL;
70 char path[256] = { 0 };
72 snprintf (path, sizeof (path), "%s/wq%d.%d", DSA_DEV_PATH, ch->did, ch->qid);
73 int fd = open (path, O_RDWR);
75 return clib_error_return (0, "failed to open dsa device %s", path);
78 clib_mem_vm_map_shared (0, size, fd, offset, "%s", (char *) path);
79 if (ch->portal == CLIB_MEM_VM_MAP_FAILED)
81 error = clib_error_return (0, "mmap portal %s failed", path);
90 intel_dsa_get_info (intel_dsa_channel_t *ch, clib_error_t **error)
94 u8 *dev_dir_name = 0, *wq_dir_name = 0;
97 dev_dir_name = format (0, "%s/dsa%d", SYS_DSA_PATH, ch->did);
100 f = format (f, "%v/numa_node%c", dev_dir_name, 0);
101 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
104 ch->numa = atoi ((char *) tmpstr);
106 wq_dir_name = format (0, "%s/%U", SYS_DSA_PATH, format_intel_dsa_addr, ch);
108 vec_reset_length (f);
109 f = format (f, "%v/max_transfer_size%c", wq_dir_name, 0);
110 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
113 ch->max_transfer_size = atoi ((char *) tmpstr);
115 vec_reset_length (f);
116 f = format (f, "%v/max_batch_size%c", wq_dir_name, 0);
117 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
120 ch->max_transfers = atoi ((char *) tmpstr);
122 vec_reset_length (f);
123 f = format (f, "%v/size%c", wq_dir_name, 0);
124 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
127 ch->size = atoi ((char *) tmpstr);
129 vec_reset_length (f);
130 f = format (f, "%v/type%c", wq_dir_name, 0);
131 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
136 if (!clib_strcmp ((char *) tmpstr, "enabled"))
137 ch->type = INTEL_DSA_DEVICE_TYPE_UNKNOWN;
138 else if (!clib_strcmp ((char *) tmpstr, "user"))
139 ch->type = INTEL_DSA_DEVICE_TYPE_USER;
140 else if (!clib_strcmp ((char *) tmpstr, "mdev"))
141 ch->type = INTEL_DSA_DEVICE_TYPE_KERNEL;
143 ch->type = INTEL_DSA_DEVICE_TYPE_UNKNOWN;
147 vec_reset_length (f);
148 f = format (f, "%v/state%c", wq_dir_name, 0);
149 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
154 if (!clib_strcmp ((char *) tmpstr, "enabled"))
161 vec_reset_length (f);
162 f = format (f, "%v/ats_disable%c", wq_dir_name, 0);
163 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
166 ch->ats_disable = atoi ((char *) tmpstr);
168 vec_reset_length (f);
169 f = format (f, "%v/block_on_fault%c", wq_dir_name, 0);
170 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
173 ch->block_on_fault = atoi ((char *) tmpstr);
175 vec_reset_length (f);
176 f = format (f, "%v/mode%c", wq_dir_name, 0);
177 err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
182 if (!clib_strcmp ((char *) tmpstr, "dedicated"))
190 vec_free (dev_dir_name);
191 vec_free (wq_dir_name);
196 vec_free (dev_dir_name);
197 vec_free (wq_dir_name);
203 intel_dsa_add_channel (vlib_main_t *vm, intel_dsa_channel_t *ch)
205 intel_dsa_main_t *dm = &intel_dsa_main;
206 clib_error_t *err = 0;
208 if (intel_dsa_map_region (ch))
209 return clib_error_return (0, "dsa open device failed");
211 if (intel_dsa_get_info (ch, &err))
212 return clib_error_return (err, "dsa info not scanned");
214 vec_validate (dm->channels, ch->numa);
215 vec_add1 (dm->channels[ch->numa], ch);
220 static clib_error_t *
221 dsa_config (vlib_main_t *vm, unformat_input_t *input)
223 clib_error_t *error = 0;
224 intel_dsa_channel_t *ch;
227 if (intel_dsa_main.lock == 0)
228 clib_spinlock_init (&(intel_dsa_main.lock));
230 if ((error = vlib_dma_register_backend (vm, &intel_dsa_backend)))
233 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
235 if (unformat (input, "dev wq%d.%d", &did, &qid))
237 ch = clib_mem_alloc_aligned (sizeof (*ch), CLIB_CACHE_LINE_BYTES);
238 clib_memset (ch, 0, sizeof (*ch));
241 if (intel_dsa_add_channel (vm, ch))
244 else if (unformat_skip_white_space (input))
248 error = clib_error_return (0, "unknown input `%U'",
249 format_unformat_error, input);
258 VLIB_CONFIG_FUNCTION (dsa_config, "dsa");
261 intel_dsa_num_workers_change (vlib_main_t *vm)
263 intel_dsa_assign_channels (vm);
267 VLIB_NUM_WORKERS_CHANGE_FN (intel_dsa_num_workers_change);
269 VLIB_PLUGIN_REGISTER () = {
270 .version = VPP_BUILD_VER,
271 .description = "Intel DSA Backend",