GNU Linux-libre 4.14.251-gnu1
[releases.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 };