Merge tag 'vfio-ccw-20170522' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms39...
[sfrench/cifs-2.6.git] / drivers / s390 / net / qeth_l2_sys.c
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>
8 #include "qeth_core.h"
9 #include "qeth_l2.h"
10
11 static 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
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
57         return rc;
58 }
59
60 static 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
66 static 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
86         if (card->options.sbp.reflect_promisc) /* Forbid direct manipulation */
87                 rc = -EPERM;
88         else if (qeth_card_hw_is_reachable(card)) {
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
100 static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
101                    qeth_bridge_port_role_store);
102
103 static 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
109 static DEVICE_ATTR(bridge_state, 0444, qeth_bridge_port_state_show,
110                    NULL);
111
112 static 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
121         enabled = card->options.sbp.hostnotification;
122
123         return sprintf(buf, "%d\n", enabled);
124 }
125
126 static 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
157 static DEVICE_ATTR(bridge_hostnotify, 0644,
158                         qeth_bridgeport_hostnotification_show,
159                         qeth_bridgeport_hostnotification_store);
160
161 static 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
181 static 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;
186         int rc = 0;
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
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         }
212
213         mutex_unlock(&card->conf_mutex);
214
215         return rc ? rc : count;
216 }
217
218 static DEVICE_ATTR(bridge_reflect_promisc, 0644,
219                         qeth_bridgeport_reflect_show,
220                         qeth_bridgeport_reflect_store);
221
222 static struct attribute *qeth_l2_bridgeport_attrs[] = {
223         &dev_attr_bridge_role.attr,
224         &dev_attr_bridge_state.attr,
225         &dev_attr_bridge_hostnotify.attr,
226         &dev_attr_bridge_reflect_promisc.attr,
227         NULL,
228 };
229
230 static struct attribute_group qeth_l2_bridgeport_attr_group = {
231         .attrs = qeth_l2_bridgeport_attrs,
232 };
233
234 int qeth_l2_create_device_attributes(struct device *dev)
235 {
236         return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
237 }
238
239 void 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  */
250 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
251 {
252         int rc;
253
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         }
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);
271 }
272
273 const 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 };