Line data Source code
1 : /* SPDX-License-Identifier: Apache-2.0
2 : * Copyright (c) 2022 Cisco Systems, Inc.
3 : * Copyright (c) 2022 Intel and/or its affiliates.
4 : */
5 : #include <sys/types.h>
6 : #include <sys/stat.h>
7 : #include <fcntl.h>
8 : #include <vlib/vlib.h>
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>
15 :
16 559 : VLIB_REGISTER_LOG_CLASS (intel_dsa_log, static) = {
17 : .class_name = "intel_dsa",
18 : };
19 :
20 : intel_dsa_main_t intel_dsa_main;
21 :
22 : void
23 559 : intel_dsa_assign_channels (vlib_main_t *vm)
24 : {
25 559 : intel_dsa_main_t *idm = &intel_dsa_main;
26 559 : intel_dsa_channel_t *ch, **chv = 0;
27 : u16 n_threads;
28 : int n;
29 :
30 559 : vec_foreach_index (n, idm->channels)
31 0 : vec_append (chv, idm->channels[n]);
32 :
33 559 : vec_validate (idm->dsa_threads, vlib_get_n_threads () - 1);
34 :
35 559 : if (vec_len (chv) == 0)
36 : {
37 559 : dsa_log_debug ("No DSA channels found");
38 559 : goto done;
39 : }
40 :
41 0 : if (vec_len (chv) >= vlib_get_n_threads ())
42 0 : n_threads = 1;
43 : else
44 0 : n_threads = vlib_get_n_threads () % vec_len (chv) ?
45 0 : vlib_get_n_threads () / vec_len (chv) + 1 :
46 0 : vlib_get_n_threads () / vec_len (chv);
47 :
48 0 : for (int i = 0; i < vlib_get_n_threads (); i++)
49 : {
50 0 : vlib_main_t *tvm = vlib_get_main_by_index (i);
51 0 : ch = *vec_elt_at_index (chv, i / n_threads);
52 0 : idm->dsa_threads[i].ch = ch;
53 0 : ch->n_threads = n_threads;
54 0 : dsa_log_debug ("Assigning channel %u/%u to thread %u (numa %u)", ch->did,
55 : ch->qid, i, tvm->numa_node);
56 : }
57 :
58 0 : done:
59 : /* free */
60 559 : vec_free (chv);
61 559 : }
62 :
63 : static clib_error_t *
64 0 : intel_dsa_map_region (intel_dsa_channel_t *ch)
65 : {
66 : static clib_error_t *error = NULL;
67 : /* map one page */
68 0 : uword size = 0x1000;
69 0 : uword offset = 0;
70 0 : char path[256] = { 0 };
71 :
72 0 : snprintf (path, sizeof (path), "%s/wq%d.%d", DSA_DEV_PATH, ch->did, ch->qid);
73 0 : int fd = open (path, O_RDWR);
74 0 : if (fd < 0)
75 0 : return clib_error_return (0, "failed to open dsa device %s", path);
76 :
77 0 : ch->portal =
78 0 : clib_mem_vm_map_shared (0, size, fd, offset, "%s", (char *) path);
79 0 : if (ch->portal == CLIB_MEM_VM_MAP_FAILED)
80 : {
81 0 : error = clib_error_return (0, "mmap portal %s failed", path);
82 0 : close (fd);
83 0 : return error;
84 : }
85 :
86 0 : return NULL;
87 : }
88 :
89 : static clib_error_t *
90 0 : intel_dsa_get_info (intel_dsa_channel_t *ch, clib_error_t **error)
91 : {
92 : clib_error_t *err;
93 : u8 *tmpstr;
94 0 : u8 *dev_dir_name = 0, *wq_dir_name = 0;
95 :
96 0 : u8 *f = 0;
97 0 : dev_dir_name = format (0, "%s/dsa%d", SYS_DSA_PATH, ch->did);
98 :
99 0 : vec_reset_length (f);
100 0 : f = format (f, "%v/numa_node%c", dev_dir_name, 0);
101 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
102 0 : if (err)
103 0 : goto error;
104 0 : ch->numa = atoi ((char *) tmpstr);
105 :
106 0 : wq_dir_name = format (0, "%s/%U", SYS_DSA_PATH, format_intel_dsa_addr, ch);
107 :
108 0 : vec_reset_length (f);
109 0 : f = format (f, "%v/max_transfer_size%c", wq_dir_name, 0);
110 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
111 0 : if (err)
112 0 : goto error;
113 0 : ch->max_transfer_size = atoi ((char *) tmpstr);
114 :
115 0 : vec_reset_length (f);
116 0 : f = format (f, "%v/max_batch_size%c", wq_dir_name, 0);
117 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
118 0 : if (err)
119 0 : goto error;
120 0 : ch->max_transfers = atoi ((char *) tmpstr);
121 :
122 0 : vec_reset_length (f);
123 0 : f = format (f, "%v/size%c", wq_dir_name, 0);
124 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
125 0 : if (err)
126 0 : goto error;
127 0 : ch->size = atoi ((char *) tmpstr);
128 :
129 0 : vec_reset_length (f);
130 0 : f = format (f, "%v/type%c", wq_dir_name, 0);
131 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
132 0 : if (err)
133 0 : goto error;
134 0 : if (tmpstr)
135 : {
136 0 : if (!clib_strcmp ((char *) tmpstr, "enabled"))
137 0 : ch->type = INTEL_DSA_DEVICE_TYPE_UNKNOWN;
138 0 : else if (!clib_strcmp ((char *) tmpstr, "user"))
139 0 : ch->type = INTEL_DSA_DEVICE_TYPE_USER;
140 0 : else if (!clib_strcmp ((char *) tmpstr, "mdev"))
141 0 : ch->type = INTEL_DSA_DEVICE_TYPE_KERNEL;
142 : else
143 0 : ch->type = INTEL_DSA_DEVICE_TYPE_UNKNOWN;
144 0 : vec_free (tmpstr);
145 : }
146 :
147 0 : vec_reset_length (f);
148 0 : f = format (f, "%v/state%c", wq_dir_name, 0);
149 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
150 0 : if (err)
151 0 : goto error;
152 0 : if (tmpstr)
153 : {
154 0 : if (!clib_strcmp ((char *) tmpstr, "enabled"))
155 0 : ch->state = 1;
156 : else
157 0 : ch->state = 0;
158 0 : vec_free (tmpstr);
159 : }
160 :
161 0 : vec_reset_length (f);
162 0 : f = format (f, "%v/ats_disable%c", wq_dir_name, 0);
163 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
164 0 : if (err)
165 0 : goto error;
166 0 : ch->ats_disable = atoi ((char *) tmpstr);
167 :
168 0 : vec_reset_length (f);
169 0 : f = format (f, "%v/block_on_fault%c", wq_dir_name, 0);
170 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
171 0 : if (err)
172 0 : goto error;
173 0 : ch->block_on_fault = atoi ((char *) tmpstr);
174 :
175 0 : vec_reset_length (f);
176 0 : f = format (f, "%v/mode%c", wq_dir_name, 0);
177 0 : err = clib_sysfs_read ((char *) f, "%s", &tmpstr);
178 0 : if (err)
179 0 : goto error;
180 0 : if (tmpstr)
181 : {
182 0 : if (!clib_strcmp ((char *) tmpstr, "dedicated"))
183 0 : ch->mode = 1;
184 : else
185 0 : ch->mode = 0;
186 0 : vec_free (tmpstr);
187 : }
188 :
189 0 : vec_free (f);
190 0 : vec_free (dev_dir_name);
191 0 : vec_free (wq_dir_name);
192 0 : return NULL;
193 :
194 0 : error:
195 0 : vec_free (f);
196 0 : vec_free (dev_dir_name);
197 0 : vec_free (wq_dir_name);
198 :
199 0 : return err;
200 : }
201 :
202 : clib_error_t *
203 0 : intel_dsa_add_channel (vlib_main_t *vm, intel_dsa_channel_t *ch)
204 : {
205 0 : intel_dsa_main_t *dm = &intel_dsa_main;
206 0 : clib_error_t *err = 0;
207 :
208 0 : if (intel_dsa_map_region (ch))
209 0 : return clib_error_return (0, "dsa open device failed");
210 :
211 0 : if (intel_dsa_get_info (ch, &err))
212 0 : return clib_error_return (err, "dsa info not scanned");
213 :
214 0 : vec_validate (dm->channels, ch->numa);
215 0 : vec_add1 (dm->channels[ch->numa], ch);
216 :
217 0 : return err;
218 : }
219 :
220 : static clib_error_t *
221 559 : dsa_config (vlib_main_t *vm, unformat_input_t *input)
222 : {
223 559 : clib_error_t *error = 0;
224 : intel_dsa_channel_t *ch;
225 : u32 did, qid;
226 :
227 559 : if (intel_dsa_main.lock == 0)
228 559 : clib_spinlock_init (&(intel_dsa_main.lock));
229 :
230 559 : if ((error = vlib_dma_register_backend (vm, &intel_dsa_backend)))
231 0 : goto done;
232 :
233 559 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
234 : {
235 0 : if (unformat (input, "dev wq%d.%d", &did, &qid))
236 : {
237 0 : ch = clib_mem_alloc_aligned (sizeof (*ch), CLIB_CACHE_LINE_BYTES);
238 0 : clib_memset (ch, 0, sizeof (*ch));
239 0 : ch->did = did;
240 0 : ch->qid = qid;
241 0 : if (intel_dsa_add_channel (vm, ch))
242 0 : clib_mem_free (ch);
243 : }
244 0 : else if (unformat_skip_white_space (input))
245 : ;
246 : else
247 : {
248 0 : error = clib_error_return (0, "unknown input `%U'",
249 : format_unformat_error, input);
250 0 : goto done;
251 : }
252 : }
253 :
254 559 : done:
255 559 : return error;
256 : }
257 :
258 5066 : VLIB_CONFIG_FUNCTION (dsa_config, "dsa");
259 :
260 : clib_error_t *
261 559 : intel_dsa_num_workers_change (vlib_main_t *vm)
262 : {
263 559 : intel_dsa_assign_channels (vm);
264 559 : return 0;
265 : }
266 :
267 1119 : VLIB_NUM_WORKERS_CHANGE_FN (intel_dsa_num_workers_change);
268 :
269 : VLIB_PLUGIN_REGISTER () = {
270 : .version = VPP_BUILD_VER,
271 : .description = "Intel DSA Backend",
272 : };
|