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