Linux Audio

Check our new training course

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