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
, char *buf
)
32 return sysfs_emit(buf
, "Usage: echo 1 > %s\n", attr
->attr
.name
);
35 static ssize_t
rtrs_srv_disconnect_store(struct kobject
*kobj
,
36 struct kobj_attribute
*attr
,
37 const char *buf
, size_t count
)
39 struct rtrs_srv_sess
*sess
;
41 char str
[MAXHOSTNAMELEN
];
43 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
45 if (!sysfs_streq(buf
, "1")) {
46 rtrs_err(s
, "%s: invalid value: '%s'\n",
47 attr
->attr
.name
, buf
);
51 sockaddr_to_str((struct sockaddr
*)&sess
->s
.dst_addr
, str
, sizeof(str
));
53 rtrs_info(s
, "disconnect for path %s requested\n", str
);
59 static struct kobj_attribute rtrs_srv_disconnect_attr
=
60 __ATTR(disconnect
, 0644,
61 rtrs_srv_disconnect_show
, rtrs_srv_disconnect_store
);
63 static ssize_t
rtrs_srv_hca_port_show(struct kobject
*kobj
,
64 struct kobj_attribute
*attr
,
67 struct rtrs_srv_sess
*sess
;
68 struct rtrs_con
*usr_con
;
70 sess
= container_of(kobj
, typeof(*sess
), kobj
);
71 usr_con
= sess
->s
.con
[0];
73 return sysfs_emit(page
, "%u\n", usr_con
->cm_id
->port_num
);
76 static struct kobj_attribute rtrs_srv_hca_port_attr
=
77 __ATTR(hca_port
, 0444, rtrs_srv_hca_port_show
, NULL
);
79 static ssize_t
rtrs_srv_hca_name_show(struct kobject
*kobj
,
80 struct kobj_attribute
*attr
,
83 struct rtrs_srv_sess
*sess
;
85 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
87 return sysfs_emit(page
, "%s\n", sess
->s
.dev
->ib_dev
->name
);
90 static struct kobj_attribute rtrs_srv_hca_name_attr
=
91 __ATTR(hca_name
, 0444, rtrs_srv_hca_name_show
, NULL
);
93 static ssize_t
rtrs_srv_src_addr_show(struct kobject
*kobj
,
94 struct kobj_attribute
*attr
,
97 struct rtrs_srv_sess
*sess
;
100 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
101 cnt
= sockaddr_to_str((struct sockaddr
*)&sess
->s
.dst_addr
,
103 return cnt
+ scnprintf(page
+ cnt
, PAGE_SIZE
- cnt
, "\n");
106 static struct kobj_attribute rtrs_srv_src_addr_attr
=
107 __ATTR(src_addr
, 0444, rtrs_srv_src_addr_show
, NULL
);
109 static ssize_t
rtrs_srv_dst_addr_show(struct kobject
*kobj
,
110 struct kobj_attribute
*attr
,
113 struct rtrs_srv_sess
*sess
;
116 sess
= container_of(kobj
, struct rtrs_srv_sess
, kobj
);
117 len
= sockaddr_to_str((struct sockaddr
*)&sess
->s
.src_addr
, page
,
119 len
+= sysfs_emit_at(page
, len
, "\n");
123 static struct kobj_attribute rtrs_srv_dst_addr_attr
=
124 __ATTR(dst_addr
, 0444, rtrs_srv_dst_addr_show
, NULL
);
126 static struct attribute
*rtrs_srv_sess_attrs
[] = {
127 &rtrs_srv_hca_name_attr
.attr
,
128 &rtrs_srv_hca_port_attr
.attr
,
129 &rtrs_srv_src_addr_attr
.attr
,
130 &rtrs_srv_dst_addr_attr
.attr
,
131 &rtrs_srv_disconnect_attr
.attr
,
135 static const struct attribute_group rtrs_srv_sess_attr_group
= {
136 .attrs
= rtrs_srv_sess_attrs
,
139 STAT_ATTR(struct rtrs_srv_stats
, rdma
,
140 rtrs_srv_stats_rdma_to_str
,
141 rtrs_srv_reset_rdma_stats
);
143 static struct attribute
*rtrs_srv_stats_attrs
[] = {
148 static const struct attribute_group rtrs_srv_stats_attr_group
= {
149 .attrs
= rtrs_srv_stats_attrs
,
152 static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess
*sess
)
154 struct rtrs_srv
*srv
= sess
->srv
;
157 mutex_lock(&srv
->paths_mutex
);
158 if (srv
->dev_ref
++) {
160 * Device needs to be registered only on the first session
164 srv
->dev
.class = rtrs_dev_class
;
165 err
= dev_set_name(&srv
->dev
, "%s", sess
->s
.sessname
);
170 * Suppress user space notification until
171 * sysfs files are created
173 dev_set_uevent_suppress(&srv
->dev
, true);
174 err
= device_add(&srv
->dev
);
176 pr_err("device_add(): %d\n", err
);
179 srv
->kobj_paths
= kobject_create_and_add("paths", &srv
->dev
.kobj
);
180 if (!srv
->kobj_paths
) {
182 pr_err("kobject_create_and_add(): %d\n", err
);
183 device_del(&srv
->dev
);
186 dev_set_uevent_suppress(&srv
->dev
, false);
187 kobject_uevent(&srv
->dev
.kobj
, KOBJ_ADD
);
191 put_device(&srv
->dev
);
193 mutex_unlock(&srv
->paths_mutex
);
199 rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess
*sess
)
201 struct rtrs_srv
*srv
= sess
->srv
;
203 mutex_lock(&srv
->paths_mutex
);
204 if (!--srv
->dev_ref
) {
205 kobject_del(srv
->kobj_paths
);
206 kobject_put(srv
->kobj_paths
);
207 mutex_unlock(&srv
->paths_mutex
);
208 device_del(&srv
->dev
);
210 mutex_unlock(&srv
->paths_mutex
);
214 static void rtrs_srv_sess_stats_release(struct kobject
*kobj
)
216 struct rtrs_srv_stats
*stats
;
218 stats
= container_of(kobj
, struct rtrs_srv_stats
, kobj_stats
);
223 static struct kobj_type ktype_stats
= {
224 .sysfs_ops
= &kobj_sysfs_ops
,
225 .release
= rtrs_srv_sess_stats_release
,
228 static int rtrs_srv_create_stats_files(struct rtrs_srv_sess
*sess
)
231 struct rtrs_sess
*s
= &sess
->s
;
233 err
= kobject_init_and_add(&sess
->stats
->kobj_stats
, &ktype_stats
,
234 &sess
->kobj
, "stats");
236 rtrs_err(s
, "kobject_init_and_add(): %d\n", err
);
239 err
= sysfs_create_group(&sess
->stats
->kobj_stats
,
240 &rtrs_srv_stats_attr_group
);
242 rtrs_err(s
, "sysfs_create_group(): %d\n", err
);
249 kobject_del(&sess
->stats
->kobj_stats
);
250 kobject_put(&sess
->stats
->kobj_stats
);
255 int rtrs_srv_create_sess_files(struct rtrs_srv_sess
*sess
)
257 struct rtrs_srv
*srv
= sess
->srv
;
258 struct rtrs_sess
*s
= &sess
->s
;
262 cnt
= sockaddr_to_str((struct sockaddr
*)&sess
->s
.dst_addr
,
264 cnt
+= scnprintf(str
+ cnt
, sizeof(str
) - cnt
, "@");
265 sockaddr_to_str((struct sockaddr
*)&sess
->s
.src_addr
,
266 str
+ cnt
, sizeof(str
) - cnt
);
268 err
= rtrs_srv_create_once_sysfs_root_folders(sess
);
272 err
= kobject_init_and_add(&sess
->kobj
, &ktype
, srv
->kobj_paths
,
275 rtrs_err(s
, "kobject_init_and_add(): %d\n", err
);
278 err
= sysfs_create_group(&sess
->kobj
, &rtrs_srv_sess_attr_group
);
280 rtrs_err(s
, "sysfs_create_group(): %d\n", err
);
283 err
= rtrs_srv_create_stats_files(sess
);
290 sysfs_remove_group(&sess
->kobj
, &rtrs_srv_sess_attr_group
);
292 kobject_del(&sess
->kobj
);
293 kobject_put(&sess
->kobj
);
295 rtrs_srv_destroy_once_sysfs_root_folders(sess
);
300 void rtrs_srv_destroy_sess_files(struct rtrs_srv_sess
*sess
)
302 if (sess
->kobj
.state_in_sysfs
) {
303 kobject_del(&sess
->stats
->kobj_stats
);
304 kobject_put(&sess
->stats
->kobj_stats
);
305 kobject_del(&sess
->kobj
);
306 kobject_put(&sess
->kobj
);
308 rtrs_srv_destroy_once_sysfs_root_folders(sess
);