powerpc/tm: Fix restoring FP/VMX facility incorrectly on interrupts
[sfrench/cifs-2.6.git] / drivers / net / netdevsim / dev.c
1 /*
2  * Copyright (c) 2018 Cumulus Networks. All rights reserved.
3  * Copyright (c) 2018 David Ahern <dsa@cumulusnetworks.com>
4  * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
5  *
6  * This software is licensed under the GNU General License Version 2,
7  * June 1991 as shown in the file COPYING in the top-level directory of this
8  * source tree.
9  *
10  * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
11  * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
12  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
14  * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
15  * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16  */
17
18 #include <linux/debugfs.h>
19 #include <linux/device.h>
20 #include <linux/list.h>
21 #include <linux/mutex.h>
22 #include <linux/random.h>
23 #include <linux/rtnetlink.h>
24 #include <net/devlink.h>
25
26 #include "netdevsim.h"
27
28 static struct dentry *nsim_dev_ddir;
29
30 static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
31 {
32         char dev_ddir_name[16];
33
34         sprintf(dev_ddir_name, DRV_NAME "%u", nsim_dev->nsim_bus_dev->dev.id);
35         nsim_dev->ddir = debugfs_create_dir(dev_ddir_name, nsim_dev_ddir);
36         if (IS_ERR_OR_NULL(nsim_dev->ddir))
37                 return PTR_ERR_OR_ZERO(nsim_dev->ddir) ?: -EINVAL;
38         nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir);
39         if (IS_ERR_OR_NULL(nsim_dev->ports_ddir))
40                 return PTR_ERR_OR_ZERO(nsim_dev->ports_ddir) ?: -EINVAL;
41         debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir,
42                             &nsim_dev->fw_update_status);
43         return 0;
44 }
45
46 static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev)
47 {
48         debugfs_remove_recursive(nsim_dev->ports_ddir);
49         debugfs_remove_recursive(nsim_dev->ddir);
50 }
51
52 static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
53                                       struct nsim_dev_port *nsim_dev_port)
54 {
55         char port_ddir_name[16];
56         char dev_link_name[32];
57
58         sprintf(port_ddir_name, "%u", nsim_dev_port->port_index);
59         nsim_dev_port->ddir = debugfs_create_dir(port_ddir_name,
60                                                  nsim_dev->ports_ddir);
61         if (IS_ERR_OR_NULL(nsim_dev_port->ddir))
62                 return -ENOMEM;
63
64         sprintf(dev_link_name, "../../../" DRV_NAME "%u",
65                 nsim_dev->nsim_bus_dev->dev.id);
66         debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name);
67
68         return 0;
69 }
70
71 static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
72 {
73         debugfs_remove_recursive(nsim_dev_port->ddir);
74 }
75
76 static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
77 {
78         struct nsim_dev *nsim_dev = priv;
79
80         return nsim_fib_get_val(nsim_dev->fib_data,
81                                 NSIM_RESOURCE_IPV4_FIB, false);
82 }
83
84 static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv)
85 {
86         struct nsim_dev *nsim_dev = priv;
87
88         return nsim_fib_get_val(nsim_dev->fib_data,
89                                 NSIM_RESOURCE_IPV4_FIB_RULES, false);
90 }
91
92 static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv)
93 {
94         struct nsim_dev *nsim_dev = priv;
95
96         return nsim_fib_get_val(nsim_dev->fib_data,
97                                 NSIM_RESOURCE_IPV6_FIB, false);
98 }
99
100 static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv)
101 {
102         struct nsim_dev *nsim_dev = priv;
103
104         return nsim_fib_get_val(nsim_dev->fib_data,
105                                 NSIM_RESOURCE_IPV6_FIB_RULES, false);
106 }
107
108 static int nsim_dev_resources_register(struct devlink *devlink)
109 {
110         struct nsim_dev *nsim_dev = devlink_priv(devlink);
111         struct devlink_resource_size_params params = {
112                 .size_max = (u64)-1,
113                 .size_granularity = 1,
114                 .unit = DEVLINK_RESOURCE_UNIT_ENTRY
115         };
116         int err;
117         u64 n;
118
119         /* Resources for IPv4 */
120         err = devlink_resource_register(devlink, "IPv4", (u64)-1,
121                                         NSIM_RESOURCE_IPV4,
122                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
123                                         &params);
124         if (err) {
125                 pr_err("Failed to register IPv4 top resource\n");
126                 goto out;
127         }
128
129         n = nsim_fib_get_val(nsim_dev->fib_data,
130                              NSIM_RESOURCE_IPV4_FIB, true);
131         err = devlink_resource_register(devlink, "fib", n,
132                                         NSIM_RESOURCE_IPV4_FIB,
133                                         NSIM_RESOURCE_IPV4, &params);
134         if (err) {
135                 pr_err("Failed to register IPv4 FIB resource\n");
136                 return err;
137         }
138
139         n = nsim_fib_get_val(nsim_dev->fib_data,
140                              NSIM_RESOURCE_IPV4_FIB_RULES, true);
141         err = devlink_resource_register(devlink, "fib-rules", n,
142                                         NSIM_RESOURCE_IPV4_FIB_RULES,
143                                         NSIM_RESOURCE_IPV4, &params);
144         if (err) {
145                 pr_err("Failed to register IPv4 FIB rules resource\n");
146                 return err;
147         }
148
149         /* Resources for IPv6 */
150         err = devlink_resource_register(devlink, "IPv6", (u64)-1,
151                                         NSIM_RESOURCE_IPV6,
152                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
153                                         &params);
154         if (err) {
155                 pr_err("Failed to register IPv6 top resource\n");
156                 goto out;
157         }
158
159         n = nsim_fib_get_val(nsim_dev->fib_data,
160                              NSIM_RESOURCE_IPV6_FIB, true);
161         err = devlink_resource_register(devlink, "fib", n,
162                                         NSIM_RESOURCE_IPV6_FIB,
163                                         NSIM_RESOURCE_IPV6, &params);
164         if (err) {
165                 pr_err("Failed to register IPv6 FIB resource\n");
166                 return err;
167         }
168
169         n = nsim_fib_get_val(nsim_dev->fib_data,
170                              NSIM_RESOURCE_IPV6_FIB_RULES, true);
171         err = devlink_resource_register(devlink, "fib-rules", n,
172                                         NSIM_RESOURCE_IPV6_FIB_RULES,
173                                         NSIM_RESOURCE_IPV6, &params);
174         if (err) {
175                 pr_err("Failed to register IPv6 FIB rules resource\n");
176                 return err;
177         }
178
179         devlink_resource_occ_get_register(devlink,
180                                           NSIM_RESOURCE_IPV4_FIB,
181                                           nsim_dev_ipv4_fib_resource_occ_get,
182                                           nsim_dev);
183         devlink_resource_occ_get_register(devlink,
184                                           NSIM_RESOURCE_IPV4_FIB_RULES,
185                                           nsim_dev_ipv4_fib_rules_res_occ_get,
186                                           nsim_dev);
187         devlink_resource_occ_get_register(devlink,
188                                           NSIM_RESOURCE_IPV6_FIB,
189                                           nsim_dev_ipv6_fib_resource_occ_get,
190                                           nsim_dev);
191         devlink_resource_occ_get_register(devlink,
192                                           NSIM_RESOURCE_IPV6_FIB_RULES,
193                                           nsim_dev_ipv6_fib_rules_res_occ_get,
194                                           nsim_dev);
195 out:
196         return err;
197 }
198
199 static int nsim_dev_reload(struct devlink *devlink,
200                            struct netlink_ext_ack *extack)
201 {
202         struct nsim_dev *nsim_dev = devlink_priv(devlink);
203         enum nsim_resource_id res_ids[] = {
204                 NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
205                 NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
206         };
207         int i;
208
209         for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
210                 int err;
211                 u64 val;
212
213                 err = devlink_resource_size_get(devlink, res_ids[i], &val);
214                 if (!err) {
215                         err = nsim_fib_set_max(nsim_dev->fib_data,
216                                                res_ids[i], val, extack);
217                         if (err)
218                                 return err;
219                 }
220         }
221
222         return 0;
223 }
224
225 #define NSIM_DEV_FLASH_SIZE 500000
226 #define NSIM_DEV_FLASH_CHUNK_SIZE 1000
227 #define NSIM_DEV_FLASH_CHUNK_TIME_MS 10
228
229 static int nsim_dev_flash_update(struct devlink *devlink, const char *file_name,
230                                  const char *component,
231                                  struct netlink_ext_ack *extack)
232 {
233         struct nsim_dev *nsim_dev = devlink_priv(devlink);
234         int i;
235
236         if (nsim_dev->fw_update_status) {
237                 devlink_flash_update_begin_notify(devlink);
238                 devlink_flash_update_status_notify(devlink,
239                                                    "Preparing to flash",
240                                                    component, 0, 0);
241         }
242
243         for (i = 0; i < NSIM_DEV_FLASH_SIZE / NSIM_DEV_FLASH_CHUNK_SIZE; i++) {
244                 if (nsim_dev->fw_update_status)
245                         devlink_flash_update_status_notify(devlink, "Flashing",
246                                                            component,
247                                                            i * NSIM_DEV_FLASH_CHUNK_SIZE,
248                                                            NSIM_DEV_FLASH_SIZE);
249                 msleep(NSIM_DEV_FLASH_CHUNK_TIME_MS);
250         }
251
252         if (nsim_dev->fw_update_status) {
253                 devlink_flash_update_status_notify(devlink, "Flashing",
254                                                    component,
255                                                    NSIM_DEV_FLASH_SIZE,
256                                                    NSIM_DEV_FLASH_SIZE);
257                 devlink_flash_update_status_notify(devlink, "Flashing done",
258                                                    component, 0, 0);
259                 devlink_flash_update_end_notify(devlink);
260         }
261
262         return 0;
263 }
264
265 static const struct devlink_ops nsim_dev_devlink_ops = {
266         .reload = nsim_dev_reload,
267         .flash_update = nsim_dev_flash_update,
268 };
269
270 static struct nsim_dev *
271 nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
272 {
273         struct nsim_dev *nsim_dev;
274         struct devlink *devlink;
275         int err;
276
277         devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev));
278         if (!devlink)
279                 return ERR_PTR(-ENOMEM);
280         nsim_dev = devlink_priv(devlink);
281         nsim_dev->nsim_bus_dev = nsim_bus_dev;
282         nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
283         get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
284         INIT_LIST_HEAD(&nsim_dev->port_list);
285         mutex_init(&nsim_dev->port_list_lock);
286         nsim_dev->fw_update_status = true;
287
288         nsim_dev->fib_data = nsim_fib_create();
289         if (IS_ERR(nsim_dev->fib_data)) {
290                 err = PTR_ERR(nsim_dev->fib_data);
291                 goto err_devlink_free;
292         }
293
294         err = nsim_dev_resources_register(devlink);
295         if (err)
296                 goto err_fib_destroy;
297
298         err = devlink_register(devlink, &nsim_bus_dev->dev);
299         if (err)
300                 goto err_resources_unregister;
301
302         err = nsim_dev_debugfs_init(nsim_dev);
303         if (err)
304                 goto err_dl_unregister;
305
306         err = nsim_bpf_dev_init(nsim_dev);
307         if (err)
308                 goto err_debugfs_exit;
309
310         return nsim_dev;
311
312 err_debugfs_exit:
313         nsim_dev_debugfs_exit(nsim_dev);
314 err_dl_unregister:
315         devlink_unregister(devlink);
316 err_resources_unregister:
317         devlink_resources_unregister(devlink, NULL);
318 err_fib_destroy:
319         nsim_fib_destroy(nsim_dev->fib_data);
320 err_devlink_free:
321         devlink_free(devlink);
322         return ERR_PTR(err);
323 }
324
325 static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
326 {
327         struct devlink *devlink = priv_to_devlink(nsim_dev);
328
329         nsim_bpf_dev_exit(nsim_dev);
330         nsim_dev_debugfs_exit(nsim_dev);
331         devlink_unregister(devlink);
332         devlink_resources_unregister(devlink, NULL);
333         nsim_fib_destroy(nsim_dev->fib_data);
334         mutex_destroy(&nsim_dev->port_list_lock);
335         devlink_free(devlink);
336 }
337
338 static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
339                                unsigned int port_index)
340 {
341         struct nsim_dev_port *nsim_dev_port;
342         struct devlink_port *devlink_port;
343         int err;
344
345         nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL);
346         if (!nsim_dev_port)
347                 return -ENOMEM;
348         nsim_dev_port->port_index = port_index;
349
350         devlink_port = &nsim_dev_port->devlink_port;
351         devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
352                                port_index + 1, 0, 0,
353                                nsim_dev->switch_id.id,
354                                nsim_dev->switch_id.id_len);
355         err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port,
356                                     port_index);
357         if (err)
358                 goto err_port_free;
359
360         err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
361         if (err)
362                 goto err_dl_port_unregister;
363
364         nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port);
365         if (IS_ERR(nsim_dev_port->ns)) {
366                 err = PTR_ERR(nsim_dev_port->ns);
367                 goto err_port_debugfs_exit;
368         }
369
370         devlink_port_type_eth_set(devlink_port, nsim_dev_port->ns->netdev);
371         list_add(&nsim_dev_port->list, &nsim_dev->port_list);
372
373         return 0;
374
375 err_port_debugfs_exit:
376         nsim_dev_port_debugfs_exit(nsim_dev_port);
377 err_dl_port_unregister:
378         devlink_port_unregister(devlink_port);
379 err_port_free:
380         kfree(nsim_dev_port);
381         return err;
382 }
383
384 static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
385 {
386         struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
387
388         list_del(&nsim_dev_port->list);
389         devlink_port_type_clear(devlink_port);
390         nsim_destroy(nsim_dev_port->ns);
391         nsim_dev_port_debugfs_exit(nsim_dev_port);
392         devlink_port_unregister(devlink_port);
393         kfree(nsim_dev_port);
394 }
395
396 static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
397 {
398         struct nsim_dev_port *nsim_dev_port, *tmp;
399
400         list_for_each_entry_safe(nsim_dev_port, tmp,
401                                  &nsim_dev->port_list, list)
402                 __nsim_dev_port_del(nsim_dev_port);
403 }
404
405 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
406 {
407         struct nsim_dev *nsim_dev;
408         int i;
409         int err;
410
411         nsim_dev = nsim_dev_create(nsim_bus_dev, nsim_bus_dev->port_count);
412         if (IS_ERR(nsim_dev))
413                 return PTR_ERR(nsim_dev);
414         dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
415
416         for (i = 0; i < nsim_bus_dev->port_count; i++) {
417                 err = __nsim_dev_port_add(nsim_dev, i);
418                 if (err)
419                         goto err_port_del_all;
420         }
421         return 0;
422
423 err_port_del_all:
424         nsim_dev_port_del_all(nsim_dev);
425         nsim_dev_destroy(nsim_dev);
426         return err;
427 }
428
429 void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
430 {
431         struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
432
433         nsim_dev_port_del_all(nsim_dev);
434         nsim_dev_destroy(nsim_dev);
435 }
436
437 static struct nsim_dev_port *
438 __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index)
439 {
440         struct nsim_dev_port *nsim_dev_port;
441
442         list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)
443                 if (nsim_dev_port->port_index == port_index)
444                         return nsim_dev_port;
445         return NULL;
446 }
447
448 int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
449                       unsigned int port_index)
450 {
451         struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
452         int err;
453
454         mutex_lock(&nsim_dev->port_list_lock);
455         if (__nsim_dev_port_lookup(nsim_dev, port_index))
456                 err = -EEXIST;
457         else
458                 err = __nsim_dev_port_add(nsim_dev, port_index);
459         mutex_unlock(&nsim_dev->port_list_lock);
460         return err;
461 }
462
463 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
464                       unsigned int port_index)
465 {
466         struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
467         struct nsim_dev_port *nsim_dev_port;
468         int err = 0;
469
470         mutex_lock(&nsim_dev->port_list_lock);
471         nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index);
472         if (!nsim_dev_port)
473                 err = -ENOENT;
474         else
475                 __nsim_dev_port_del(nsim_dev_port);
476         mutex_unlock(&nsim_dev->port_list_lock);
477         return err;
478 }
479
480 int nsim_dev_init(void)
481 {
482         nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
483         if (IS_ERR_OR_NULL(nsim_dev_ddir))
484                 return -ENOMEM;
485         return 0;
486 }
487
488 void nsim_dev_exit(void)
489 {
490         debugfs_remove_recursive(nsim_dev_ddir);
491 }