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