1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2/*
3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
5 */
6
7#include "rxe.h"
8#include "rxe_net.h"
9
10/* Copy argument and remove trailing CR. Return the new length. */
11static int sanitize_arg(const char *val, char *intf, int intf_len)
12{
13	int len;
14
15	if (!val)
16		return 0;
17
18	/* Remove newline. */
19	for (len = 0; len < intf_len - 1 && val[len] && val[len] != '\n'; len++)
20		intf[len] = val[len];
21	intf[len] = 0;
22
23	if (len == 0 || (val[len] != 0 && val[len] != '\n'))
24		return 0;
25
26	return len;
27}
28
29static int rxe_param_set_add(const char *val, const struct kernel_param *kp)
30{
31	int len;
32	int err = 0;
33	char intf[32];
34	struct net_device *ndev;
35	struct rxe_dev *exists;
36
37	if (!rxe_initialized) {
38		pr_err("Module parameters are not supported, use rdma link add or rxe_cfg\n");
39		return -EAGAIN;
40	}
41
42	len = sanitize_arg(val, intf, sizeof(intf));
43	if (!len) {
44		pr_err("add: invalid interface name\n");
45		return -EINVAL;
46	}
47
48	ndev = dev_get_by_name(&init_net, intf);
49	if (!ndev) {
50		pr_err("interface %s not found\n", intf);
51		return -EINVAL;
52	}
53
54	if (is_vlan_dev(ndev)) {
55		pr_err("rxe creation allowed on top of a real device only\n");
56		err = -EPERM;
57		goto err;
58	}
59
60	exists = rxe_get_dev_from_net(ndev);
61	if (exists) {
62		ib_device_put(&exists->ib_dev);
63		pr_err("already configured on %s\n", intf);
64		err = -EINVAL;
65		goto err;
66	}
67
68	err = rxe_net_add("rxe%d", ndev);
69	if (err) {
70		pr_err("failed to add %s\n", intf);
71		goto err;
72	}
73
74err:
75	dev_put(ndev);
76	return err;
77}
78
79static int rxe_param_set_remove(const char *val, const struct kernel_param *kp)
80{
81	int len;
82	char intf[32];
83	struct ib_device *ib_dev;
84
85	len = sanitize_arg(val, intf, sizeof(intf));
86	if (!len) {
87		pr_err("add: invalid interface name\n");
88		return -EINVAL;
89	}
90
91	if (strncmp("all", intf, len) == 0) {
92		pr_info("rxe_sys: remove all");
93		ib_unregister_driver(RDMA_DRIVER_RXE);
94		return 0;
95	}
96
97	ib_dev = ib_device_get_by_name(intf, RDMA_DRIVER_RXE);
98	if (!ib_dev) {
99		pr_err("not configured on %s\n", intf);
100		return -EINVAL;
101	}
102
103	ib_unregister_device_and_put(ib_dev);
104
105	return 0;
106}
107
108static const struct kernel_param_ops rxe_add_ops = {
109	.set = rxe_param_set_add,
110};
111
112static const struct kernel_param_ops rxe_remove_ops = {
113	.set = rxe_param_set_remove,
114};
115
116module_param_cb(add, &rxe_add_ops, NULL, 0200);
117MODULE_PARM_DESC(add, "DEPRECATED.  Create RXE device over network interface");
118module_param_cb(remove, &rxe_remove_ops, NULL, 0200);
119MODULE_PARM_DESC(remove, "DEPRECATED.  Remove RXE device over network interface");
120