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