Linux Audio

Check our new training course

Loading...
v5.9
  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_l2_vnicc_is_in_use(card))
 22		return sprintf(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 = sprintf(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_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
 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_l2_vnicc_is_in_use(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_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
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_l2_vnicc_is_in_use(card))
135		return sprintf(buf, "n/a (VNIC characteristics)\n");
136
137	enabled = card->options.sbp.hostnotification;
138
139	return sprintf(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_l2_vnicc_is_in_use(card))
157		rc = -EBUSY;
158	else if (qeth_card_hw_is_reachable(card)) {
159		rc = qeth_bridgeport_an_set(card, enable);
 
160		if (!rc)
161			card->options.sbp.hostnotification = enable;
162	} else
163		card->options.sbp.hostnotification = enable;
164
165	mutex_unlock(&card->sbp_lock);
166	mutex_unlock(&card->conf_mutex);
167
168	return rc ? rc : count;
169}
170
171static DEVICE_ATTR(bridge_hostnotify, 0644,
172			qeth_bridgeport_hostnotification_show,
173			qeth_bridgeport_hostnotification_store);
174
175static ssize_t qeth_bridgeport_reflect_show(struct device *dev,
176				struct device_attribute *attr, char *buf)
177{
178	struct qeth_card *card = dev_get_drvdata(dev);
179	char *state;
180
181	if (qeth_l2_vnicc_is_in_use(card))
182		return sprintf(buf, "n/a (VNIC characteristics)\n");
183
184	if (card->options.sbp.reflect_promisc) {
185		if (card->options.sbp.reflect_promisc_primary)
186			state = "primary";
187		else
188			state = "secondary";
189	} else
190		state = "none";
191
192	return sprintf(buf, "%s\n", state);
193}
194
195static ssize_t qeth_bridgeport_reflect_store(struct device *dev,
196		struct device_attribute *attr, const char *buf, size_t count)
197{
198	struct qeth_card *card = dev_get_drvdata(dev);
199	int enable, primary;
200	int rc = 0;
201
202	if (sysfs_streq(buf, "none")) {
203		enable = 0;
204		primary = 0;
205	} else if (sysfs_streq(buf, "primary")) {
206		enable = 1;
207		primary = 1;
208	} else if (sysfs_streq(buf, "secondary")) {
209		enable = 1;
210		primary = 0;
211	} else
212		return -EINVAL;
213
214	mutex_lock(&card->conf_mutex);
215	mutex_lock(&card->sbp_lock);
216
217	if (qeth_l2_vnicc_is_in_use(card))
218		rc = -EBUSY;
219	else if (card->options.sbp.role != QETH_SBP_ROLE_NONE)
220		rc = -EPERM;
221	else {
222		card->options.sbp.reflect_promisc = enable;
223		card->options.sbp.reflect_promisc_primary = primary;
224		rc = 0;
225	}
226
227	mutex_unlock(&card->sbp_lock);
228	mutex_unlock(&card->conf_mutex);
229
230	return rc ? rc : count;
231}
232
233static DEVICE_ATTR(bridge_reflect_promisc, 0644,
234			qeth_bridgeport_reflect_show,
235			qeth_bridgeport_reflect_store);
236
237static struct attribute *qeth_l2_bridgeport_attrs[] = {
238	&dev_attr_bridge_role.attr,
239	&dev_attr_bridge_state.attr,
240	&dev_attr_bridge_hostnotify.attr,
241	&dev_attr_bridge_reflect_promisc.attr,
242	NULL,
243};
244
245static struct attribute_group qeth_l2_bridgeport_attr_group = {
246	.attrs = qeth_l2_bridgeport_attrs,
247};
248
249/* VNIC CHARS support */
250
251/* convert sysfs attr name to VNIC characteristic */
252static u32 qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name)
253{
254	if (sysfs_streq(attr_name, "flooding"))
255		return QETH_VNICC_FLOODING;
256	else if (sysfs_streq(attr_name, "mcast_flooding"))
257		return QETH_VNICC_MCAST_FLOODING;
258	else if (sysfs_streq(attr_name, "learning"))
259		return QETH_VNICC_LEARNING;
260	else if (sysfs_streq(attr_name, "takeover_setvmac"))
261		return QETH_VNICC_TAKEOVER_SETVMAC;
262	else if (sysfs_streq(attr_name, "takeover_learning"))
263		return QETH_VNICC_TAKEOVER_LEARNING;
264	else if (sysfs_streq(attr_name, "bridge_invisible"))
265		return QETH_VNICC_BRIDGE_INVISIBLE;
266	else if (sysfs_streq(attr_name, "rx_bcast"))
267		return QETH_VNICC_RX_BCAST;
268
269	return 0;
270}
271
272/* get current timeout setting */
273static ssize_t qeth_vnicc_timeout_show(struct device *dev,
274				       struct device_attribute *attr, char *buf)
275{
276	struct qeth_card *card = dev_get_drvdata(dev);
277	u32 timeout;
278	int rc;
279
280	rc = qeth_l2_vnicc_get_timeout(card, &timeout);
281	if (rc == -EBUSY)
282		return sprintf(buf, "n/a (BridgePort)\n");
283	if (rc == -EOPNOTSUPP)
284		return sprintf(buf, "n/a\n");
285	return rc ? rc : sprintf(buf, "%d\n", timeout);
286}
287
288/* change timeout setting */
289static ssize_t qeth_vnicc_timeout_store(struct device *dev,
290					struct device_attribute *attr,
291					const char *buf, size_t count)
292{
293	struct qeth_card *card = dev_get_drvdata(dev);
294	u32 timeout;
295	int rc;
296
297	rc = kstrtou32(buf, 10, &timeout);
298	if (rc)
299		return rc;
300
301	mutex_lock(&card->conf_mutex);
302	rc = qeth_l2_vnicc_set_timeout(card, timeout);
303	mutex_unlock(&card->conf_mutex);
304	return rc ? rc : count;
305}
306
307/* get current setting of characteristic */
308static ssize_t qeth_vnicc_char_show(struct device *dev,
309				    struct device_attribute *attr, char *buf)
310{
311	struct qeth_card *card = dev_get_drvdata(dev);
312	bool state;
313	u32 vnicc;
314	int rc;
315
316	vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);
317	rc = qeth_l2_vnicc_get_state(card, vnicc, &state);
318
319	if (rc == -EBUSY)
320		return sprintf(buf, "n/a (BridgePort)\n");
321	if (rc == -EOPNOTSUPP)
322		return sprintf(buf, "n/a\n");
323	return rc ? rc : sprintf(buf, "%d\n", state);
324}
325
326/* change setting of characteristic */
327static ssize_t qeth_vnicc_char_store(struct device *dev,
328				     struct device_attribute *attr,
329				     const char *buf, size_t count)
330{
331	struct qeth_card *card = dev_get_drvdata(dev);
332	bool state;
333	u32 vnicc;
334	int rc;
335
336	if (kstrtobool(buf, &state))
337		return -EINVAL;
338
339	vnicc = qeth_l2_vnicc_sysfs_attr_to_char(attr->attr.name);
340	mutex_lock(&card->conf_mutex);
341	rc = qeth_l2_vnicc_set_state(card, vnicc, state);
342	mutex_unlock(&card->conf_mutex);
343
344	return rc ? rc : count;
345}
346
347static DEVICE_ATTR(flooding, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
348static DEVICE_ATTR(mcast_flooding, 0644, qeth_vnicc_char_show,
349		   qeth_vnicc_char_store);
350static DEVICE_ATTR(learning, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
351static DEVICE_ATTR(learning_timeout, 0644, qeth_vnicc_timeout_show,
352		   qeth_vnicc_timeout_store);
353static DEVICE_ATTR(takeover_setvmac, 0644, qeth_vnicc_char_show,
354		   qeth_vnicc_char_store);
355static DEVICE_ATTR(takeover_learning, 0644, qeth_vnicc_char_show,
356		   qeth_vnicc_char_store);
357static DEVICE_ATTR(bridge_invisible, 0644, qeth_vnicc_char_show,
358		   qeth_vnicc_char_store);
359static DEVICE_ATTR(rx_bcast, 0644, qeth_vnicc_char_show, qeth_vnicc_char_store);
360
361static struct attribute *qeth_l2_vnicc_attrs[] = {
362	&dev_attr_flooding.attr,
363	&dev_attr_mcast_flooding.attr,
364	&dev_attr_learning.attr,
365	&dev_attr_learning_timeout.attr,
366	&dev_attr_takeover_setvmac.attr,
367	&dev_attr_takeover_learning.attr,
368	&dev_attr_bridge_invisible.attr,
369	&dev_attr_rx_bcast.attr,
370	NULL,
371};
372
373static struct attribute_group qeth_l2_vnicc_attr_group = {
374	.attrs = qeth_l2_vnicc_attrs,
375	.name = "vnicc",
376};
377
378static const struct attribute_group *qeth_l2_only_attr_groups[] = {
379	&qeth_l2_bridgeport_attr_group,
380	&qeth_l2_vnicc_attr_group,
381	NULL,
382};
383
384int qeth_l2_create_device_attributes(struct device *dev)
385{
386	return sysfs_create_groups(&dev->kobj, qeth_l2_only_attr_groups);
387}
388
389void qeth_l2_remove_device_attributes(struct device *dev)
390{
391	sysfs_remove_groups(&dev->kobj, qeth_l2_only_attr_groups);
392}
393
394const struct attribute_group *qeth_l2_attr_groups[] = {
395	&qeth_device_attr_group,
396	&qeth_device_blkt_group,
397	/* l2 specific, see qeth_l2_only_attr_groups: */
398	&qeth_l2_bridgeport_attr_group,
399	&qeth_l2_vnicc_attr_group,
400	NULL,
401};
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};