]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/s390/net/qeth_l2_sys.c
Merge remote-tracking branch 'regulator/fix/max77802' into regulator-linus
[mirror_ubuntu-artful-kernel.git] / drivers / s390 / net / qeth_l2_sys.c
CommitLineData
b4d72c08
EC
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>
511c2445 8#include "qeth_core.h"
b4d72c08
EC
9#include "qeth_l2.h"
10
b4d72c08
EC
11static 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
b4d72c08
EC
23 if (qeth_card_hw_is_reachable(card) &&
24 card->options.sbp.supported_funcs)
25 rc = qeth_bridgeport_query_ports(card,
26 &card->options.sbp.role, &state);
27 if (!rc) {
28 if (show_state)
29 switch (state) {
30 case QETH_SBP_STATE_INACTIVE:
31 word = "inactive"; break;
32 case QETH_SBP_STATE_STANDBY:
33 word = "standby"; break;
34 case QETH_SBP_STATE_ACTIVE:
35 word = "active"; break;
36 default:
37 rc = -EIO;
38 }
39 else
40 switch (card->options.sbp.role) {
41 case QETH_SBP_ROLE_NONE:
42 word = "none"; break;
43 case QETH_SBP_ROLE_PRIMARY:
44 word = "primary"; break;
45 case QETH_SBP_ROLE_SECONDARY:
46 word = "secondary"; break;
47 default:
48 rc = -EIO;
49 }
50 if (rc)
51 QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
52 card->options.sbp.role, state);
53 else
54 rc = sprintf(buf, "%s\n", word);
55 }
56
b4d72c08
EC
57 return rc;
58}
59
60static ssize_t qeth_bridge_port_role_show(struct device *dev,
61 struct device_attribute *attr, char *buf)
62{
63 return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
64}
65
66static ssize_t qeth_bridge_port_role_store(struct device *dev,
67 struct device_attribute *attr, const char *buf, size_t count)
68{
69 struct qeth_card *card = dev_get_drvdata(dev);
70 int rc = 0;
71 enum qeth_sbp_roles role;
72
73 if (!card)
74 return -EINVAL;
75 if (sysfs_streq(buf, "primary"))
76 role = QETH_SBP_ROLE_PRIMARY;
77 else if (sysfs_streq(buf, "secondary"))
78 role = QETH_SBP_ROLE_SECONDARY;
79 else if (sysfs_streq(buf, "none"))
80 role = QETH_SBP_ROLE_NONE;
81 else
82 return -EINVAL;
83
84 mutex_lock(&card->conf_mutex);
85
ff1d9291
EC
86 if (card->options.sbp.reflect_promisc) /* Forbid direct manipulation */
87 rc = -EPERM;
88 else if (qeth_card_hw_is_reachable(card)) {
b4d72c08
EC
89 rc = qeth_bridgeport_setrole(card, role);
90 if (!rc)
91 card->options.sbp.role = role;
92 } else
93 card->options.sbp.role = role;
94
95 mutex_unlock(&card->conf_mutex);
96
97 return rc ? rc : count;
98}
99
100static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
101 qeth_bridge_port_role_store);
102
103static ssize_t qeth_bridge_port_state_show(struct device *dev,
104 struct device_attribute *attr, char *buf)
105{
106 return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
107}
108
248046ba 109static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
b4d72c08
EC
110 NULL);
111
9f48b9db
EC
112static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
113 struct device_attribute *attr, char *buf)
114{
115 struct qeth_card *card = dev_get_drvdata(dev);
116 int enabled;
117
118 if (!card)
119 return -EINVAL;
120
9f48b9db
EC
121 enabled = card->options.sbp.hostnotification;
122
9f48b9db
EC
123 return sprintf(buf, "%d\n", enabled);
124}
125
126static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
127 struct device_attribute *attr, const char *buf, size_t count)
128{
129 struct qeth_card *card = dev_get_drvdata(dev);
130 int rc = 0;
131 int enable;
132
133 if (!card)
134 return -EINVAL;
135
136 if (sysfs_streq(buf, "0"))
137 enable = 0;
138 else if (sysfs_streq(buf, "1"))
139 enable = 1;
140 else
141 return -EINVAL;
142
143 mutex_lock(&card->conf_mutex);
144
145 if (qeth_card_hw_is_reachable(card)) {
146 rc = qeth_bridgeport_an_set(card, enable);
147 if (!rc)
148 card->options.sbp.hostnotification = enable;
149 } else
150 card->options.sbp.hostnotification = enable;
151
152 mutex_unlock(&card->conf_mutex);
153
154 return rc ? rc : count;
155}
156
157static DEVICE_ATTR(bridge_hostnotify, 0644,
158 qeth_bridgeport_hostnotification_show,
159 qeth_bridgeport_hostnotification_store);
160
0db587b0
EC
161static ssize_t qeth_bridgeport_reflect_show(struct device *dev,
162 struct device_attribute *attr, char *buf)
163{
164 struct qeth_card *card = dev_get_drvdata(dev);
165 char *state;
166
167 if (!card)
168 return -EINVAL;
169
170 if (card->options.sbp.reflect_promisc) {
171 if (card->options.sbp.reflect_promisc_primary)
172 state = "primary";
173 else
174 state = "secondary";
175 } else
176 state = "none";
177
178 return sprintf(buf, "%s\n", state);
179}
180
181static ssize_t qeth_bridgeport_reflect_store(struct device *dev,
182 struct device_attribute *attr, const char *buf, size_t count)
183{
184 struct qeth_card *card = dev_get_drvdata(dev);
185 int enable, primary;
ff1d9291 186 int rc = 0;
0db587b0
EC
187
188 if (!card)
189 return -EINVAL;
190
191 if (sysfs_streq(buf, "none")) {
192 enable = 0;
193 primary = 0;
194 } else if (sysfs_streq(buf, "primary")) {
195 enable = 1;
196 primary = 1;
197 } else if (sysfs_streq(buf, "secondary")) {
198 enable = 1;
199 primary = 0;
200 } else
201 return -EINVAL;
202
203 mutex_lock(&card->conf_mutex);
204
ff1d9291
EC
205 if (card->options.sbp.role != QETH_SBP_ROLE_NONE)
206 rc = -EPERM;
207 else {
208 card->options.sbp.reflect_promisc = enable;
209 card->options.sbp.reflect_promisc_primary = primary;
210 rc = 0;
211 }
0db587b0
EC
212
213 mutex_unlock(&card->conf_mutex);
214
ff1d9291 215 return rc ? rc : count;
0db587b0
EC
216}
217
218static DEVICE_ATTR(bridge_reflect_promisc, 0644,
219 qeth_bridgeport_reflect_show,
220 qeth_bridgeport_reflect_store);
221
b4d72c08
EC
222static struct attribute *qeth_l2_bridgeport_attrs[] = {
223 &dev_attr_bridge_role.attr,
224 &dev_attr_bridge_state.attr,
9f48b9db 225 &dev_attr_bridge_hostnotify.attr,
0db587b0 226 &dev_attr_bridge_reflect_promisc.attr,
b4d72c08
EC
227 NULL,
228};
229
230static struct attribute_group qeth_l2_bridgeport_attr_group = {
231 .attrs = qeth_l2_bridgeport_attrs,
232};
233
234int qeth_l2_create_device_attributes(struct device *dev)
235{
236 return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
237}
238
239void qeth_l2_remove_device_attributes(struct device *dev)
240{
241 sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
242}
243
244/**
245 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
246 * @card: qeth_card structure pointer
247 *
248 * Note: this function is called with conf_mutex held by the caller
249 */
250void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
251{
9f48b9db
EC
252 int rc;
253
b4d72c08
EC
254 if (!card)
255 return;
256 if (!card->options.sbp.supported_funcs)
257 return;
258 if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
259 /* Conditional to avoid spurious error messages */
260 qeth_bridgeport_setrole(card, card->options.sbp.role);
261 /* Let the callback function refresh the stored role value. */
262 qeth_bridgeport_query_ports(card,
263 &card->options.sbp.role, NULL);
264 }
9f48b9db
EC
265 if (card->options.sbp.hostnotification) {
266 rc = qeth_bridgeport_an_set(card, 1);
267 if (rc)
268 card->options.sbp.hostnotification = 0;
269 } else
270 qeth_bridgeport_an_set(card, 0);
b4d72c08 271}
2d2ebb3e
JW
272
273const struct attribute_group *qeth_l2_attr_groups[] = {
274 &qeth_device_attr_group,
275 &qeth_device_blkt_group,
276 /* l2 specific, see l2_{create,remove}_device_attributes(): */
277 &qeth_l2_bridgeport_attr_group,
278 NULL,
279};