Merge branch 'core-objtool-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / s390 / net / qeth_l3_sys.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
4a71df50 2/*
4a71df50
FB
3 * Copyright IBM Corp. 2007
4 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
5 * Frank Pavlic <fpavlic@de.ibm.com>,
6 * Thomas Spatzier <tspat@de.ibm.com>,
7 * Frank Blaschka <frank.blaschka@de.ibm.com>
8 */
9
5a0e3ad6 10#include <linux/slab.h>
b3332930 11#include <asm/ebcdic.h>
5f78e29c 12#include <linux/hashtable.h>
556fd271 13#include <linux/inet.h>
4a71df50
FB
14#include "qeth_l3.h"
15
16#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
17struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
18
556fd271
JW
19static int qeth_l3_string_to_ipaddr(const char *buf,
20 enum qeth_prot_versions proto, u8 *addr)
21{
22 const char *end;
23
24 if ((proto == QETH_PROT_IPV4 && !in4_pton(buf, -1, addr, -1, &end)) ||
25 (proto == QETH_PROT_IPV6 && !in6_pton(buf, -1, addr, -1, &end)))
26 return -EINVAL;
27 return 0;
28}
29
4a71df50
FB
30static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
31 struct qeth_routing_info *route, char *buf)
32{
33 switch (route->type) {
34 case PRIMARY_ROUTER:
35 return sprintf(buf, "%s\n", "primary router");
36 case SECONDARY_ROUTER:
37 return sprintf(buf, "%s\n", "secondary router");
38 case MULTICAST_ROUTER:
39 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
40 return sprintf(buf, "%s\n", "multicast router+");
41 else
42 return sprintf(buf, "%s\n", "multicast router");
43 case PRIMARY_CONNECTOR:
44 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
45 return sprintf(buf, "%s\n", "primary connector+");
46 else
47 return sprintf(buf, "%s\n", "primary connector");
48 case SECONDARY_CONNECTOR:
49 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
50 return sprintf(buf, "%s\n", "secondary connector+");
51 else
52 return sprintf(buf, "%s\n", "secondary connector");
53 default:
54 return sprintf(buf, "%s\n", "no");
55 }
56}
57
58static ssize_t qeth_l3_dev_route4_show(struct device *dev,
59 struct device_attribute *attr, char *buf)
60{
61 struct qeth_card *card = dev_get_drvdata(dev);
62
4a71df50
FB
63 return qeth_l3_dev_route_show(card, &card->options.route4, buf);
64}
65
66static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
67 struct qeth_routing_info *route, enum qeth_prot_versions prot,
68 const char *buf, size_t count)
69{
70 enum qeth_routing_types old_route_type = route->type;
c4949f07 71 int rc = 0;
4a71df50 72
c4949f07 73 mutex_lock(&card->conf_mutex);
7e846d6b 74 if (sysfs_streq(buf, "no_router")) {
4a71df50 75 route->type = NO_ROUTER;
7e846d6b 76 } else if (sysfs_streq(buf, "primary_connector")) {
4a71df50 77 route->type = PRIMARY_CONNECTOR;
7e846d6b 78 } else if (sysfs_streq(buf, "secondary_connector")) {
4a71df50 79 route->type = SECONDARY_CONNECTOR;
7e846d6b 80 } else if (sysfs_streq(buf, "primary_router")) {
4a71df50 81 route->type = PRIMARY_ROUTER;
7e846d6b 82 } else if (sysfs_streq(buf, "secondary_router")) {
4a71df50 83 route->type = SECONDARY_ROUTER;
7e846d6b 84 } else if (sysfs_streq(buf, "multicast_router")) {
4a71df50
FB
85 route->type = MULTICAST_ROUTER;
86 } else {
c4949f07
FB
87 rc = -EINVAL;
88 goto out;
4a71df50 89 }
c3521254 90 if (qeth_card_hw_is_reachable(card) &&
4a71df50
FB
91 (old_route_type != route->type)) {
92 if (prot == QETH_PROT_IPV4)
93 rc = qeth_l3_setrouting_v4(card);
94 else if (prot == QETH_PROT_IPV6)
95 rc = qeth_l3_setrouting_v6(card);
96 }
c4949f07 97out:
82e2e782
SR
98 if (rc)
99 route->type = old_route_type;
c4949f07
FB
100 mutex_unlock(&card->conf_mutex);
101 return rc ? rc : count;
4a71df50
FB
102}
103
104static ssize_t qeth_l3_dev_route4_store(struct device *dev,
105 struct device_attribute *attr, const char *buf, size_t count)
106{
107 struct qeth_card *card = dev_get_drvdata(dev);
108
4a71df50
FB
109 return qeth_l3_dev_route_store(card, &card->options.route4,
110 QETH_PROT_IPV4, buf, count);
111}
112
113static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
114 qeth_l3_dev_route4_store);
115
116static ssize_t qeth_l3_dev_route6_show(struct device *dev,
117 struct device_attribute *attr, char *buf)
118{
119 struct qeth_card *card = dev_get_drvdata(dev);
120
4a71df50
FB
121 return qeth_l3_dev_route_show(card, &card->options.route6, buf);
122}
123
124static ssize_t qeth_l3_dev_route6_store(struct device *dev,
125 struct device_attribute *attr, const char *buf, size_t count)
126{
127 struct qeth_card *card = dev_get_drvdata(dev);
128
4a71df50
FB
129 return qeth_l3_dev_route_store(card, &card->options.route6,
130 QETH_PROT_IPV6, buf, count);
131}
132
133static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
134 qeth_l3_dev_route6_store);
135
136static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
137 struct device_attribute *attr, char *buf)
138{
139 struct qeth_card *card = dev_get_drvdata(dev);
140
4a71df50
FB
141 return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
142}
143
144static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
145 struct device_attribute *attr, const char *buf, size_t count)
146{
147 struct qeth_card *card = dev_get_drvdata(dev);
148 char *tmp;
c4949f07 149 int i, rc = 0;
4a71df50 150
c4949f07 151 mutex_lock(&card->conf_mutex);
d7d543f2 152 if (card->state != CARD_STATE_DOWN) {
c4949f07
FB
153 rc = -EPERM;
154 goto out;
155 }
4a71df50
FB
156
157 i = simple_strtoul(buf, &tmp, 16);
158 if ((i == 0) || (i == 1))
159 card->options.fake_broadcast = i;
c4949f07
FB
160 else
161 rc = -EINVAL;
162out:
163 mutex_unlock(&card->conf_mutex);
164 return rc ? rc : count;
4a71df50
FB
165}
166
167static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
168 qeth_l3_dev_fake_broadcast_store);
169
76b11f8e
UB
170static ssize_t qeth_l3_dev_sniffer_show(struct device *dev,
171 struct device_attribute *attr, char *buf)
172{
173 struct qeth_card *card = dev_get_drvdata(dev);
174
76b11f8e
UB
175 return sprintf(buf, "%i\n", card->options.sniffer ? 1 : 0);
176}
177
178static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
179 struct device_attribute *attr, const char *buf, size_t count)
180{
181 struct qeth_card *card = dev_get_drvdata(dev);
c4949f07 182 int rc = 0;
76b11f8e
UB
183 unsigned long i;
184
379ac99e 185 if (!IS_IQD(card))
76b11f8e 186 return -EPERM;
b3332930
FB
187 if (card->options.cq == QETH_CQ_ENABLED)
188 return -EPERM;
76b11f8e 189
c4949f07 190 mutex_lock(&card->conf_mutex);
d7d543f2 191 if (card->state != CARD_STATE_DOWN) {
c4949f07
FB
192 rc = -EPERM;
193 goto out;
194 }
76b11f8e 195
0178722b 196 rc = kstrtoul(buf, 16, &i);
c4949f07
FB
197 if (rc) {
198 rc = -EINVAL;
199 goto out;
200 }
76b11f8e
UB
201 switch (i) {
202 case 0:
203 card->options.sniffer = i;
204 break;
205 case 1:
c4949f07 206 qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
1917b47d 207 if (card->ssqd.qdioac2 & CHSC_AC2_SNIFFER_AVAILABLE) {
76b11f8e 208 card->options.sniffer = i;
5d4f7856
JW
209 qeth_resize_buffer_pool(card, QETH_IN_BUF_COUNT_MAX);
210 } else {
c4949f07 211 rc = -EPERM;
5d4f7856
JW
212 }
213
6cc31d09
UB
214 break;
215 default:
c4949f07 216 rc = -EINVAL;
76b11f8e 217 }
c4949f07
FB
218out:
219 mutex_unlock(&card->conf_mutex);
220 return rc ? rc : count;
76b11f8e
UB
221}
222
223static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
224 qeth_l3_dev_sniffer_store);
225
b3332930
FB
226static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
227 struct device_attribute *attr, char *buf)
228{
229 struct qeth_card *card = dev_get_drvdata(dev);
230 char tmp_hsuid[9];
231
379ac99e 232 if (!IS_IQD(card))
b3332930
FB
233 return -EPERM;
234
b3332930
FB
235 memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
236 EBCASC(tmp_hsuid, 8);
237 return sprintf(buf, "%s\n", tmp_hsuid);
238}
239
240static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
241 struct device_attribute *attr, const char *buf, size_t count)
242{
243 struct qeth_card *card = dev_get_drvdata(dev);
5b6c7b55 244 int rc = 0;
b3332930 245 char *tmp;
b3332930 246
379ac99e 247 if (!IS_IQD(card))
b3332930 248 return -EPERM;
5b6c7b55
JW
249
250 mutex_lock(&card->conf_mutex);
251 if (card->state != CARD_STATE_DOWN) {
252 rc = -EPERM;
253 goto out;
254 }
255
256 if (card->options.sniffer) {
257 rc = -EPERM;
258 goto out;
259 }
260
261 if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
262 rc = -EPERM;
263 goto out;
264 }
b3332930
FB
265
266 tmp = strsep((char **)&buf, "\n");
5b6c7b55
JW
267 if (strlen(tmp) > 8) {
268 rc = -EINVAL;
269 goto out;
270 }
b3332930 271
1617dae2 272 if (card->options.hsuid[0])
b3332930 273 /* delete old ip address */
1617dae2 274 qeth_l3_modify_hsuid(card, false);
b3332930
FB
275
276 if (strlen(tmp) == 0) {
277 /* delete ip address only */
278 card->options.hsuid[0] = '\0';
d3d1b205 279 memcpy(card->dev->perm_addr, card->options.hsuid, 9);
b3332930 280 qeth_configure_cq(card, QETH_CQ_DISABLED);
5b6c7b55 281 goto out;
b3332930
FB
282 }
283
5b6c7b55
JW
284 if (qeth_configure_cq(card, QETH_CQ_ENABLED)) {
285 rc = -EPERM;
286 goto out;
287 }
b3332930 288
096a8aac
KC
289 snprintf(card->options.hsuid, sizeof(card->options.hsuid),
290 "%-8s", tmp);
b3332930 291 ASCEBC(card->options.hsuid, 8);
d3d1b205 292 memcpy(card->dev->perm_addr, card->options.hsuid, 9);
b3332930 293
1617dae2 294 rc = qeth_l3_modify_hsuid(card, true);
b3332930 295
5b6c7b55
JW
296out:
297 mutex_unlock(&card->conf_mutex);
b9ea5250 298 return rc ? rc : count;
b3332930
FB
299}
300
301static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
302 qeth_l3_dev_hsuid_store);
303
304
4a71df50
FB
305static struct attribute *qeth_l3_device_attrs[] = {
306 &dev_attr_route4.attr,
307 &dev_attr_route6.attr,
308 &dev_attr_fake_broadcast.attr,
76b11f8e 309 &dev_attr_sniffer.attr,
b3332930 310 &dev_attr_hsuid.attr,
4a71df50
FB
311 NULL,
312};
313
cfe9a042 314static const struct attribute_group qeth_l3_device_attr_group = {
4a71df50
FB
315 .attrs = qeth_l3_device_attrs,
316};
317
318static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
319 struct device_attribute *attr, char *buf)
320{
321 struct qeth_card *card = dev_get_drvdata(dev);
322
4a71df50
FB
323 return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
324}
325
326static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
327 struct device_attribute *attr, const char *buf, size_t count)
328{
329 struct qeth_card *card = dev_get_drvdata(dev);
7fbd9493 330 bool enable;
02f510f3 331 int rc = 0;
4a71df50 332
c4949f07 333 mutex_lock(&card->conf_mutex);
d7d543f2 334 if (card->state != CARD_STATE_DOWN) {
c4949f07
FB
335 rc = -EPERM;
336 goto out;
337 }
4a71df50 338
7e846d6b 339 if (sysfs_streq(buf, "toggle")) {
7fbd9493
JW
340 enable = !card->ipato.enabled;
341 } else if (kstrtobool(buf, &enable)) {
c4949f07 342 rc = -EINVAL;
7fbd9493
JW
343 goto out;
344 }
345
02f510f3
JW
346 if (card->ipato.enabled != enable) {
347 card->ipato.enabled = enable;
df2a2a52 348 mutex_lock(&card->ip_lock);
02f510f3 349 qeth_l3_update_ipato(card);
df2a2a52 350 mutex_unlock(&card->ip_lock);
7fbd9493 351 }
c4949f07
FB
352out:
353 mutex_unlock(&card->conf_mutex);
354 return rc ? rc : count;
4a71df50
FB
355}
356
357static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
358 qeth_l3_dev_ipato_enable_show,
359 qeth_l3_dev_ipato_enable_store);
360
361static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
362 struct device_attribute *attr, char *buf)
363{
364 struct qeth_card *card = dev_get_drvdata(dev);
365
4a71df50
FB
366 return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
367}
368
369static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
370 struct device_attribute *attr,
371 const char *buf, size_t count)
372{
373 struct qeth_card *card = dev_get_drvdata(dev);
02f510f3 374 bool invert;
c4949f07 375 int rc = 0;
4a71df50 376
c4949f07 377 mutex_lock(&card->conf_mutex);
02f510f3
JW
378 if (sysfs_streq(buf, "toggle")) {
379 invert = !card->ipato.invert4;
380 } else if (kstrtobool(buf, &invert)) {
c4949f07 381 rc = -EINVAL;
02f510f3
JW
382 goto out;
383 }
384
385 if (card->ipato.invert4 != invert) {
386 card->ipato.invert4 = invert;
df2a2a52 387 mutex_lock(&card->ip_lock);
02f510f3 388 qeth_l3_update_ipato(card);
df2a2a52 389 mutex_unlock(&card->ip_lock);
02f510f3
JW
390 }
391out:
c4949f07
FB
392 mutex_unlock(&card->conf_mutex);
393 return rc ? rc : count;
4a71df50
FB
394}
395
396static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
397 qeth_l3_dev_ipato_invert4_show,
398 qeth_l3_dev_ipato_invert4_store);
399
400static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
401 enum qeth_prot_versions proto)
402{
403 struct qeth_ipato_entry *ipatoe;
e6b1b7da 404 int str_len = 0;
4a71df50 405
df2a2a52 406 mutex_lock(&card->ip_lock);
4a71df50 407 list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
e6b1b7da
JW
408 char addr_str[40];
409 int entry_len;
410
4a71df50
FB
411 if (ipatoe->proto != proto)
412 continue;
e6b1b7da
JW
413
414 entry_len = qeth_l3_ipaddr_to_string(proto, ipatoe->addr,
415 addr_str);
416 if (entry_len < 0)
417 continue;
418
419 /* Append /%mask to the entry: */
420 entry_len += 1 + ((proto == QETH_PROT_IPV4) ? 2 : 3);
421 /* Enough room to format %entry\n into null terminated page? */
422 if (entry_len + 1 > PAGE_SIZE - str_len - 1)
4a71df50 423 break;
e6b1b7da
JW
424
425 entry_len = scnprintf(buf, PAGE_SIZE - str_len,
426 "%s/%i\n", addr_str, ipatoe->mask_bits);
427 str_len += entry_len;
428 buf += entry_len;
4a71df50 429 }
df2a2a52 430 mutex_unlock(&card->ip_lock);
4a71df50 431
e6b1b7da 432 return str_len ? str_len : scnprintf(buf, PAGE_SIZE, "\n");
4a71df50
FB
433}
434
435static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
436 struct device_attribute *attr, char *buf)
437{
438 struct qeth_card *card = dev_get_drvdata(dev);
439
4a71df50
FB
440 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
441}
442
443static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
444 u8 *addr, int *mask_bits)
445{
446 const char *start, *end;
447 char *tmp;
448 char buffer[40] = {0, };
449
450 start = buf;
451 /* get address string */
452 end = strchr(start, '/');
453 if (!end || (end - start >= 40)) {
4a71df50
FB
454 return -EINVAL;
455 }
456 strncpy(buffer, start, end - start);
457 if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
4a71df50
FB
458 return -EINVAL;
459 }
460 start = end + 1;
461 *mask_bits = simple_strtoul(start, &tmp, 10);
462 if (!strlen(start) ||
463 (tmp == start) ||
464 (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
4a71df50
FB
465 return -EINVAL;
466 }
467 return 0;
468}
469
470static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
471 struct qeth_card *card, enum qeth_prot_versions proto)
472{
473 struct qeth_ipato_entry *ipatoe;
474 u8 addr[16];
475 int mask_bits;
c4949f07 476 int rc = 0;
4a71df50
FB
477
478 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
479 if (rc)
2390166a 480 return rc;
4a71df50
FB
481
482 ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
2390166a
JW
483 if (!ipatoe)
484 return -ENOMEM;
485
4a71df50
FB
486 ipatoe->proto = proto;
487 memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
488 ipatoe->mask_bits = mask_bits;
489
490 rc = qeth_l3_add_ipato_entry(card, ipatoe);
c4949f07 491 if (rc)
4a71df50 492 kfree(ipatoe);
2390166a 493
c4949f07 494 return rc ? rc : count;
4a71df50
FB
495}
496
497static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
498 struct device_attribute *attr, const char *buf, size_t count)
499{
500 struct qeth_card *card = dev_get_drvdata(dev);
501
4a71df50
FB
502 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
503}
504
505static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
506 qeth_l3_dev_ipato_add4_show,
507 qeth_l3_dev_ipato_add4_store);
508
509static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
510 struct qeth_card *card, enum qeth_prot_versions proto)
511{
512 u8 addr[16];
513 int mask_bits;
c4949f07 514 int rc = 0;
4a71df50
FB
515
516 rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
c4949f07 517 if (!rc)
b9ea5250 518 rc = qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
c4949f07 519 return rc ? rc : count;
4a71df50
FB
520}
521
522static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
523 struct device_attribute *attr, const char *buf, size_t count)
524{
525 struct qeth_card *card = dev_get_drvdata(dev);
526
4a71df50
FB
527 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
528}
529
530static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
531 qeth_l3_dev_ipato_del4_store);
532
533static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
534 struct device_attribute *attr, char *buf)
535{
536 struct qeth_card *card = dev_get_drvdata(dev);
537
4a71df50
FB
538 return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
539}
540
541static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
542 struct device_attribute *attr, const char *buf, size_t count)
543{
544 struct qeth_card *card = dev_get_drvdata(dev);
02f510f3 545 bool invert;
c4949f07 546 int rc = 0;
4a71df50 547
c4949f07 548 mutex_lock(&card->conf_mutex);
02f510f3
JW
549 if (sysfs_streq(buf, "toggle")) {
550 invert = !card->ipato.invert6;
551 } else if (kstrtobool(buf, &invert)) {
c4949f07 552 rc = -EINVAL;
02f510f3
JW
553 goto out;
554 }
555
556 if (card->ipato.invert6 != invert) {
557 card->ipato.invert6 = invert;
df2a2a52 558 mutex_lock(&card->ip_lock);
02f510f3 559 qeth_l3_update_ipato(card);
df2a2a52 560 mutex_unlock(&card->ip_lock);
02f510f3
JW
561 }
562out:
c4949f07
FB
563 mutex_unlock(&card->conf_mutex);
564 return rc ? rc : count;
4a71df50
FB
565}
566
567static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
568 qeth_l3_dev_ipato_invert6_show,
569 qeth_l3_dev_ipato_invert6_store);
570
571
572static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
573 struct device_attribute *attr, char *buf)
574{
575 struct qeth_card *card = dev_get_drvdata(dev);
576
4a71df50
FB
577 return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
578}
579
580static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
581 struct device_attribute *attr, const char *buf, size_t count)
582{
583 struct qeth_card *card = dev_get_drvdata(dev);
584
4a71df50
FB
585 return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
586}
587
588static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
589 qeth_l3_dev_ipato_add6_show,
590 qeth_l3_dev_ipato_add6_store);
591
592static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
593 struct device_attribute *attr, const char *buf, size_t count)
594{
595 struct qeth_card *card = dev_get_drvdata(dev);
596
4a71df50
FB
597 return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
598}
599
600static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
601 qeth_l3_dev_ipato_del6_store);
602
603static struct attribute *qeth_ipato_device_attrs[] = {
604 &dev_attr_ipato_enable.attr,
605 &dev_attr_ipato_invert4.attr,
606 &dev_attr_ipato_add4.attr,
607 &dev_attr_ipato_del4.attr,
608 &dev_attr_ipato_invert6.attr,
609 &dev_attr_ipato_add6.attr,
610 &dev_attr_ipato_del6.attr,
611 NULL,
612};
613
cfe9a042 614static const struct attribute_group qeth_device_ipato_group = {
4a71df50
FB
615 .name = "ipa_takeover",
616 .attrs = qeth_ipato_device_attrs,
617};
618
d2073ef3
JW
619static ssize_t qeth_l3_dev_ip_add_show(struct device *dev, char *buf,
620 enum qeth_prot_versions proto,
621 enum qeth_ip_types type)
4a71df50 622{
d2073ef3 623 struct qeth_card *card = dev_get_drvdata(dev);
4a71df50 624 struct qeth_ipaddr *ipaddr;
e48b9eaa 625 int str_len = 0;
e48b9eaa 626 int i;
4a71df50 627
df2a2a52 628 mutex_lock(&card->ip_lock);
e48b9eaa 629 hash_for_each(card->ip_htable, i, ipaddr, hnode) {
e6b1b7da
JW
630 char addr_str[40];
631 int entry_len;
632
d2073ef3 633 if (ipaddr->proto != proto || ipaddr->type != type)
4a71df50 634 continue;
e6b1b7da
JW
635
636 entry_len = qeth_l3_ipaddr_to_string(proto, (u8 *)&ipaddr->u,
637 addr_str);
638 if (entry_len < 0)
639 continue;
640
641 /* Enough room to format %addr\n into null terminated page? */
642 if (entry_len + 1 > PAGE_SIZE - str_len - 1)
4a71df50 643 break;
e6b1b7da
JW
644
645 entry_len = scnprintf(buf, PAGE_SIZE - str_len, "%s\n",
646 addr_str);
647 str_len += entry_len;
648 buf += entry_len;
4a71df50 649 }
df2a2a52 650 mutex_unlock(&card->ip_lock);
4a71df50 651
e6b1b7da 652 return str_len ? str_len : scnprintf(buf, PAGE_SIZE, "\n");
4a71df50
FB
653}
654
655static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
d2073ef3
JW
656 struct device_attribute *attr,
657 char *buf)
4a71df50 658{
d2073ef3
JW
659 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV4,
660 QETH_IP_TYPE_VIPA);
4a71df50
FB
661}
662
2390166a
JW
663static ssize_t qeth_l3_vipa_store(struct device *dev, const char *buf, bool add,
664 size_t count, enum qeth_prot_versions proto)
4a71df50 665{
2390166a 666 struct qeth_card *card = dev_get_drvdata(dev);
4a71df50
FB
667 u8 addr[16] = {0, };
668 int rc;
669
2390166a 670 rc = qeth_l3_string_to_ipaddr(buf, proto, addr);
c4949f07 671 if (!rc)
2390166a 672 rc = qeth_l3_modify_rxip_vipa(card, add, addr,
1617dae2 673 QETH_IP_TYPE_VIPA, proto);
c4949f07 674 return rc ? rc : count;
4a71df50
FB
675}
676
677static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
678 struct device_attribute *attr, const char *buf, size_t count)
679{
2390166a 680 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);
4a71df50
FB
681}
682
683static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
684 qeth_l3_dev_vipa_add4_show,
685 qeth_l3_dev_vipa_add4_store);
686
4a71df50
FB
687static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
688 struct device_attribute *attr, const char *buf, size_t count)
689{
2390166a 690 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);
4a71df50
FB
691}
692
693static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
694 qeth_l3_dev_vipa_del4_store);
695
696static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
d2073ef3
JW
697 struct device_attribute *attr,
698 char *buf)
4a71df50 699{
d2073ef3
JW
700 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV6,
701 QETH_IP_TYPE_VIPA);
4a71df50
FB
702}
703
704static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
705 struct device_attribute *attr, const char *buf, size_t count)
706{
2390166a 707 return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV6);
4a71df50
FB
708}
709
710static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
711 qeth_l3_dev_vipa_add6_show,
712 qeth_l3_dev_vipa_add6_store);
713
714static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
715 struct device_attribute *attr, const char *buf, size_t count)
716{
2390166a 717 return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV6);
4a71df50
FB
718}
719
720static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
721 qeth_l3_dev_vipa_del6_store);
722
723static struct attribute *qeth_vipa_device_attrs[] = {
724 &dev_attr_vipa_add4.attr,
725 &dev_attr_vipa_del4.attr,
726 &dev_attr_vipa_add6.attr,
727 &dev_attr_vipa_del6.attr,
728 NULL,
729};
730
cfe9a042 731static const struct attribute_group qeth_device_vipa_group = {
4a71df50
FB
732 .name = "vipa",
733 .attrs = qeth_vipa_device_attrs,
734};
735
4a71df50 736static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
d2073ef3
JW
737 struct device_attribute *attr,
738 char *buf)
4a71df50 739{
d2073ef3
JW
740 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV4,
741 QETH_IP_TYPE_RXIP);
4a71df50
FB
742}
743
744static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
745 u8 *addr)
746{
aa9bea0b
KM
747 __be32 ipv4_addr;
748 struct in6_addr ipv6_addr;
749
4a71df50 750 if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
4a71df50
FB
751 return -EINVAL;
752 }
aa9bea0b
KM
753 if (proto == QETH_PROT_IPV4) {
754 memcpy(&ipv4_addr, addr, sizeof(ipv4_addr));
755 if (ipv4_is_multicast(ipv4_addr)) {
756 QETH_DBF_MESSAGE(2, "multicast rxip not supported.\n");
757 return -EINVAL;
758 }
759 } else if (proto == QETH_PROT_IPV6) {
760 memcpy(&ipv6_addr, addr, sizeof(ipv6_addr));
761 if (ipv6_addr_is_multicast(&ipv6_addr)) {
762 QETH_DBF_MESSAGE(2, "multicast rxip not supported.\n");
763 return -EINVAL;
764 }
765 }
766
4a71df50
FB
767 return 0;
768}
769
2390166a
JW
770static ssize_t qeth_l3_rxip_store(struct device *dev, const char *buf, bool add,
771 size_t count, enum qeth_prot_versions proto)
4a71df50 772{
2390166a 773 struct qeth_card *card = dev_get_drvdata(dev);
4a71df50
FB
774 u8 addr[16] = {0, };
775 int rc;
776
777 rc = qeth_l3_parse_rxipe(buf, proto, addr);
c4949f07 778 if (!rc)
2390166a 779 rc = qeth_l3_modify_rxip_vipa(card, add, addr,
1617dae2 780 QETH_IP_TYPE_RXIP, proto);
c4949f07 781 return rc ? rc : count;
4a71df50
FB
782}
783
784static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
785 struct device_attribute *attr, const char *buf, size_t count)
786{
2390166a 787 return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV4);
4a71df50
FB
788}
789
790static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
791 qeth_l3_dev_rxip_add4_show,
792 qeth_l3_dev_rxip_add4_store);
793
4a71df50
FB
794static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
795 struct device_attribute *attr, const char *buf, size_t count)
796{
2390166a 797 return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV4);
4a71df50
FB
798}
799
800static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
801 qeth_l3_dev_rxip_del4_store);
802
803static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
d2073ef3
JW
804 struct device_attribute *attr,
805 char *buf)
4a71df50 806{
d2073ef3
JW
807 return qeth_l3_dev_ip_add_show(dev, buf, QETH_PROT_IPV6,
808 QETH_IP_TYPE_RXIP);
4a71df50
FB
809}
810
811static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
812 struct device_attribute *attr, const char *buf, size_t count)
813{
2390166a 814 return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV6);
4a71df50
FB
815}
816
817static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
818 qeth_l3_dev_rxip_add6_show,
819 qeth_l3_dev_rxip_add6_store);
820
821static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
822 struct device_attribute *attr, const char *buf, size_t count)
823{
2390166a 824 return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV6);
4a71df50
FB
825}
826
827static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
828 qeth_l3_dev_rxip_del6_store);
829
830static struct attribute *qeth_rxip_device_attrs[] = {
831 &dev_attr_rxip_add4.attr,
832 &dev_attr_rxip_del4.attr,
833 &dev_attr_rxip_add6.attr,
834 &dev_attr_rxip_del6.attr,
835 NULL,
836};
837
cfe9a042 838static const struct attribute_group qeth_device_rxip_group = {
4a71df50
FB
839 .name = "rxip",
840 .attrs = qeth_rxip_device_attrs,
841};
842
ab25a501
JW
843static const struct attribute_group *qeth_l3_only_attr_groups[] = {
844 &qeth_l3_device_attr_group,
845 &qeth_device_ipato_group,
846 &qeth_device_vipa_group,
847 &qeth_device_rxip_group,
848 NULL,
849};
850
4a71df50
FB
851int qeth_l3_create_device_attributes(struct device *dev)
852{
ab25a501 853 return sysfs_create_groups(&dev->kobj, qeth_l3_only_attr_groups);
4a71df50
FB
854}
855
856void qeth_l3_remove_device_attributes(struct device *dev)
857{
ab25a501 858 sysfs_remove_groups(&dev->kobj, qeth_l3_only_attr_groups);
4a71df50 859}
79a04e40
UB
860
861const struct attribute_group *qeth_l3_attr_groups[] = {
862 &qeth_device_attr_group,
863 &qeth_device_blkt_group,
ab25a501 864 /* l3 specific, see qeth_l3_only_attr_groups: */
79a04e40
UB
865 &qeth_l3_device_attr_group,
866 &qeth_device_ipato_group,
867 &qeth_device_vipa_group,
868 &qeth_device_rxip_group,
ab25a501 869 NULL,
79a04e40 870};