[S390] qdio: optimize cache line usage of struct qdio_irq
[safe/jmp/linux-2.6] / 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         enum qeth_checksum_types csum_type;
297         char *tmp;
298         int rc;
299
300         if (!card)
301                 return -EINVAL;
302
303         tmp = strsep((char **) &buf, "\n");
304         if (!strcmp(tmp, "sw_checksumming"))
305                 csum_type = SW_CHECKSUMMING;
306         else if (!strcmp(tmp, "hw_checksumming"))
307                 csum_type = HW_CHECKSUMMING;
308         else if (!strcmp(tmp, "no_checksumming"))
309                 csum_type = NO_CHECKSUMMING;
310         else
311                 return -EINVAL;
312
313         rc = qeth_l3_set_rx_csum(card, csum_type);
314         if (rc)
315                 return rc;
316         return count;
317 }
318
319 static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
320                 qeth_l3_dev_checksum_store);
321
322 static ssize_t qeth_l3_dev_large_send_show(struct device *dev,
323                                 struct device_attribute *attr, char *buf)
324 {
325         struct qeth_card *card = dev_get_drvdata(dev);
326
327         if (!card)
328                 return -EINVAL;
329
330         switch (card->options.large_send) {
331         case QETH_LARGE_SEND_NO:
332                 return sprintf(buf, "%s\n", "no");
333         case QETH_LARGE_SEND_TSO:
334                 return sprintf(buf, "%s\n", "TSO");
335         default:
336                 return sprintf(buf, "%s\n", "N/A");
337         }
338 }
339
340 static ssize_t qeth_l3_dev_large_send_store(struct device *dev,
341                 struct device_attribute *attr, const char *buf, size_t count)
342 {
343         struct qeth_card *card = dev_get_drvdata(dev);
344         enum qeth_large_send_types type;
345         int rc = 0;
346         char *tmp;
347
348         if (!card)
349                 return -EINVAL;
350         tmp = strsep((char **) &buf, "\n");
351         if (!strcmp(tmp, "no"))
352                 type = QETH_LARGE_SEND_NO;
353         else if (!strcmp(tmp, "TSO"))
354                 type = QETH_LARGE_SEND_TSO;
355         else
356                 return -EINVAL;
357
358         if (card->options.large_send == type)
359                 return count;
360         rc = qeth_l3_set_large_send(card, type);
361         if (rc)
362                 return rc;
363         return count;
364 }
365
366 static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
367                    qeth_l3_dev_large_send_store);
368
369 static struct attribute *qeth_l3_device_attrs[] = {
370         &dev_attr_route4.attr,
371         &dev_attr_route6.attr,
372         &dev_attr_fake_broadcast.attr,
373         &dev_attr_broadcast_mode.attr,
374         &dev_attr_canonical_macaddr.attr,
375         &dev_attr_checksumming.attr,
376         &dev_attr_large_send.attr,
377         NULL,
378 };
379
380 static struct attribute_group qeth_l3_device_attr_group = {
381         .attrs = qeth_l3_device_attrs,
382 };
383
384 static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
385                         struct device_attribute *attr, char *buf)
386 {
387         struct qeth_card *card = dev_get_drvdata(dev);
388
389         if (!card)
390                 return -EINVAL;
391
392         return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
393 }
394
395 static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
396                 struct device_attribute *attr, const char *buf, size_t count)
397 {
398         struct qeth_card *card = dev_get_drvdata(dev);
399         char *tmp;
400
401         if (!card)
402                 return -EINVAL;
403
404         if ((card->state != CARD_STATE_DOWN) &&
405             (card->state != CARD_STATE_RECOVER))
406                 return -EPERM;
407
408         tmp = strsep((char **) &buf, "\n");
409         if (!strcmp(tmp, "toggle")) {
410                 card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
411         } else if (!strcmp(tmp, "1")) {
412                 card->ipato.enabled = 1;
413         } else if (!strcmp(tmp, "0")) {
414                 card->ipato.enabled = 0;
415         } else {
416                 return -EINVAL;
417         }
418         return count;
419 }
420
421 static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
422                         qeth_l3_dev_ipato_enable_show,
423                         qeth_l3_dev_ipato_enable_store);
424
425 static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
426                                 struct device_attribute *attr, char *buf)
427 {
428         struct qeth_card *card = dev_get_drvdata(dev);
429
430         if (!card)
431                 return -EINVAL;
432
433         return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
434 }
435
436 static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
437                                 struct device_attribute *attr,
438                                 const char *buf, size_t count)
439 {
440         struct qeth_card *card = dev_get_drvdata(dev);
441         char *tmp;
442
443         if (!card)
444                 return -EINVAL;
445
446         tmp = strsep((char **) &buf, "\n");
447         if (!strcmp(tmp, "toggle")) {
448                 card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
449         } else if (!strcmp(tmp, "1")) {
450                 card->ipato.invert4 = 1;
451         } else if (!strcmp(tmp, "0")) {
452                 card->ipato.invert4 = 0;
453         } else {
454                 return -EINVAL;
455         }
456         return count;
457 }
458
459 static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
460                         qeth_l3_dev_ipato_invert4_show,
461                         qeth_l3_dev_ipato_invert4_store);
462
463 static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
464                         enum qeth_prot_versions proto)
465 {
466         struct qeth_ipato_entry *ipatoe;
467         unsigned long flags;
468         char addr_str[40];
469         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
470         int i = 0;
471
472         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
473         /* add strlen for "/<mask>\n" */
474         entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
475         spin_lock_irqsave(&card->ip_lock, flags);
476         list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
477                 if (ipatoe->proto != proto)
478                         continue;
479                 /* String must not be longer than PAGE_SIZE. So we check if
480                  * string length gets near PAGE_SIZE. Then we can savely display
481                  * the next IPv6 address (worst case, compared to IPv4) */
482                 if ((PAGE_SIZE - i) <= entry_len)
483                         break;
484                 qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
485                 i += snprintf(buf + i, PAGE_SIZE - i,
486                               "%s/%i\n", addr_str, ipatoe->mask_bits);
487         }
488         spin_unlock_irqrestore(&card->ip_lock, flags);
489         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
490
491         return i;
492 }
493
494 static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
495                                 struct device_attribute *attr, char *buf)
496 {
497         struct qeth_card *card = dev_get_drvdata(dev);
498
499         if (!card)
500                 return -EINVAL;
501
502         return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
503 }
504
505 static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
506                   u8 *addr, int *mask_bits)
507 {
508         const char *start, *end;
509         char *tmp;
510         char buffer[40] = {0, };
511
512         start = buf;
513         /* get address string */
514         end = strchr(start, '/');
515         if (!end || (end - start >= 40)) {
516                 return -EINVAL;
517         }
518         strncpy(buffer, start, end - start);
519         if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
520                 return -EINVAL;
521         }
522         start = end + 1;
523         *mask_bits = simple_strtoul(start, &tmp, 10);
524         if (!strlen(start) ||
525             (tmp == start) ||
526             (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
527                 return -EINVAL;
528         }
529         return 0;
530 }
531
532 static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
533                          struct qeth_card *card, enum qeth_prot_versions proto)
534 {
535         struct qeth_ipato_entry *ipatoe;
536         u8 addr[16];
537         int mask_bits;
538         int rc;
539
540         rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
541         if (rc)
542                 return rc;
543
544         ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
545         if (!ipatoe) {
546                 return -ENOMEM;
547         }
548         ipatoe->proto = proto;
549         memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
550         ipatoe->mask_bits = mask_bits;
551
552         rc = qeth_l3_add_ipato_entry(card, ipatoe);
553         if (rc) {
554                 kfree(ipatoe);
555                 return rc;
556         }
557
558         return count;
559 }
560
561 static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
562                 struct device_attribute *attr, const char *buf, size_t count)
563 {
564         struct qeth_card *card = dev_get_drvdata(dev);
565
566         if (!card)
567                 return -EINVAL;
568
569         return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
570 }
571
572 static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
573                         qeth_l3_dev_ipato_add4_show,
574                         qeth_l3_dev_ipato_add4_store);
575
576 static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
577                          struct qeth_card *card, enum qeth_prot_versions proto)
578 {
579         u8 addr[16];
580         int mask_bits;
581         int rc;
582
583         rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
584         if (rc)
585                 return rc;
586
587         qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
588
589         return count;
590 }
591
592 static ssize_t qeth_l3_dev_ipato_del4_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
597         if (!card)
598                 return -EINVAL;
599
600         return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
601 }
602
603 static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
604                         qeth_l3_dev_ipato_del4_store);
605
606 static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
607                 struct device_attribute *attr, char *buf)
608 {
609         struct qeth_card *card = dev_get_drvdata(dev);
610
611         if (!card)
612                 return -EINVAL;
613
614         return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
615 }
616
617 static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
618                 struct device_attribute *attr, const char *buf, size_t count)
619 {
620         struct qeth_card *card = dev_get_drvdata(dev);
621         char *tmp;
622
623         if (!card)
624                 return -EINVAL;
625
626         tmp = strsep((char **) &buf, "\n");
627         if (!strcmp(tmp, "toggle")) {
628                 card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
629         } else if (!strcmp(tmp, "1")) {
630                 card->ipato.invert6 = 1;
631         } else if (!strcmp(tmp, "0")) {
632                 card->ipato.invert6 = 0;
633         } else {
634                 return -EINVAL;
635         }
636         return count;
637 }
638
639 static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
640                         qeth_l3_dev_ipato_invert6_show,
641                         qeth_l3_dev_ipato_invert6_store);
642
643
644 static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
645                                 struct device_attribute *attr, char *buf)
646 {
647         struct qeth_card *card = dev_get_drvdata(dev);
648
649         if (!card)
650                 return -EINVAL;
651
652         return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
653 }
654
655 static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
656                 struct device_attribute *attr, const char *buf, size_t count)
657 {
658         struct qeth_card *card = dev_get_drvdata(dev);
659
660         if (!card)
661                 return -EINVAL;
662
663         return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
664 }
665
666 static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
667                         qeth_l3_dev_ipato_add6_show,
668                         qeth_l3_dev_ipato_add6_store);
669
670 static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
671                 struct device_attribute *attr, const char *buf, size_t count)
672 {
673         struct qeth_card *card = dev_get_drvdata(dev);
674
675         if (!card)
676                 return -EINVAL;
677
678         return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
679 }
680
681 static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
682                         qeth_l3_dev_ipato_del6_store);
683
684 static struct attribute *qeth_ipato_device_attrs[] = {
685         &dev_attr_ipato_enable.attr,
686         &dev_attr_ipato_invert4.attr,
687         &dev_attr_ipato_add4.attr,
688         &dev_attr_ipato_del4.attr,
689         &dev_attr_ipato_invert6.attr,
690         &dev_attr_ipato_add6.attr,
691         &dev_attr_ipato_del6.attr,
692         NULL,
693 };
694
695 static struct attribute_group qeth_device_ipato_group = {
696         .name = "ipa_takeover",
697         .attrs = qeth_ipato_device_attrs,
698 };
699
700 static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
701                         enum qeth_prot_versions proto)
702 {
703         struct qeth_ipaddr *ipaddr;
704         char addr_str[40];
705         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
706         unsigned long flags;
707         int i = 0;
708
709         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
710         entry_len += 2; /* \n + terminator */
711         spin_lock_irqsave(&card->ip_lock, flags);
712         list_for_each_entry(ipaddr, &card->ip_list, entry) {
713                 if (ipaddr->proto != proto)
714                         continue;
715                 if (ipaddr->type != QETH_IP_TYPE_VIPA)
716                         continue;
717                 /* String must not be longer than PAGE_SIZE. So we check if
718                  * string length gets near PAGE_SIZE. Then we can savely display
719                  * the next IPv6 address (worst case, compared to IPv4) */
720                 if ((PAGE_SIZE - i) <= entry_len)
721                         break;
722                 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
723                         addr_str);
724                 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
725         }
726         spin_unlock_irqrestore(&card->ip_lock, flags);
727         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
728
729         return i;
730 }
731
732 static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
733                         struct device_attribute *attr, char *buf)
734 {
735         struct qeth_card *card = dev_get_drvdata(dev);
736
737         if (!card)
738                 return -EINVAL;
739
740         return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
741 }
742
743 static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
744                  u8 *addr)
745 {
746         if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
747                 return -EINVAL;
748         }
749         return 0;
750 }
751
752 static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
753                         struct qeth_card *card, enum qeth_prot_versions proto)
754 {
755         u8 addr[16] = {0, };
756         int rc;
757
758         rc = qeth_l3_parse_vipae(buf, proto, addr);
759         if (rc)
760                 return rc;
761
762         rc = qeth_l3_add_vipa(card, proto, addr);
763         if (rc)
764                 return rc;
765
766         return count;
767 }
768
769 static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
770                 struct device_attribute *attr, const char *buf, size_t count)
771 {
772         struct qeth_card *card = dev_get_drvdata(dev);
773
774         if (!card)
775                 return -EINVAL;
776
777         return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
778 }
779
780 static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
781                         qeth_l3_dev_vipa_add4_show,
782                         qeth_l3_dev_vipa_add4_store);
783
784 static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
785                          struct qeth_card *card, enum qeth_prot_versions proto)
786 {
787         u8 addr[16];
788         int rc;
789
790         rc = qeth_l3_parse_vipae(buf, proto, addr);
791         if (rc)
792                 return rc;
793
794         qeth_l3_del_vipa(card, proto, addr);
795
796         return count;
797 }
798
799 static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
800                 struct device_attribute *attr, const char *buf, size_t count)
801 {
802         struct qeth_card *card = dev_get_drvdata(dev);
803
804         if (!card)
805                 return -EINVAL;
806
807         return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
808 }
809
810 static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
811                         qeth_l3_dev_vipa_del4_store);
812
813 static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
814                                 struct device_attribute *attr, char *buf)
815 {
816         struct qeth_card *card = dev_get_drvdata(dev);
817
818         if (!card)
819                 return -EINVAL;
820
821         return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
822 }
823
824 static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
825                 struct device_attribute *attr, const char *buf, size_t count)
826 {
827         struct qeth_card *card = dev_get_drvdata(dev);
828
829         if (!card)
830                 return -EINVAL;
831
832         return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
833 }
834
835 static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
836                         qeth_l3_dev_vipa_add6_show,
837                         qeth_l3_dev_vipa_add6_store);
838
839 static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
840                 struct device_attribute *attr, const char *buf, size_t count)
841 {
842         struct qeth_card *card = dev_get_drvdata(dev);
843
844         if (!card)
845                 return -EINVAL;
846
847         return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
848 }
849
850 static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
851                         qeth_l3_dev_vipa_del6_store);
852
853 static struct attribute *qeth_vipa_device_attrs[] = {
854         &dev_attr_vipa_add4.attr,
855         &dev_attr_vipa_del4.attr,
856         &dev_attr_vipa_add6.attr,
857         &dev_attr_vipa_del6.attr,
858         NULL,
859 };
860
861 static struct attribute_group qeth_device_vipa_group = {
862         .name = "vipa",
863         .attrs = qeth_vipa_device_attrs,
864 };
865
866 static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
867                        enum qeth_prot_versions proto)
868 {
869         struct qeth_ipaddr *ipaddr;
870         char addr_str[40];
871         int entry_len; /* length of 1 entry string, differs between v4 and v6 */
872         unsigned long flags;
873         int i = 0;
874
875         entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
876         entry_len += 2; /* \n + terminator */
877         spin_lock_irqsave(&card->ip_lock, flags);
878         list_for_each_entry(ipaddr, &card->ip_list, entry) {
879                 if (ipaddr->proto != proto)
880                         continue;
881                 if (ipaddr->type != QETH_IP_TYPE_RXIP)
882                         continue;
883                 /* String must not be longer than PAGE_SIZE. So we check if
884                  * string length gets near PAGE_SIZE. Then we can savely display
885                  * the next IPv6 address (worst case, compared to IPv4) */
886                 if ((PAGE_SIZE - i) <= entry_len)
887                         break;
888                 qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
889                         addr_str);
890                 i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
891         }
892         spin_unlock_irqrestore(&card->ip_lock, flags);
893         i += snprintf(buf + i, PAGE_SIZE - i, "\n");
894
895         return i;
896 }
897
898 static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
899                         struct device_attribute *attr, char *buf)
900 {
901         struct qeth_card *card = dev_get_drvdata(dev);
902
903         if (!card)
904                 return -EINVAL;
905
906         return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
907 }
908
909 static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
910                  u8 *addr)
911 {
912         if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
913                 return -EINVAL;
914         }
915         return 0;
916 }
917
918 static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
919                         struct qeth_card *card, enum qeth_prot_versions proto)
920 {
921         u8 addr[16] = {0, };
922         int rc;
923
924         rc = qeth_l3_parse_rxipe(buf, proto, addr);
925         if (rc)
926                 return rc;
927
928         rc = qeth_l3_add_rxip(card, proto, addr);
929         if (rc)
930                 return rc;
931
932         return count;
933 }
934
935 static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
936                 struct device_attribute *attr, const char *buf, size_t count)
937 {
938         struct qeth_card *card = dev_get_drvdata(dev);
939
940         if (!card)
941                 return -EINVAL;
942
943         return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
944 }
945
946 static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
947                         qeth_l3_dev_rxip_add4_show,
948                         qeth_l3_dev_rxip_add4_store);
949
950 static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
951                         struct qeth_card *card, enum qeth_prot_versions proto)
952 {
953         u8 addr[16];
954         int rc;
955
956         rc = qeth_l3_parse_rxipe(buf, proto, addr);
957         if (rc)
958                 return rc;
959
960         qeth_l3_del_rxip(card, proto, addr);
961
962         return count;
963 }
964
965 static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
966                 struct device_attribute *attr, const char *buf, size_t count)
967 {
968         struct qeth_card *card = dev_get_drvdata(dev);
969
970         if (!card)
971                 return -EINVAL;
972
973         return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
974 }
975
976 static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
977                         qeth_l3_dev_rxip_del4_store);
978
979 static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
980                 struct device_attribute *attr, char *buf)
981 {
982         struct qeth_card *card = dev_get_drvdata(dev);
983
984         if (!card)
985                 return -EINVAL;
986
987         return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
988 }
989
990 static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
991                 struct device_attribute *attr, const char *buf, size_t count)
992 {
993         struct qeth_card *card = dev_get_drvdata(dev);
994
995         if (!card)
996                 return -EINVAL;
997
998         return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
999 }
1000
1001 static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
1002                         qeth_l3_dev_rxip_add6_show,
1003                         qeth_l3_dev_rxip_add6_store);
1004
1005 static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
1006                 struct device_attribute *attr, const char *buf, size_t count)
1007 {
1008         struct qeth_card *card = dev_get_drvdata(dev);
1009
1010         if (!card)
1011                 return -EINVAL;
1012
1013         return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
1014 }
1015
1016 static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
1017                         qeth_l3_dev_rxip_del6_store);
1018
1019 static struct attribute *qeth_rxip_device_attrs[] = {
1020         &dev_attr_rxip_add4.attr,
1021         &dev_attr_rxip_del4.attr,
1022         &dev_attr_rxip_add6.attr,
1023         &dev_attr_rxip_del6.attr,
1024         NULL,
1025 };
1026
1027 static struct attribute_group qeth_device_rxip_group = {
1028         .name = "rxip",
1029         .attrs = qeth_rxip_device_attrs,
1030 };
1031
1032 int qeth_l3_create_device_attributes(struct device *dev)
1033 {
1034         int ret;
1035
1036         ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
1037         if (ret)
1038                 return ret;
1039
1040         ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
1041         if (ret) {
1042                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1043                 return ret;
1044         }
1045
1046         ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
1047         if (ret) {
1048                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1049                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1050                 return ret;
1051         }
1052
1053         ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
1054         if (ret) {
1055                 sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1056                 sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1057                 sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1058                 return ret;
1059         }
1060         return 0;
1061 }
1062
1063 void qeth_l3_remove_device_attributes(struct device *dev)
1064 {
1065         sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
1066         sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
1067         sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
1068         sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
1069 }