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