1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright IBM Corp. 2013
4 * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
7 #include <linux/slab.h>
8 #include <asm/ebcdic.h>
12 static ssize_t
qeth_bridge_port_role_state_show(struct device
*dev
,
13 struct device_attribute
*attr
, char *buf
,
16 struct qeth_card
*card
= dev_get_drvdata(dev
);
17 enum qeth_sbp_states state
= QETH_SBP_STATE_INACTIVE
;
21 if (qeth_l2_vnicc_is_in_use(card
))
22 return sprintf(buf
, "n/a (VNIC characteristics)\n");
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
);
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;
42 switch (card
->options
.sbp
.role
) {
43 case QETH_SBP_ROLE_NONE
:
45 case QETH_SBP_ROLE_PRIMARY
:
46 word
= "primary"; break;
47 case QETH_SBP_ROLE_SECONDARY
:
48 word
= "secondary"; break;
53 QETH_CARD_TEXT_(card
, 2, "SBP%02x:%02x",
54 card
->options
.sbp
.role
, state
);
56 rc
= sprintf(buf
, "%s\n", word
);
58 mutex_unlock(&card
->sbp_lock
);
63 static ssize_t
qeth_bridge_port_role_show(struct device
*dev
,
64 struct device_attribute
*attr
, char *buf
)
66 struct qeth_card
*card
= dev_get_drvdata(dev
);
68 if (qeth_l2_vnicc_is_in_use(card
))
69 return sprintf(buf
, "n/a (VNIC characteristics)\n");
71 return qeth_bridge_port_role_state_show(dev
, attr
, buf
, 0);
74 static ssize_t
qeth_bridge_port_role_store(struct device
*dev
,
75 struct device_attribute
*attr
, const char *buf
, size_t count
)
77 struct qeth_card
*card
= dev_get_drvdata(dev
);
79 enum qeth_sbp_roles role
;
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
;
90 mutex_lock(&card
->conf_mutex
);
91 mutex_lock(&card
->sbp_lock
);
93 if (qeth_l2_vnicc_is_in_use(card
))
95 else if (card
->options
.sbp
.reflect_promisc
)
96 /* Forbid direct manipulation */
98 else if (qeth_card_hw_is_reachable(card
)) {
99 rc
= qeth_bridgeport_setrole(card
, role
);
101 card
->options
.sbp
.role
= role
;
103 card
->options
.sbp
.role
= role
;
105 mutex_unlock(&card
->sbp_lock
);
106 mutex_unlock(&card
->conf_mutex
);
108 return rc
? rc
: count
;
111 static DEVICE_ATTR(bridge_role
, 0644, qeth_bridge_port_role_show
,
112 qeth_bridge_port_role_store
);
114 static ssize_t
qeth_bridge_port_state_show(struct device
*dev
,
115 struct device_attribute
*attr
, char *buf
)
117 struct qeth_card
*card
= dev_get_drvdata(dev
);
119 if (qeth_l2_vnicc_is_in_use(card
))
120 return sprintf(buf
, "n/a (VNIC characteristics)\n");
122 return qeth_bridge_port_role_state_show(dev
, attr
, buf
, 1);
125 static DEVICE_ATTR(bridge_state
, 0444, qeth_bridge_port_state_show
,
128 static ssize_t
qeth_bridgeport_hostnotification_show(struct device
*dev
,
129 struct device_attribute
*attr
, char *buf
)
131 struct qeth_card
*card
= dev_get_drvdata(dev
);
134 if (qeth_l2_vnicc_is_in_use(card
))
135 return sprintf(buf
, "n/a (VNIC characteristics)\n");
137 enabled
= card
->options
.sbp
.hostnotification
;
139 return sprintf(buf
, "%d\n", enabled
);
142 static ssize_t
qeth_bridgeport_hostnotification_store(struct device
*dev
,
143 struct device_attribute
*attr
, const char *buf
, size_t count
)
145 struct qeth_card
*card
= dev_get_drvdata(dev
);
149 rc
= kstrtobool(buf
, &enable
);
153 mutex_lock(&card
->conf_mutex
);
154 mutex_lock(&card
->sbp_lock
);
156 if (qeth_l2_vnicc_is_in_use(card
))
158 else if (qeth_card_hw_is_reachable(card
)) {
159 rc
= qeth_bridgeport_an_set(card
, enable
);
161 card
->options
.sbp
.hostnotification
= enable
;
163 card
->options
.sbp
.hostnotification
= enable
;
165 mutex_unlock(&card
->sbp_lock
);
166 mutex_unlock(&card
->conf_mutex
);
168 return rc
? rc
: count
;
171 static DEVICE_ATTR(bridge_hostnotify
, 0644,
172 qeth_bridgeport_hostnotification_show
,
173 qeth_bridgeport_hostnotification_store
);
175 static ssize_t
qeth_bridgeport_reflect_show(struct device
*dev
,
176 struct device_attribute
*attr
, char *buf
)
178 struct qeth_card
*card
= dev_get_drvdata(dev
);
181 if (qeth_l2_vnicc_is_in_use(card
))
182 return sprintf(buf
, "n/a (VNIC characteristics)\n");
184 if (card
->options
.sbp
.reflect_promisc
) {
185 if (card
->options
.sbp
.reflect_promisc_primary
)
192 return sprintf(buf
, "%s\n", state
);
195 static ssize_t
qeth_bridgeport_reflect_store(struct device
*dev
,
196 struct device_attribute
*attr
, const char *buf
, size_t count
)
198 struct qeth_card
*card
= dev_get_drvdata(dev
);
202 if (sysfs_streq(buf
, "none")) {
205 } else if (sysfs_streq(buf
, "primary")) {
208 } else if (sysfs_streq(buf
, "secondary")) {
214 mutex_lock(&card
->conf_mutex
);
215 mutex_lock(&card
->sbp_lock
);
217 if (qeth_l2_vnicc_is_in_use(card
))
219 else if (card
->options
.sbp
.role
!= QETH_SBP_ROLE_NONE
)
222 card
->options
.sbp
.reflect_promisc
= enable
;
223 card
->options
.sbp
.reflect_promisc_primary
= primary
;
227 mutex_unlock(&card
->sbp_lock
);
228 mutex_unlock(&card
->conf_mutex
);
230 return rc
? rc
: count
;
233 static DEVICE_ATTR(bridge_reflect_promisc
, 0644,
234 qeth_bridgeport_reflect_show
,
235 qeth_bridgeport_reflect_store
);
237 static 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
,
245 static struct attribute_group qeth_l2_bridgeport_attr_group
= {
246 .attrs
= qeth_l2_bridgeport_attrs
,
249 /* VNIC CHARS support */
251 /* convert sysfs attr name to VNIC characteristic */
252 static u32
qeth_l2_vnicc_sysfs_attr_to_char(const char *attr_name
)
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
;
272 /* get current timeout setting */
273 static ssize_t
qeth_vnicc_timeout_show(struct device
*dev
,
274 struct device_attribute
*attr
, char *buf
)
276 struct qeth_card
*card
= dev_get_drvdata(dev
);
280 rc
= qeth_l2_vnicc_get_timeout(card
, &timeout
);
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
);
288 /* change timeout setting */
289 static ssize_t
qeth_vnicc_timeout_store(struct device
*dev
,
290 struct device_attribute
*attr
,
291 const char *buf
, size_t count
)
293 struct qeth_card
*card
= dev_get_drvdata(dev
);
297 rc
= kstrtou32(buf
, 10, &timeout
);
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
;
307 /* get current setting of characteristic */
308 static ssize_t
qeth_vnicc_char_show(struct device
*dev
,
309 struct device_attribute
*attr
, char *buf
)
311 struct qeth_card
*card
= dev_get_drvdata(dev
);
316 vnicc
= qeth_l2_vnicc_sysfs_attr_to_char(attr
->attr
.name
);
317 rc
= qeth_l2_vnicc_get_state(card
, vnicc
, &state
);
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
);
326 /* change setting of characteristic */
327 static ssize_t
qeth_vnicc_char_store(struct device
*dev
,
328 struct device_attribute
*attr
,
329 const char *buf
, size_t count
)
331 struct qeth_card
*card
= dev_get_drvdata(dev
);
336 if (kstrtobool(buf
, &state
))
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
);
344 return rc
? rc
: count
;
347 static DEVICE_ATTR(flooding
, 0644, qeth_vnicc_char_show
, qeth_vnicc_char_store
);
348 static DEVICE_ATTR(mcast_flooding
, 0644, qeth_vnicc_char_show
,
349 qeth_vnicc_char_store
);
350 static DEVICE_ATTR(learning
, 0644, qeth_vnicc_char_show
, qeth_vnicc_char_store
);
351 static DEVICE_ATTR(learning_timeout
, 0644, qeth_vnicc_timeout_show
,
352 qeth_vnicc_timeout_store
);
353 static DEVICE_ATTR(takeover_setvmac
, 0644, qeth_vnicc_char_show
,
354 qeth_vnicc_char_store
);
355 static DEVICE_ATTR(takeover_learning
, 0644, qeth_vnicc_char_show
,
356 qeth_vnicc_char_store
);
357 static DEVICE_ATTR(bridge_invisible
, 0644, qeth_vnicc_char_show
,
358 qeth_vnicc_char_store
);
359 static DEVICE_ATTR(rx_bcast
, 0644, qeth_vnicc_char_show
, qeth_vnicc_char_store
);
361 static 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
,
373 static struct attribute_group qeth_l2_vnicc_attr_group
= {
374 .attrs
= qeth_l2_vnicc_attrs
,
378 static const struct attribute_group
*qeth_l2_only_attr_groups
[] = {
379 &qeth_l2_bridgeport_attr_group
,
380 &qeth_l2_vnicc_attr_group
,
384 int qeth_l2_create_device_attributes(struct device
*dev
)
386 return sysfs_create_groups(&dev
->kobj
, qeth_l2_only_attr_groups
);
389 void qeth_l2_remove_device_attributes(struct device
*dev
)
391 sysfs_remove_groups(&dev
->kobj
, qeth_l2_only_attr_groups
);
394 const 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
,