1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright IBM Corp. 2013
4 * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
5 */
6
7 #include <linux/slab.h>
8 #include <asm/ebcdic.h>
9 #include "qeth_core.h"
10 #include "qeth_l2.h"
11
qeth_bridge_port_role_state_show(struct device * dev,struct device_attribute * attr,char * buf,int show_state)12 static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
13 struct device_attribute *attr, char *buf,
14 int show_state)
15 {
16 struct qeth_card *card = dev_get_drvdata(dev);
17 enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
18 int rc = 0;
19 char *word;
20
21 if (!card)
22 return -EINVAL;
23
24 if (qeth_l2_vnicc_is_in_use(card))
25 return sprintf(buf, "n/a (VNIC characteristics)\n");
26
27 mutex_lock(&card->sbp_lock);
28 if (qeth_card_hw_is_reachable(card) &&
29 card->options.sbp.supported_funcs)
30 rc = qeth_bridgeport_query_ports(card,
31 &card->options.sbp.role, &state);
32 if (!rc) {
33 if (show_state)
34 switch (state) {
35 case QETH_SBP_STATE_INACTIVE:
36 word = "inactive"; break;
37 case QETH_SBP_STATE_STANDBY:
38 word = "standby"; break;
39 case QETH_SBP_STATE_ACTIVE:
40 word = "active"; break;
41 default:
42 rc = -EIO;
43 }
44 else
45 switch (card->options.sbp.role) {
46 case QETH_SBP_ROLE_NONE:
47 word = "none"; break;
48 case QETH_SBP_ROLE_PRIMARY:
49 word = "primary"; break;
50 case QETH_SBP_ROLE_SECONDARY:
51 word = "secondary"; break;
52 default:
53 rc = -EIO;
54 }
55 if (rc)
56 QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
57 card->options.sbp.role, state);
58 else
59 rc = sprintf(buf, "%s\n", word);
60 }
61 mutex_unlock(&card->sbp_lock);
62
63 return rc;
64 }
65
qeth_bridge_port_role_show(struct device * dev,struct device_attribute * attr,char * buf)66 static ssize_t qeth_bridge_port_role_show(struct device *dev,
67 struct device_attribute *attr, char *buf)
68 {
69 struct qeth_card *card = dev_get_drvdata(dev);
70
71 if (qeth_l2_vnicc_is_in_use(card))
72 return sprintf(buf, "n/a (VNIC characteristics)\n");
73
74 return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
75 }
76
qeth_bridge_port_role_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)77 static ssize_t qeth_bridge_port_role_store(struct device *dev,
78 struct device_attribute *attr, const char *buf, size_t count)
79 {
80 struct qeth_card *card = dev_get_drvdata(dev);
81 int rc = 0;
82 enum qeth_sbp_roles role;
83
84 if (!card)
85 return -EINVAL;
86 if (sysfs_streq(buf, "primary"))
87 role = QETH_SBP_ROLE_PRIMARY;
88 else if (sysfs_streq(buf, "secondary"))
89 role = QETH_SBP_ROLE_SECONDARY;
90 else if (sysfs_streq(buf, "none"))
91 role = QETH_SBP_ROLE_NONE;
92 else
93 return -EINVAL;
94
95 mutex_lock(&card->conf_mutex);
96 mutex_lock(&card->sbp_lock);
97
98 if (qeth_l2_vnicc_is_in_use(card))
99 rc = -EBUSY;
100 else if (card->options.sbp.reflect_promisc)
101 /* Forbid direct manipulation */
102 rc = -EPERM;
103 else if (qeth_card_hw_is_reachable(card)) {
104 rc = qeth_bridgeport_setrole(card, role);
105 if (!rc)
106 card->options.sbp.role = role;
107 } else
108 card->options.sbp.role = role;
109
110 mutex_unlock(&card->sbp_lock);
111 mutex_unlock(&card->conf_mutex);
112
113 return rc ? rc : count;
114 }
115
116 static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
117 qeth_bridge_port_role_store);
118
qeth_bridge_port_state_show(struct device * dev,struct device_attribute * attr,char * buf)119 static ssize_t qeth_bridge_port_state_show(struct device *dev,
120 struct device_attribute *attr, char *buf)
121 {
122 struct qeth_card *card = dev_get_drvdata(dev);
123
124 if (qeth_l2_vnicc_is_in_use(card))
125 return sprintf(buf, "n/a (VNIC characteristics)\n");
126
127 return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
128 }
129
130 static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
131 NULL);
132
qeth_bridgeport_hostnotification_show(struct device * dev,struct device_attribute * attr,char * buf)133 static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
134 struct device_attribute *attr, char *buf)
135 {
136 struct qeth_card *card = dev_get_drvdata(dev);
137 int enabled;
138
139 if (!card)
140 return -EINVAL;
141
142 if (qeth_l2_vnicc_is_in_use(card))
143 return sprintf(buf, "n/a (VNIC characteristics)\n");
144
145 enabled = card->options.sbp.hostnotification;
146
147 return sprintf(buf, "%d\n", enabled);
148 }
149
qeth_bridgeport_hostnotification_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)150 static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
151 struct device_attribute *attr, const char *buf, size_t count)
152 {
153 struct qeth_card *card = dev_get_drvdata(dev);
154 bool enable;
155 int rc;
156
157 if (!card)
158 return -EINVAL;
159
160 rc = kstrtobool(buf, &enable);
161 if (rc)
162 return rc;
163
164 mutex_lock(&card->conf_mutex);
165 mutex_lock(&card->sbp_lock);
166
167 if (qeth_l2_vnicc_is_in_use(card))
168 rc = -EBUSY;
169 else if (qeth_card_hw_is_reachable(card)) {
170 rc = qeth_bridgeport_an_set(card, enable);
171 if (!rc)
172 card->options.sbp.hostnotification = enable;
173 } else
174 card->options.sbp.hostnotification = enable;
175
176 mutex_unlock(&card->sbp_lock);
177 mutex_unlock(&card->conf_mutex);
178
179 return rc ? rc : count;
180 }
181
182 static DEVICE_ATTR(bridge_hostnotify, 0644,
183 qeth_bridgeport_hostnotification_show,
184 qeth_bridgeport_hostnotification_store);
185
qeth_bridgeport_reflect_show(struct device * dev,struct device_attribute * attr,char * buf)186 static ssize_t qeth_bridgeport_reflect_show(struct device *dev,
187 struct device_attribute *attr, char *buf)
188 {
189 struct qeth_card *card = dev_get_drvdata(dev);
190 char *state;
191
192 if (!card)
193 return -EINVAL;
194
195 if (qeth_l2_vnicc_is_in_use(card))
196 return sprintf(buf, "n/a (VNIC characteristics)\n");
197
198 if (card->options.sbp.reflect_promisc) {
199 if (card->options.sbp.reflect_promisc_primary)
200 state = "primary";
201 else
202 state = "secondary";
203 } else
204 state = "none";
205
206 return sprintf(buf, "%s\n", state);
207 }
208
qeth_bridgeport_reflect_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)209 static ssize_t qeth_bridgeport_reflect_store(struct device *dev,
210 struct device_attribute *attr, const char *buf, size_t count)
211 {
212 struct qeth_card *card = dev_get_drvdata(dev);
213 int enable, primary;
214 int rc = 0;
215
216 if (!card)
217 return -EINVAL;
218
219 if (sysfs_streq(buf, "none")) {
220 enable = 0;
221 primary = 0;
222 } else if (sysfs_streq(buf, "primary")) {
223 enable = 1;
224 primary = 1;
225 } else if (sysfs_streq(buf, "secondary")) {
226 enable = 1;
227 primary = 0;
228 } else
229 return -EINVAL;
230
231 mutex_lock(&card->conf_mutex);
232 mutex_lock(&card->sbp_lock);
233
234 if (qeth_l2_vnicc_is_in_use(card))
235 rc = -EBUSY;
236 else if (card->options.sbp.role != QETH_SBP_ROLE_NONE)
237 rc = -EPERM;
238 else {
239 card->options.sbp.reflect_promisc = enable;
240 card->options.sbp.reflect_promisc_primary = primary;
241 rc = 0;
242 }
243
244 mutex_unlock(&card->sbp_lock);
245 mutex_unlock(&card->conf_mutex);
246
247 return rc ? rc : count;
248 }
249
250 static DEVICE_ATTR(bridge_reflect_promisc, 0644,
251 qeth_bridgeport_reflect_show,
252 qeth_bridgeport_reflect_store);
253
254 static struct attribute *qeth_l2_bridgeport_attrs[] = {
255 &dev_attr_bridge_role.attr,
256 &dev_attr_bridge_state.attr,
257 &dev_attr_bridge_hostnotify.attr,
258 &dev_attr_bridge_reflect_promisc.attr,
259 NULL,
260 };
261
262 static struct attribute_group qeth_l2_bridgeport_attr_group = {
263 .attrs = qeth_l2_bridgeport_attrs,
264 };
265
266 /**
267 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
268 * @card: qeth_card structure pointer
269 *
270 * Note: this function is called with conf_mutex held by the caller
271 */
qeth_l2_setup_bridgeport_attrs(struct qeth_card * card)272 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
273 {
274 int rc;
275
276 if (!card)
277 return;
278 if (!card->options.sbp.supported_funcs)
279 return;
280
281 mutex_lock(&card->sbp_lock);
282 if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
283 /* Conditional to avoid spurious error messages */
284 qeth_bridgeport_setrole(card, card->options.sbp.role);
285 /* Let the callback function refresh the stored role value. */
286 qeth_bridgeport_query_ports(card,
287 &card->options.sbp.role, NULL);
288 }
289 if (card->options.sbp.hostnotification) {
290 rc = qeth_bridgeport_an_set(card, 1);
291 if (rc)
292 card->options.sbp.hostnotification = 0;
293 } else {
294 qeth_bridgeport_an_set(card, 0);
295 }
296 mutex_unlock(&card->sbp_lock);
297 }
298
299 /* VNIC CHARS support */
300
301 /* convert sysfs attr name to VNIC characteristic */
qeth_l2_vnicc_sysfs_attr_to_char(const char * attr_name)302 static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name)
303 {
304 if (sysfs_streq(attr_name, "flooding"))
305 return QETH_VNICC_FLOODING;
306 else if (sysfs_streq(attr_name, "mcast_flooding"))
307 return QETH_VNICC_MCAST_FLOODING;
308 else if (sysfs_streq(attr_name, "learning"))
309 return QETH_VNICC_LEARNING;
310 else if (sysfs_streq(attr_name, "takeover_setvmac"))
311 return QETH_VNICC_TAKEOVER_SETVMAC;
312 else if (sysfs_streq(attr_name, "takeover_learning"))
313 return QETH_VNICC_TAKEOVER_LEARNING;
314 else if (sysfs_streq(attr_name, "bridge_invisible"))
315 return QETH_VNICC_BRIDGE_INVISIBLE;
316 else if (sysfs_streq(attr_name, "rx_bcast"))
317 return QETH_VNICC_RX_BCAST;
318
319 return 0;
320 }
321
322 /* get current timeout setting */
qeth_vnicc_timeout_show(struct device * dev,struct device_attribute * attr,char * buf)323 static ssize_t qeth_vnicc_timeout_show(struct device *dev,
324 struct device_attribute *attr, char *buf)
325 {
326 struct qeth_card *card = dev_get_drvdata(dev);
327 u32 timeout;
328 int rc;
329
330 if (!card)
331 return -EINVAL;
332
333 rc = qeth_l2_vnicc_get_timeout(card, &timeout);
334 if (rc == -EBUSY)
335 return sprintf(buf, "n/a (BridgePort)\n");
336 if (rc == -EOPNOTSUPP)
337 return sprintf(buf, "n/a\n");
338 return rc ? rc : sprintf(buf, "%d\n", timeout);
339 }
340
341 /* change timeout setting */
qeth_vnicc_timeout_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)342 static ssize_t qeth_vnicc_timeout_store(struct device *dev,
343 struct device_attribute *attr,
344 const char *buf, size_t count)
345 {
346 struct qeth_card *card = dev_get_drvdata(dev);
347 u32 timeout;
348 int rc;
349
350 if (!card)
351 return -EINVAL;
352
353 rc = kstrtou32(buf, 10, &timeout);
354 if (rc)
355 return rc;
356
357 mutex_lock(&card->conf_mutex);
358 rc = qeth_l2_vnicc_set_timeout(card, timeout);
359 mutex_unlock(&card->conf_mutex);
360 return rc ? rc : count;
361 }
362
363 /* get current setting of characteristic */
qeth_vnicc_char_show(struct device * dev,struct device_attribute * attr,char * buf)364 static ssize_t qeth_vnicc_char_show(struct device *dev,
365 struct device_attribute *attr, char *buf)
366 {
367 struct qeth_card *card = dev_get_drvdata(dev);
368 bool state;
369 u32 vnicc;
370 int rc;
371
372 if (!card)
373 return -EINVAL;
374
375 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);
376 rc = qeth_l2_vnicc_get_state(card, vnicc, &state);
377
378 if (rc == -EBUSY)
379 return sprintf(buf, "n/a (BridgePort)\n");
380 if (rc == -EOPNOTSUPP)
381 return sprintf(buf, "n/a\n");
382 return rc ? rc : sprintf(buf, "%d\n", state);
383 }
384
385 /* change setting of characteristic */
qeth_vnicc_char_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)386 static ssize_t qeth_vnicc_char_store(struct device *dev,
387 struct device_attribute *attr,
388 const char *buf, size_t count)
389 {
390 struct qeth_card *card = dev_get_drvdata(dev);
391 bool state;
392 u32 vnicc;
393 int rc;
394
395 if (!card)
396 return -EINVAL;
397
398 if (kstrtobool(buf, &state))
399 return -EINVAL;
400
401 vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);
402 mutex_lock(&card->conf_mutex);
403 rc = qeth_l2_vnicc_set_state(card, vnicc, state);
404 mutex_unlock(&card->conf_mutex);
405
406 return rc ? rc : count;
407 }
408
409 static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
410 static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show,
411 qeth_vnicc_char_store);
412 static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
413 static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show,
414 qeth_vnicc_timeout_store);
415 static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show,
416 qeth_vnicc_char_store);
417 static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show,
418 qeth_vnicc_char_store);
419 static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show,
420 qeth_vnicc_char_store);
421 static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
422
423 static struct attribute *qeth_l2_vnicc_attrs[] = {
424 &dev_attr_flooding.attr,
425 &dev_attr_mcast_flooding.attr,
426 &dev_attr_learning.attr,
427 &dev_attr_learning_timeout.attr,
428 &dev_attr_takeover_setvmac.attr,
429 &dev_attr_takeover_learning.attr,
430 &dev_attr_bridge_invisible.attr,
431 &dev_attr_rx_bcast.attr,
432 NULL,
433 };
434
435 static struct attribute_group qeth_l2_vnicc_attr_group = {
436 .attrs = qeth_l2_vnicc_attrs,
437 .name = "vnicc",
438 };
439
440 static const struct attribute_group *qeth_l2_only_attr_groups[] = {
441 &qeth_l2_bridgeport_attr_group,
442 &qeth_l2_vnicc_attr_group,
443 NULL,
444 };
445
qeth_l2_create_device_attributes(struct device * dev)446 int qeth_l2_create_device_attributes(struct device *dev)
447 {
448 return sysfs_create_groups(&dev->kobj, qeth_l2_only_attr_groups);
449 }
450
qeth_l2_remove_device_attributes(struct device * dev)451 void qeth_l2_remove_device_attributes(struct device *dev)
452 {
453 sysfs_remove_groups(&dev->kobj, qeth_l2_only_attr_groups);
454 }
455
456 const struct attribute_group *qeth_l2_attr_groups[] = {
457 &qeth_device_attr_group,
458 &qeth_device_blkt_group,
459 /* l2 specific, see qeth_l2_only_attr_groups: */
460 &qeth_l2_bridgeport_attr_group,
461 &qeth_l2_vnicc_attr_group,
462 NULL,
463 };
464