1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.
6 * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.
7 * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.
10 #define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt
16 static void rtrs_srv_release(struct kobject
*kobj
)
18 struct rtrs_srv_sess
*sess
;
20 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
24 static struct kobj_type ktype
= {
25 .sysfs_ops
= &kobj_sysfs_ops
,
26 .release
= rtrs_srv_release
,
29 static ssize_t
rtrs_srv_disconnect_show(struct kobject
*kobj
,
30 struct kobj_attribute
*attr
,
33 return scnprintf(page
, PAGE_SIZE
, "Usage: echo 1 > %s\n",
37 static ssize_t
rtrs_srv_disconnect_store(struct kobject
*kobj
,
38 struct kobj_attribute
*attr
,
39 const char *buf
, size_t count
)
41 struct rtrs_srv_sess
*sess
;
43 char str
[MAXHOSTNAMELEN
];
45 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
47 if (!sysfs_streq(buf
, "1")) {
48 rtrs_err(s
, "%s: invalid value: '%s'\n",
49 attr
->attr
.name
, buf
);
53 sockaddr_to_str((struct sockaddr
*)&sess
->s
.dst_addr
, str
, sizeof(str
));
55 rtrs_info(s
, "disconnect for path %s requested\n", str
);
61 static struct kobj_attribute rtrs_srv_disconnect_attr
=
62 __ATTR(disconnect
, 0644,
63 rtrs_srv_disconnect_show
, rtrs_srv_disconnect_store
);
65 static ssize_t
rtrs_srv_hca_port_show(struct kobject
*kobj
,
66 struct kobj_attribute
*attr
,
69 struct rtrs_srv_sess
*sess
;
70 struct rtrs_con
*usr_con
;
72 sess
= container_of(kobj
, typeof(*sess
), kobj
);
73 usr_con
= sess
->s
.con
[0];
75 return scnprintf(page
, PAGE_SIZE
, "%u\n",
76 usr_con
->cm_id
->port_num
);
79 static struct kobj_attribute rtrs_srv_hca_port_attr
=
80 __ATTR(hca_port
, 0444, rtrs_srv_hca_port_show
, NULL
);
82 static ssize_t
rtrs_srv_hca_name_show(struct kobject
*kobj
,
83 struct kobj_attribute
*attr
,
86 struct rtrs_srv_sess
*sess
;
88 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
90 return scnprintf(page
, PAGE_SIZE
, "%s\n",
91 sess
->s
.dev
->ib_dev
->name
);
94 static struct kobj_attribute rtrs_srv_hca_name_attr
=
95 __ATTR(hca_name
, 0444, rtrs_srv_hca_name_show
, NULL
);
97 static ssize_t
rtrs_srv_src_addr_show(struct kobject
*kobj
,
98 struct kobj_attribute
*attr
,
101 struct rtrs_srv_sess
*sess
;
104 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
105 cnt
= sockaddr_to_str((struct sockaddr
*)&sess
->s
.dst_addr
,
107 return cnt
+ scnprintf(page
+ cnt
, PAGE_SIZE
- cnt
, "\n");
110 static struct kobj_attribute rtrs_srv_src_addr_attr
=
111 __ATTR(src_addr
, 0444, rtrs_srv_src_addr_show
, NULL
);
113 static ssize_t
rtrs_srv_dst_addr_show(struct kobject
*kobj
,
114 struct kobj_attribute
*attr
,
117 struct rtrs_srv_sess
*sess
;
120 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
121 cnt
= sockaddr_to_str((struct sockaddr
*)&sess
->s
.src_addr
,
123 return cnt
+ scnprintf(page
+ cnt
, PAGE_SIZE
- cnt
, "\n");
126 static struct kobj_attribute rtrs_srv_dst_addr_attr
=
127 __ATTR(dst_addr
, 0444, rtrs_srv_dst_addr_show
, NULL
);
129 static struct attribute
*rtrs_srv_sess_attrs
[] = {
130 &rtrs_srv_hca_name_attr
.attr
,
131 &rtrs_srv_hca_port_attr
.attr
,
132 &rtrs_srv_src_addr_attr
.attr
,
133 &rtrs_srv_dst_addr_attr
.attr
,
134 &rtrs_srv_disconnect_attr
.attr
,
138 static struct attribute_group rtrs_srv_sess_attr_group
= {
139 .attrs
= rtrs_srv_sess_attrs
,
142 STAT_ATTR(struct rtrs_srv_stats
, rdma
,
143 rtrs_srv_stats_rdma_to_str
,
144 rtrs_srv_reset_rdma_stats
);
146 static struct attribute
*rtrs_srv_stats_attrs
[] = {
151 static struct attribute_group rtrs_srv_stats_attr_group
= {
152 .attrs
= rtrs_srv_stats_attrs
,
155 static void rtrs_srv_dev_release(struct device
*dev
)
157 struct rtrs_srv
*srv
= container_of(dev
, struct rtrs_srv
, dev
);
162 static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess
*sess
)
164 struct rtrs_srv
*srv
= sess
->srv
;
167 mutex_lock(&srv
->paths_mutex
);
168 if (srv
->dev_ref
++) {
170 * Device needs to be registered only on the first session
174 srv
->dev
.class = rtrs_dev_class
;
175 srv
->dev
.release
= rtrs_srv_dev_release
;
176 err
= dev_set_name(&srv
->dev
, "%s", sess
->s
.sessname
);
181 * Suppress user space notification until
182 * sysfs files are created
184 dev_set_uevent_suppress(&srv
->dev
, true);
185 err
= device_register(&srv
->dev
);
187 pr_err("device_register(): %d\n", err
);
190 srv
->kobj_paths
= kobject_create_and_add("paths", &srv
->dev
.kobj
);
191 if (!srv
->kobj_paths
) {
193 pr_err("kobject_create_and_add(): %d\n", err
);
194 device_unregister(&srv
->dev
);
197 dev_set_uevent_suppress(&srv
->dev
, false);
198 kobject_uevent(&srv
->dev
.kobj
, KOBJ_ADD
);
202 put_device(&srv
->dev
);
204 mutex_unlock(&srv
->paths_mutex
);
210 rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess
*sess
)
212 struct rtrs_srv
*srv
= sess
->srv
;
214 mutex_lock(&srv
->paths_mutex
);
215 if (!--srv
->dev_ref
) {
216 kobject_del(srv
->kobj_paths
);
217 kobject_put(srv
->kobj_paths
);
218 mutex_unlock(&srv
->paths_mutex
);
219 device_unregister(&srv
->dev
);
221 mutex_unlock(&srv
->paths_mutex
);
225 static void rtrs_srv_sess_stats_release(struct kobject
*kobj
)
227 struct rtrs_srv_stats
*stats
;
229 stats
= container_of(kobj
, struct rtrs_srv_stats
, kobj_stats
);
234 static struct kobj_type ktype_stats
= {
235 .sysfs_ops
= &kobj_sysfs_ops
,
236 .release
= rtrs_srv_sess_stats_release
,
239 static int rtrs_srv_create_stats_files(struct rtrs_srv_sess
*sess
)
242 struct rtrs_sess
*s
= &sess
->s
;
244 err
= kobject_init_and_add(&sess
->stats
->kobj_stats
, &ktype_stats
,
245 &sess
->kobj
, "stats");
247 rtrs_err(s
, "kobject_init_and_add(): %d\n", err
);
250 err
= sysfs_create_group(&sess
->stats
->kobj_stats
,
251 &rtrs_srv_stats_attr_group
);
253 rtrs_err(s
, "sysfs_create_group(): %d\n", err
);
260 kobject_del(&sess
->stats
->kobj_stats
);
261 kobject_put(&sess
->stats
->kobj_stats
);
266 int rtrs_srv_create_sess_files(struct rtrs_srv_sess
*sess
)
268 struct rtrs_srv
*srv
= sess
->srv
;
269 struct rtrs_sess
*s
= &sess
->s
;
273 cnt
= sockaddr_to_str((struct sockaddr
*)&sess
->s
.dst_addr
,
275 cnt
+= scnprintf(str
+ cnt
, sizeof(str
) - cnt
, "@");
276 sockaddr_to_str((struct sockaddr
*)&sess
->s
.src_addr
,
277 str
+ cnt
, sizeof(str
) - cnt
);
279 err
= rtrs_srv_create_once_sysfs_root_folders(sess
);
283 err
= kobject_init_and_add(&sess
->kobj
, &ktype
, srv
->kobj_paths
,
286 rtrs_err(s
, "kobject_init_and_add(): %d\n", err
);
289 err
= sysfs_create_group(&sess
->kobj
, &rtrs_srv_sess_attr_group
);
291 rtrs_err(s
, "sysfs_create_group(): %d\n", err
);
294 err
= rtrs_srv_create_stats_files(sess
);
301 sysfs_remove_group(&sess
->kobj
, &rtrs_srv_sess_attr_group
);
303 kobject_del(&sess
->kobj
);
304 kobject_put(&sess
->kobj
);
306 rtrs_srv_destroy_once_sysfs_root_folders(sess
);
311 void rtrs_srv_destroy_sess_files(struct rtrs_srv_sess
*sess
)
313 if (sess
->kobj
.state_in_sysfs
) {
314 kobject_del(&sess
->stats
->kobj_stats
);
315 kobject_put(&sess
->stats
->kobj_stats
);
316 kobject_del(&sess
->kobj
);
317 kobject_put(&sess
->kobj
);
319 rtrs_srv_destroy_once_sysfs_root_folders(sess
);