]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/s390/net/qeth_l3_sys.c
88f200c8ea3c1debd72c7de091e2f81ca2af13e8
[karo-tx-linux.git] / drivers / s390 / net / qeth_l3_sys.c
1 /*
2  *  drivers/s390/net/qeth_l3_sys.c
3  *
4  *    Copyright IBM Corp. 2007
5  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
6  *               Frank Pavlic <fpavlic@de.ibm.com>,
7  *               Thomas Spatzier <tspat@de.ibm.com>,
8  *               Frank Blaschka <frank.blaschka@de.ibm.com>
9  */
10
11 #include "qeth_l3.h"
12
13 #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
14 struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
15
16 static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
17 {
18         if (card->options.checksum_type == SW_CHECKSUMMING)
19                 return "sw";
20         else if (card->options.checksum_type == HW_CHECKSUMMING)
21                 return "hw";
22         else
23                 return "no";
24 }
25
26 static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
27                         struct qeth_routing_info *route, char *buf)
28 {
29         switch (route->type) {
30         case PRIMARY_ROUTER:
31                 return sprintf(buf, "%s\n", "primary router");
32         case SECONDARY_ROUTER:
33                 return sprintf(buf, "%s\n", "secondary router");
34         case MULTICAST_ROUTER:
35                 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
36                         return sprintf(buf, "%s\n", "multicast router+");
37                 else
38                         return sprintf(buf, "%s\n", "multicast router");
39         case PRIMARY_CONNECTOR:
40                 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
41                         return sprintf(buf, "%s\n", "primary connector+");
42                 else
43                         return sprintf(buf, "%s\n", "primary connector");
44         case SECONDARY_CONNECTOR:
45                 if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
46                         return sprintf(buf, "%s\n", "secondary connector+");
47                 else
48                         return sprintf(buf, "%s\n", "secondary connector");
49         default:
50                 return sprintf(buf, "%s\n", "no");
51         }
52 }
53
54 static ssize_t qeth_l3_dev_route4_show(struct device *dev,
55                         struct device_attribute *attr, char *buf)
56 {
57         struct qeth_card *card = dev_get_drvdata(dev);
58
59         if (!card)
60                 return -EINVAL;
61
62         return qeth_l3_dev_route_show(card, &card->options.route4, buf);
63 }
64
65 static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
66                 struct qeth_routing_info *route, enum qeth_prot_versions prot,
67                 const char *buf, size_t count)
68 {
69         enum qeth_routing_types old_route_type = route->type;
70         char *tmp;
71         int rc;
72
73         tmp = strsep((char **) &buf, "\n");
74
75         if (!strcmp(tmp, "no_router")) {
76                 route->type = NO_ROUTER;
77         } else if (!strcmp(tmp, "primary_connector")) {
78                 route->type = PRIMARY_CONNECTOR;
79         } else if (!strcmp(tmp, "secondary_connector")) {
80                 route->type = SECONDARY_CONNECTOR;
81         } else if (!strcmp(tmp, "primary_router")) {
82                 route->type = PRIMARY_ROUTER;
83         } else if (!strcmp(tmp, "secondary_router")) {
84                 route->type = SECONDARY_ROUTER;
85         } else if (!strcmp(tmp, "multicast_router")) {
86                 route->type = MULTICAST_ROUTER;
87         } else {
88                 return -EINVAL;
89         }
90         if (((card->state == CARD_STATE_SOFTSETUP) ||
91              (card->state == CARD_STATE_UP)) &&
92             (old_route_type != route->type)) {
93                 if (prot == QETH_PROT_IPV4)
94                         rc = qeth_l3_setrouting_v4(card);
95                 else if (prot == QETH_PROT_IPV6)
96                         rc = qeth_l3_setrouting_v6(card);
97         }
98         return count;
99 }
100
101 static ssize_t qeth_l3_dev_route4_store(struct device *dev,
102                 struct device_attribute *attr, const char *buf, size_t count)
103 {
104         struct qeth_card *card = dev_get_drvdata(dev);
105
106         if (!card)
107                 return -EINVAL;
108
109         return qeth_l3_dev_route_store(card, &card->options.route4,
110                                 QETH_PROT_IPV4, buf, count);
111 }
112
113 static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
114                         qeth_l3_dev_route4_store);
115
116 static 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
121         if (!card)
122                 return -EINVAL;
123
124         return qeth_l3_dev_route_show(card, &card->options.route6, buf);
125 }
126
127 static ssize_t qeth_l3_dev_route6_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
132         if (!card)
133                 return -EINVAL;
134
135         return qeth_l3_dev_route_store(card, &card->options.route6,
136                                 QETH_PROT_IPV6, buf, count);
137 }
138
139 static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
140                         qeth_l3_dev_route6_store);
141
142 static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
143                         struct device_attribute *attr, char *buf)
144 {
145         struct qeth_card *card = dev_get_drvdata(dev);
146
147         if (!card)
148                 return -EINVAL;
149
150         return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
151 }
152
153 static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
154                 struct device_attribute *attr, const char *buf, size_t count)
155 {
156         struct qeth_card *card = dev_get_drvdata(dev);
157         char *tmp;
158         int i;
159
160         if (!card)
161                 return -EINVAL;
162
163         if ((card->state != CARD_STATE_DOWN) &&
164             (card->state != CARD_STATE_RECOVER))
165                 return -EPERM;
166
167         i = simple_strtoul(buf, &tmp, 16);
168         if ((i == 0) || (i == 1))
169                 card->options.fake_broadcast = i;
170         else {
171                 return -EINVAL;
172         }
173         return count;
174 }
175
176 static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
177                    qeth_l3_dev_fake_broadcast_store);
178
179 static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
180                                 struct device_attribute *attr, char *buf)
181 {
182         struct qeth_card *card = dev_get_drvdata(dev);
183
184         if (!card)
185                 return -EINVAL;
186
187         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
188               (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
189                 return sprintf(buf, "n/a\n");
190
191         return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
192                                      QETH_TR_BROADCAST_ALLRINGS)?
193                        "all rings":"local");
194 }
195
196 static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
197                 struct device_attribute *attr, const char *buf, size_t count)
198 {
199         struct qeth_card *card = dev_get_drvdata(dev);
200         char *tmp;
201
202         if (!card)
203                 return -EINVAL;
204
205         if ((card->state != CARD_STATE_DOWN) &&
206             (card->state != CARD_STATE_RECOVER))
207                 return -EPERM;
208
209         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
210               (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
211                 return -EINVAL;
212         }
213
214         tmp = strsep((char **) &buf, "\n");
215
216         if (!strcmp(tmp, "local")) {
217                 card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
218                 return count;
219         } else if (!strcmp(tmp, "all_rings")) {
220                 card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
221                 return count;
222         } else {
223                 return -EINVAL;
224         }
225         return count;
226 }
227
228 static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
229                    qeth_l3_dev_broadcast_mode_store);
230
231 static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
232                                 struct device_attribute *attr, char *buf)
233 {
234         struct qeth_card *card = dev_get_drvdata(dev);
235
236         if (!card)
237                 return -EINVAL;
238
239         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
240               (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
241                 return sprintf(buf, "n/a\n");
242
243         return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
244                                      QETH_TR_MACADDR_CANONICAL)? 1:0);
245 }
246
247 static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
248                 struct device_attribute *attr, const char *buf, size_t count)
249 {
250         struct qeth_card *card = dev_get_drvdata(dev);
251         char *tmp;
252         int i;
253
254         if (!card)
255                 return -EINVAL;
256
257         if ((card->state != CARD_STATE_DOWN) &&
258             (card->state != CARD_STATE_RECOVER))
259                 return -EPERM;
260
261         if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
262               (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
263                 return -EINVAL;
264         }
265
266         i = simple_strtoul(buf, &tmp, 16);
267         if ((i == 0) || (i == 1))
268                 card->options.macaddr_mode = i?
269                         QETH_TR_MACADDR_CANONICAL :
270                         QETH_TR_MACADDR_NONCANONICAL;
271         else {
272                 return -EINVAL;
273         }
274         return count;
275 }
276
277 static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
278                    qeth_l3_dev_canonical_macaddr_store);
279
280 static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
281                         struct device_attribute *attr, char *buf)
282 {
283         struct qeth_card *card = dev_get_drvdata(dev);
284
285         if (!card)
286                 return -EINVAL;
287
288         return sprintf(buf, "%s checksumming\n",
289                         qeth_l3_get_checksum_str(card));
290 }
291
292 static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
293                 struct device_attribute *attr, const char *buf, size_t count)
294 {
295         struct qeth_card *card = dev_get_drvdata(dev);
296         char *tmp;
297
298         if (!card)
299                 return -EINVAL;
300
301         if ((card->state != CARD_STATE_DOWN) &&
302             (card->state != CARD_STATE_RECOVER))
303                 return -EPERM;
304
305         tmp = strsep((char **) &buf, "\n");
306         if (!strcmp(tmp, "sw_checksumming"))
307                 card->options.checksum_type = SW_CHECKSUMMING;
308         else if (!strcmp(tmp, "hw_checksumming"))
309                 card->options.checksum_type = HW_CHECKSUMMING;
310         else if (!strcmp(tmp, "no_checksumming"))
311                 card->options.checksum_type = NO_CHECKSUMMING;
312         else {
313                 return -EINVAL;
314         }
315         return count;
316 }
317
318 static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
319                 qeth_l3_dev_checksum_store);
320
321 static ssize_t qeth_l3_dev_large_send_show(struct device *dev,
322                                 struct device_attribute *attr, char *buf)
323 {
324         struct qeth_card *card = dev_get_drvdata(dev);
325
326         if (!card)
327                 return -EINVAL;
328
329         switch (card->options.large_send) {
330         case QETH_LARGE_SEND_NO:
331                 return sprintf(buf, "%s\n", "no");
332         case QETH_LARGE_SEND_TSO:
333                 return sprintf(buf, "%s\n", "TSO");
334         default:
335                 return sprintf(buf, "%s\n", "N/A");
336         }
337 }
338
339 static ssize_t qeth_l3_dev_large_send_store(struct device *dev,
340                 struct device_attribute *attr, const char *buf, size_t count)
341 {
342         struct qeth_card *card = dev_get_drvdata(dev);
343         enum qeth_large_send_types type;
344         int rc = 0;
345         char *tmp;
346
347         if (!card)
348                 return -EINVAL;
349         tmp = strsep((char **) &buf, "\n");
350         if (!strcmp(tmp, "no"))
351                 type = QETH_LARGE_SEND_NO;
352         else if (!strcmp(tmp, "TSO"))
353                 type = QETH_LARGE_SEND_TSO;
354         else
355                 return -EINVAL;
356
357         if (card->options.large_send == type)
358                 return count;
359         rc = qeth_l3_set_large_send(card, type);
360         if (rc)
361                 return rc;
362         return count;
363 }
364
365 static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
366                    qeth_l3_dev_large_send_store);
367
368 static struct attribute *qeth_l3_device_attrs[] = {
369         &dev_attr_route4.attr,
370         &dev_attr_route6.attr,
371         &dev_attr_fake_broadcast.attr,
372         &dev_attr_broadcast_mode.attr,
373         &dev_attr_canonical_macaddr.attr,
374         &dev_attr_checksumming.attr,
375         &dev_attr_large_send.attr,
376         NULL,
377 };
378
379 static struct attribute_group qeth_l3_device_attr_group = {
380         .attrs = qeth_l3_device_attrs,
381 };
382
383 static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
384                         struct device_attribute *attr, char *buf)
385 {
386         struct qeth_card *card = dev_get_drvdata(dev);
387
388         if (!card)
389                 return -EINVAL;
390
391         return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
392 }
393
394 static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
395                 struct device_attribute *attr, const char *buf, size_t count)
396 {
397         struct qeth_card *card = dev_get_drvdata(dev);
398         char *tmp;
399
400         if (!card)
401                 return -EINVAL;
402
403         if ((card->state != CARD_STATE_DOWN) &&
404             (card->state != CARD_STATE_RECOVER))
405                 return -EPERM;
406
407         tmp = strsep((char **) &buf, "\n");
408         if (!strcmp(tmp, "toggle")) {
409                 card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
410         } else if (!strcmp(tmp, "1")) {
411                 card->ipato.enabled = 1;
412         } else if (!strcmp(tmp, "0")) {
413                 card->ipato.enabled = 0;
414         } else {
415                 return -EINVAL;
416         }
417         return count;
418 }
419
420 static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
421                         qeth_l3_dev_ipato_enable_show,
422                         qeth_l3_dev_ipato_enable_store);
423
424 static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
425                                 struct device_attribute *attr, char *buf)
426 {
427         struct qeth_card *card = dev_get_drvdata(dev);
428
429         if (!card)
430                 return -EINVAL;
431
432         return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
433 }
434
435 static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
436                                 struct device_attribute *attr,
437                                 const char *buf, size_t count)
438 {
439         struct qeth_card *card = dev_get_drvdata(dev);
440         char *tmp;
441
442         if (!card)
443                 return -EINVAL;
444
445         tmp = strsep((char **) &buf, "\n");
446         if (!strcmp(tmp, "toggle")) {
447                 card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
448         } else if (!strcmp(tmp, "1")) {
449                 card->ipato.invert4 = 1;
450         } else if (!strcmp(tmp, "0")) {
451                 card->ipato.invert4 = 0;
452         } else {
453                 return -EINVAL;
454         }
455         return count;
456 }
457
458 static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
459                         qeth_l3_dev_ipato_invert4_show,
460                         qeth_l3_dev_ipato_invert4_store);
461
462 static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
463                         enum qeth_prot_versions proto)
464 {
465         struct qeth_ipato_entry *ipatoe;
466         unsigned long flags;
467         char addr_str[40];
468         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
469         int i = 0;
470
471         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
472         /* add strlen for "/<mask>\n" */
473         entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
474         spin_lock_irqsave(&card->ip_lock, flags);
475         list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
476                 if (ipatoe->proto != proto)
477                         continue;
478                 /* String must not be longer than PAGE_SIZE. So we check if
479                  * string length gets near PAGE_SIZE. Then we can savely display
480                  * the next IPv6 address (worst case, compared to IPv4) */
481                 if ((PAGE_SIZE - i) <= entry_len)
482                         break;
483                 qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
484                 i += snprintf(buf + i, PAGE_SIZE - i,
485                               "%s/%i\n", addr_str, ipatoe->mask_bits);
486         }
487         spin_unlock_irqrestore(&card->ip_lock, flags);
488         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
489
490         return i;
491 }
492
493 static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
494                                 struct device_attribute *attr, char *buf)
495 {
496         struct qeth_card *card = dev_get_drvdata(dev);
497
498         if (!card)
499                 return -EINVAL;
500
501         return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
502 }
503
504 static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
505                   u8 *addr, int *mask_bits)
506 {
507         const char *start, *end;
508         char *tmp;
509         char buffer[40] = {0, };
510
511         start = buf;
512         /* get address string */
513         end = strchr(start, '/');
514         if (!end || (end - start >= 40)) {
515                 return -EINVAL;
516         }
517         strncpy(buffer, start, end - start);
518         if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
519                 return -EINVAL;
520         }
521         start = end + 1;
522         *mask_bits = simple_strtoul(start, &tmp, 10);
523         if (!strlen(start) ||
524             (tmp == start) ||
525             (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
526                 return -EINVAL;
527         }
528         return 0;
529 }
530
531 static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
532                          struct qeth_card *card, enum qeth_prot_versions proto)
533 {
534         struct qeth_ipato_entry *ipatoe;
535         u8 addr[16];
536         int mask_bits;
537         int rc;
538
539         rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
540         if (rc)
541                 return rc;
542
543         ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
544         if (!ipatoe) {
545                 return -ENOMEM;
546         }
547         ipatoe->proto = proto;
548         memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
549         ipatoe->mask_bits = mask_bits;
550
551         rc = qeth_l3_add_ipato_entry(card, ipatoe);
552         if (rc) {
553                 kfree(ipatoe);
554                 return rc;
555         }
556
557         return count;
558 }
559
560 static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
561                 struct device_attribute *attr, const char *buf, size_t count)
562 {
563         struct qeth_card *card = dev_get_drvdata(dev);
564
565         if (!card)
566                 return -EINVAL;
567
568         return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
569 }
570
571 static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
572                         qeth_l3_dev_ipato_add4_show,
573                         qeth_l3_dev_ipato_add4_store);
574
575 static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
576                          struct qeth_card *card, enum qeth_prot_versions proto)
577 {
578         u8 addr[16];
579         int mask_bits;
580         int rc;
581
582         rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
583         if (rc)
584                 return rc;
585
586         qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
587
588         return count;
589 }
590
591 static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
592                 struct device_attribute *attr, const char *buf, size_t count)
593 {
594         struct qeth_card *card = dev_get_drvdata(dev);
595
596         if (!card)
597                 return -EINVAL;
598
599         return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
600 }
601
602 static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
603                         qeth_l3_dev_ipato_del4_store);
604
605 static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
606                 struct device_attribute *attr, char *buf)
607 {
608         struct qeth_card *card = dev_get_drvdata(dev);
609
610         if (!card)
611                 return -EINVAL;
612
613         return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
614 }
615
616 static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
617                 struct device_attribute *attr, const char *buf, size_t count)
618 {
619         struct qeth_card *card = dev_get_drvdata(dev);
620         char *tmp;
621
622         if (!card)
623                 return -EINVAL;
624
625         tmp = strsep((char **) &buf, "\n");
626         if (!strcmp(tmp, "toggle")) {
627                 card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
628         } else if (!strcmp(tmp, "1")) {
629                 card->ipato.invert6 = 1;
630         } else if (!strcmp(tmp, "0")) {
631                 card->ipato.invert6 = 0;
632         } else {
633                 return -EINVAL;
634         }
635         return count;
636 }
637
638 static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
639                         qeth_l3_dev_ipato_invert6_show,
640                         qeth_l3_dev_ipato_invert6_store);
641
642
643 static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
644                                 struct device_attribute *attr, char *buf)
645 {
646         struct qeth_card *card = dev_get_drvdata(dev);
647
648         if (!card)
649                 return -EINVAL;
650
651         return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
652 }
653
654 static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
655                 struct device_attribute *attr, const char *buf, size_t count)
656 {
657         struct qeth_card *card = dev_get_drvdata(dev);
658
659         if (!card)
660                 return -EINVAL;
661
662         return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
663 }
664
665 static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
666                         qeth_l3_dev_ipato_add6_show,
667                         qeth_l3_dev_ipato_add6_store);
668
669 static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
670                 struct device_attribute *attr, const char *buf, size_t count)
671 {
672         struct qeth_card *card = dev_get_drvdata(dev);
673
674         if (!card)
675                 return -EINVAL;
676
677         return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
678 }
679
680 static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
681                         qeth_l3_dev_ipato_del6_store);
682
683 static struct attribute *qeth_ipato_device_attrs[] = {
684         &dev_attr_ipato_enable.attr,
685         &dev_attr_ipato_invert4.attr,
686         &dev_attr_ipato_add4.attr,
687         &dev_attr_ipato_del4.attr,
688         &dev_attr_ipato_invert6.attr,
689         &dev_attr_ipato_add6.attr,
690         &dev_attr_ipato_del6.attr,
691         NULL,
692 };
693
694 static struct attribute_group qeth_device_ipato_group = {
695         .name = "ipa_takeover",
696         .attrs = qeth_ipato_device_attrs,
697 };
698
699 static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
700                         enum qeth_prot_versions proto)
701 {
702         struct qeth_ipaddr *ipaddr;
703         char addr_str[40];
704         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
705         unsigned long flags;
706         int i = 0;
707
708         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
709         entry_len += 2; /* \n + terminator */
710         spin_lock_irqsave(&card->ip_lock, flags);
711         list_for_each_entry(ipaddr, &card->ip_list, entry) {
712                 if (ipaddr->proto != proto)
713                         continue;
714                 if (ipaddr->type != QETH_IP_TYPE_VIPA)
715                         continue;
716                 /* String must not be longer than PAGE_SIZE. So we check if
717                  * string length gets near PAGE_SIZE. Then we can savely display
718                  * the next IPv6 address (worst case, compared to IPv4) */
719                 if ((PAGE_SIZE - i) <= entry_len)
720                         break;
721                 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
722                         addr_str);
723                 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
724         }
725         spin_unlock_irqrestore(&card->ip_lock, flags);
726         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
727
728         return i;
729 }
730
731 static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
732                         struct device_attribute *attr, char *buf)
733 {
734         struct qeth_card *card = dev_get_drvdata(dev);
735
736         if (!card)
737                 return -EINVAL;
738
739         return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
740 }
741
742 static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
743                  u8 *addr)
744 {
745         if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
746                 return -EINVAL;
747         }
748         return 0;
749 }
750
751 static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
752                         struct qeth_card *card, enum qeth_prot_versions proto)
753 {
754         u8 addr[16] = {0, };
755         int rc;
756
757         rc = qeth_l3_parse_vipae(buf, proto, addr);
758         if (rc)
759                 return rc;
760
761         rc = qeth_l3_add_vipa(card, proto, addr);
762         if (rc)
763                 return rc;
764
765         return count;
766 }
767
768 static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
769                 struct device_attribute *attr, const char *buf, size_t count)
770 {
771         struct qeth_card *card = dev_get_drvdata(dev);
772
773         if (!card)
774                 return -EINVAL;
775
776         return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
777 }
778
779 static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
780                         qeth_l3_dev_vipa_add4_show,
781                         qeth_l3_dev_vipa_add4_store);
782
783 static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
784                          struct qeth_card *card, enum qeth_prot_versions proto)
785 {
786         u8 addr[16];
787         int rc;
788
789         rc = qeth_l3_parse_vipae(buf, proto, addr);
790         if (rc)
791                 return rc;
792
793         qeth_l3_del_vipa(card, proto, addr);
794
795         return count;
796 }
797
798 static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
799                 struct device_attribute *attr, const char *buf, size_t count)
800 {
801         struct qeth_card *card = dev_get_drvdata(dev);
802
803         if (!card)
804                 return -EINVAL;
805
806         return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
807 }
808
809 static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
810                         qeth_l3_dev_vipa_del4_store);
811
812 static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
813                                 struct device_attribute *attr, char *buf)
814 {
815         struct qeth_card *card = dev_get_drvdata(dev);
816
817         if (!card)
818                 return -EINVAL;
819
820         return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
821 }
822
823 static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
824                 struct device_attribute *attr, const char *buf, size_t count)
825 {
826         struct qeth_card *card = dev_get_drvdata(dev);
827
828         if (!card)
829                 return -EINVAL;
830
831         return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
832 }
833
834 static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
835                         qeth_l3_dev_vipa_add6_show,
836                         qeth_l3_dev_vipa_add6_store);
837
838 static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
839                 struct device_attribute *attr, const char *buf, size_t count)
840 {
841         struct qeth_card *card = dev_get_drvdata(dev);
842
843         if (!card)
844                 return -EINVAL;
845
846         return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
847 }
848
849 static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
850                         qeth_l3_dev_vipa_del6_store);
851
852 static struct attribute *qeth_vipa_device_attrs[] = {
853         &dev_attr_vipa_add4.attr,
854         &dev_attr_vipa_del4.attr,
855         &dev_attr_vipa_add6.attr,
856         &dev_attr_vipa_del6.attr,
857         NULL,
858 };
859
860 static struct attribute_group qeth_device_vipa_group = {
861         .name = "vipa",
862         .attrs = qeth_vipa_device_attrs,
863 };
864
865 static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
866                        enum qeth_prot_versions proto)
867 {
868         struct qeth_ipaddr *ipaddr;
869         char addr_str[40];
870         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
871         unsigned long flags;
872         int i = 0;
873
874         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
875         entry_len += 2; /* \n + terminator */
876         spin_lock_irqsave(&card->ip_lock, flags);
877         list_for_each_entry(ipaddr, &card->ip_list, entry) {
878                 if (ipaddr->proto != proto)
879                         continue;
880                 if (ipaddr->type != QETH_IP_TYPE_RXIP)
881                         continue;
882                 /* String must not be longer than PAGE_SIZE. So we check if
883                  * string length gets near PAGE_SIZE. Then we can savely display
884                  * the next IPv6 address (worst case, compared to IPv4) */
885                 if ((PAGE_SIZE - i) <= entry_len)
886                         break;
887                 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
888                         addr_str);
889                 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
890         }
891         spin_unlock_irqrestore(&card->ip_lock, flags);
892         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
893
894         return i;
895 }
896
897 static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
898                         struct device_attribute *attr, char *buf)
899 {
900         struct qeth_card *card = dev_get_drvdata(dev);
901
902         if (!card)
903                 return -EINVAL;
904
905         return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
906 }
907
908 static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
909                  u8 *addr)
910 {
911         if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
912                 return -EINVAL;
913         }
914         return 0;
915 }
916
917 static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
918                         struct qeth_card *card, enum qeth_prot_versions proto)
919 {
920         u8 addr[16] = {0, };
921         int rc;
922
923         rc = qeth_l3_parse_rxipe(buf, proto, addr);
924         if (rc)
925                 return rc;
926
927         rc = qeth_l3_add_rxip(card, proto, addr);
928         if (rc)
929                 return rc;
930
931         return count;
932 }
933
934 static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
935                 struct device_attribute *attr, const char *buf, size_t count)
936 {
937         struct qeth_card *card = dev_get_drvdata(dev);
938
939         if (!card)
940                 return -EINVAL;
941
942         return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
943 }
944
945 static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
946                         qeth_l3_dev_rxip_add4_show,
947                         qeth_l3_dev_rxip_add4_store);
948
949 static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
950                         struct qeth_card *card, enum qeth_prot_versions proto)
951 {
952         u8 addr[16];
953         int rc;
954
955         rc = qeth_l3_parse_rxipe(buf, proto, addr);
956         if (rc)
957                 return rc;
958
959         qeth_l3_del_rxip(card, proto, addr);
960
961         return count;
962 }
963
964 static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
965                 struct device_attribute *attr, const char *buf, size_t count)
966 {
967         struct qeth_card *card = dev_get_drvdata(dev);
968
969         if (!card)
970                 return -EINVAL;
971
972         return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
973 }
974
975 static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
976                         qeth_l3_dev_rxip_del4_store);
977
978 static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
979                 struct device_attribute *attr, char *buf)
980 {
981         struct qeth_card *card = dev_get_drvdata(dev);
982
983         if (!card)
984                 return -EINVAL;
985
986         return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
987 }
988
989 static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
990                 struct device_attribute *attr, const char *buf, size_t count)
991 {
992         struct qeth_card *card = dev_get_drvdata(dev);
993
994         if (!card)
995                 return -EINVAL;
996
997         return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
998 }
999
1000 static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
1001                         qeth_l3_dev_rxip_add6_show,
1002                         qeth_l3_dev_rxip_add6_store);
1003
1004 static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
1005                 struct device_attribute *attr, const char *buf, size_t count)
1006 {
1007         struct qeth_card *card = dev_get_drvdata(dev);
1008
1009         if (!card)
1010                 return -EINVAL;
1011
1012         return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
1013 }
1014
1015 static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
1016                         qeth_l3_dev_rxip_del6_store);
1017
1018 static struct attribute *qeth_rxip_device_attrs[] = {
1019         &dev_attr_rxip_add4.attr,
1020         &dev_attr_rxip_del4.attr,
1021         &dev_attr_rxip_add6.attr,
1022         &dev_attr_rxip_del6.attr,
1023         NULL,
1024 };
1025
1026 static struct attribute_group qeth_device_rxip_group = {
1027         .name = "rxip",
1028         .attrs = qeth_rxip_device_attrs,
1029 };
1030
1031 int qeth_l3_create_device_attributes(struct device *dev)
1032 {
1033         int ret;
1034
1035         ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
1036         if (ret)
1037                 return ret;
1038
1039         ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
1040         if (ret) {
1041                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1042                 return ret;
1043         }
1044
1045         ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
1046         if (ret) {
1047                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1048                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1049                 return ret;
1050         }
1051
1052         ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
1053         if (ret) {
1054                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1055                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1056                 sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1057                 return ret;
1058         }
1059         return 0;
1060 }
1061
1062 void qeth_l3_remove_device_attributes(struct device *dev)
1063 {
1064         sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1065         sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1066         sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1067         sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
1068 }