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