Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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_l2.h"
  9
 10#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
 11struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
 12
 13static int qeth_card_hw_is_reachable(struct qeth_card *card)
 14{
 15	return (card->state == CARD_STATE_SOFTSETUP) ||
 16		(card->state == CARD_STATE_UP);
 17}
 18
 19static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
 20				struct device_attribute *attr, char *buf,
 21				int show_state)
 22{
 23	struct qeth_card *card = dev_get_drvdata(dev);
 24	enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
 25	int rc = 0;
 26	char *word;
 27
 28	if (!card)
 29		return -EINVAL;
 30
 31	mutex_lock(&card->conf_mutex);
 32
 33	if (qeth_card_hw_is_reachable(card) &&
 34					card->options.sbp.supported_funcs)
 35		rc = qeth_bridgeport_query_ports(card,
 36			&card->options.sbp.role, &state);
 37	if (!rc) {
 38		if (show_state)
 39			switch (state) {
 40			case QETH_SBP_STATE_INACTIVE:
 41				word = "inactive"; break;
 42			case QETH_SBP_STATE_STANDBY:
 43				word = "standby"; break;
 44			case QETH_SBP_STATE_ACTIVE:
 45				word = "active"; break;
 46			default:
 47				rc = -EIO;
 48			}
 49		else
 50			switch (card->options.sbp.role) {
 51			case QETH_SBP_ROLE_NONE:
 52				word = "none"; break;
 53			case QETH_SBP_ROLE_PRIMARY:
 54				word = "primary"; break;
 55			case QETH_SBP_ROLE_SECONDARY:
 56				word = "secondary"; break;
 57			default:
 58				rc = -EIO;
 59			}
 60		if (rc)
 61			QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
 62				card->options.sbp.role, state);
 63		else
 64			rc = sprintf(buf, "%s\n", word);
 65	}
 66
 67	mutex_unlock(&card->conf_mutex);
 68
 69	return rc;
 70}
 71
 72static ssize_t qeth_bridge_port_role_show(struct device *dev,
 73				struct device_attribute *attr, char *buf)
 74{
 75	return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
 76}
 77
 78static ssize_t qeth_bridge_port_role_store(struct device *dev,
 79		struct device_attribute *attr, const char *buf, size_t count)
 80{
 81	struct qeth_card *card = dev_get_drvdata(dev);
 82	int rc = 0;
 83	enum qeth_sbp_roles role;
 84
 85	if (!card)
 86		return -EINVAL;
 87	if (sysfs_streq(buf, "primary"))
 88		role = QETH_SBP_ROLE_PRIMARY;
 89	else if (sysfs_streq(buf, "secondary"))
 90		role = QETH_SBP_ROLE_SECONDARY;
 91	else if (sysfs_streq(buf, "none"))
 92		role = QETH_SBP_ROLE_NONE;
 93	else
 94		return -EINVAL;
 95
 96	mutex_lock(&card->conf_mutex);
 97
 98	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->conf_mutex);
106
107	return rc ? rc : count;
108}
109
110static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
111		   qeth_bridge_port_role_store);
112
113static ssize_t qeth_bridge_port_state_show(struct device *dev,
114				struct device_attribute *attr, char *buf)
115{
116	return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
117}
118
119static DEVICE_ATTR(bridge_state, 0644, qeth_bridge_port_state_show,
120		   NULL);
121
122static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
123				struct device_attribute *attr, char *buf)
124{
125	struct qeth_card *card = dev_get_drvdata(dev);
126	int enabled;
127
128	if (!card)
129		return -EINVAL;
130
131	mutex_lock(&card->conf_mutex);
132
133	enabled = card->options.sbp.hostnotification;
134
135	mutex_unlock(&card->conf_mutex);
136
137	return sprintf(buf, "%d\n", enabled);
138}
139
140static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
141		struct device_attribute *attr, const char *buf, size_t count)
142{
143	struct qeth_card *card = dev_get_drvdata(dev);
144	int rc = 0;
145	int enable;
146
147	if (!card)
148		return -EINVAL;
149
150	if (sysfs_streq(buf, "0"))
151		enable = 0;
152	else if (sysfs_streq(buf, "1"))
153		enable = 1;
154	else
155		return -EINVAL;
156
157	mutex_lock(&card->conf_mutex);
158
159	if (qeth_card_hw_is_reachable(card)) {
160		rc = qeth_bridgeport_an_set(card, enable);
161		if (!rc)
162			card->options.sbp.hostnotification = enable;
163	} else
164		card->options.sbp.hostnotification = enable;
165
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 struct attribute *qeth_l2_bridgeport_attrs[] = {
176	&dev_attr_bridge_role.attr,
177	&dev_attr_bridge_state.attr,
178	&dev_attr_bridge_hostnotify.attr,
179	NULL,
180};
181
182static struct attribute_group qeth_l2_bridgeport_attr_group = {
183	.attrs = qeth_l2_bridgeport_attrs,
184};
185
186int qeth_l2_create_device_attributes(struct device *dev)
187{
188	return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
189}
190
191void qeth_l2_remove_device_attributes(struct device *dev)
192{
193	sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
194}
195
196/**
197 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
198 * @card:			      qeth_card structure pointer
199 *
200 * Note: this function is called with conf_mutex held by the caller
201 */
202void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
203{
204	int rc;
205
206	if (!card)
207		return;
208	if (!card->options.sbp.supported_funcs)
209		return;
210	if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
211		/* Conditional to avoid spurious error messages */
212		qeth_bridgeport_setrole(card, card->options.sbp.role);
213		/* Let the callback function refresh the stored role value. */
214		qeth_bridgeport_query_ports(card,
215			&card->options.sbp.role, NULL);
216	}
217	if (card->options.sbp.hostnotification) {
218		rc = qeth_bridgeport_an_set(card, 1);
219		if (rc)
220			card->options.sbp.hostnotification = 0;
221	} else
222		qeth_bridgeport_an_set(card, 0);
223}