Merge branches 'slab/fixes', 'slab/kmemleak', 'slub/perf' and 'slub/stats' into for...
[linux-2.6-block.git] / drivers / s390 / net / qeth_core_sys.c
CommitLineData
4a71df50
FB
1/*
2 * drivers/s390/net/qeth_core_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 <linux/list.h>
12#include <linux/rwsem.h>
13#include <asm/ebcdic.h>
14
15#include "qeth_core.h"
16
17static ssize_t qeth_dev_state_show(struct device *dev,
18 struct device_attribute *attr, char *buf)
19{
20 struct qeth_card *card = dev_get_drvdata(dev);
21 if (!card)
22 return -EINVAL;
23
24 switch (card->state) {
25 case CARD_STATE_DOWN:
26 return sprintf(buf, "DOWN\n");
27 case CARD_STATE_HARDSETUP:
28 return sprintf(buf, "HARDSETUP\n");
29 case CARD_STATE_SOFTSETUP:
30 return sprintf(buf, "SOFTSETUP\n");
31 case CARD_STATE_UP:
32 if (card->lan_online)
33 return sprintf(buf, "UP (LAN ONLINE)\n");
34 else
35 return sprintf(buf, "UP (LAN OFFLINE)\n");
36 case CARD_STATE_RECOVER:
37 return sprintf(buf, "RECOVER\n");
38 default:
39 return sprintf(buf, "UNKNOWN\n");
40 }
41}
42
43static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
44
45static ssize_t qeth_dev_chpid_show(struct device *dev,
46 struct device_attribute *attr, char *buf)
47{
48 struct qeth_card *card = dev_get_drvdata(dev);
49 if (!card)
50 return -EINVAL;
51
52 return sprintf(buf, "%02X\n", card->info.chpid);
53}
54
55static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
56
57static ssize_t qeth_dev_if_name_show(struct device *dev,
58 struct device_attribute *attr, char *buf)
59{
60 struct qeth_card *card = dev_get_drvdata(dev);
61 if (!card)
62 return -EINVAL;
63 return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
64}
65
66static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
67
68static ssize_t qeth_dev_card_type_show(struct device *dev,
69 struct device_attribute *attr, char *buf)
70{
71 struct qeth_card *card = dev_get_drvdata(dev);
72 if (!card)
73 return -EINVAL;
74
75 return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
76}
77
78static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
79
80static inline const char *qeth_get_bufsize_str(struct qeth_card *card)
81{
82 if (card->qdio.in_buf_size == 16384)
83 return "16k";
84 else if (card->qdio.in_buf_size == 24576)
85 return "24k";
86 else if (card->qdio.in_buf_size == 32768)
87 return "32k";
88 else if (card->qdio.in_buf_size == 40960)
89 return "40k";
90 else
91 return "64k";
92}
93
94static ssize_t qeth_dev_inbuf_size_show(struct device *dev,
95 struct device_attribute *attr, char *buf)
96{
97 struct qeth_card *card = dev_get_drvdata(dev);
98 if (!card)
99 return -EINVAL;
100
101 return sprintf(buf, "%s\n", qeth_get_bufsize_str(card));
102}
103
104static DEVICE_ATTR(inbuf_size, 0444, qeth_dev_inbuf_size_show, NULL);
105
106static ssize_t qeth_dev_portno_show(struct device *dev,
107 struct device_attribute *attr, char *buf)
108{
109 struct qeth_card *card = dev_get_drvdata(dev);
110 if (!card)
111 return -EINVAL;
112
113 return sprintf(buf, "%i\n", card->info.portno);
114}
115
116static ssize_t qeth_dev_portno_store(struct device *dev,
117 struct device_attribute *attr, const char *buf, size_t count)
118{
119 struct qeth_card *card = dev_get_drvdata(dev);
120 char *tmp;
121 unsigned int portno;
122
123 if (!card)
124 return -EINVAL;
125
126 if ((card->state != CARD_STATE_DOWN) &&
127 (card->state != CARD_STATE_RECOVER))
128 return -EPERM;
129
130 portno = simple_strtoul(buf, &tmp, 16);
131 if (portno > QETH_MAX_PORTNO) {
4a71df50
FB
132 return -EINVAL;
133 }
134
135 card->info.portno = portno;
136 return count;
137}
138
139static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
140
141static ssize_t qeth_dev_portname_show(struct device *dev,
142 struct device_attribute *attr, char *buf)
143{
144 struct qeth_card *card = dev_get_drvdata(dev);
145 char portname[9] = {0, };
146
147 if (!card)
148 return -EINVAL;
149
150 if (card->info.portname_required) {
151 memcpy(portname, card->info.portname + 1, 8);
152 EBCASC(portname, 8);
153 return sprintf(buf, "%s\n", portname);
154 } else
155 return sprintf(buf, "no portname required\n");
156}
157
158static ssize_t qeth_dev_portname_store(struct device *dev,
159 struct device_attribute *attr, const char *buf, size_t count)
160{
161 struct qeth_card *card = dev_get_drvdata(dev);
162 char *tmp;
163 int i;
164
165 if (!card)
166 return -EINVAL;
167
168 if ((card->state != CARD_STATE_DOWN) &&
169 (card->state != CARD_STATE_RECOVER))
170 return -EPERM;
171
172 tmp = strsep((char **) &buf, "\n");
173 if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
174 return -EINVAL;
175
176 card->info.portname[0] = strlen(tmp);
177 /* for beauty reasons */
178 for (i = 1; i < 9; i++)
179 card->info.portname[i] = ' ';
180 strcpy(card->info.portname + 1, tmp);
181 ASCEBC(card->info.portname + 1, 8);
182
183 return count;
184}
185
186static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
187 qeth_dev_portname_store);
188
189static ssize_t qeth_dev_prioqing_show(struct device *dev,
190 struct device_attribute *attr, char *buf)
191{
192 struct qeth_card *card = dev_get_drvdata(dev);
193
194 if (!card)
195 return -EINVAL;
196
197 switch (card->qdio.do_prio_queueing) {
198 case QETH_PRIO_Q_ING_PREC:
199 return sprintf(buf, "%s\n", "by precedence");
200 case QETH_PRIO_Q_ING_TOS:
201 return sprintf(buf, "%s\n", "by type of service");
202 default:
203 return sprintf(buf, "always queue %i\n",
204 card->qdio.default_out_queue);
205 }
206}
207
208static ssize_t qeth_dev_prioqing_store(struct device *dev,
209 struct device_attribute *attr, const char *buf, size_t count)
210{
211 struct qeth_card *card = dev_get_drvdata(dev);
212 char *tmp;
213
214 if (!card)
215 return -EINVAL;
216
217 if ((card->state != CARD_STATE_DOWN) &&
218 (card->state != CARD_STATE_RECOVER))
219 return -EPERM;
220
221 /* check if 1920 devices are supported ,
222 * if though we have to permit priority queueing
223 */
224 if (card->qdio.no_out_queues == 1) {
4a71df50
FB
225 card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
226 return -EPERM;
227 }
228
229 tmp = strsep((char **) &buf, "\n");
230 if (!strcmp(tmp, "prio_queueing_prec"))
231 card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
232 else if (!strcmp(tmp, "prio_queueing_tos"))
233 card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
234 else if (!strcmp(tmp, "no_prio_queueing:0")) {
235 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
236 card->qdio.default_out_queue = 0;
237 } else if (!strcmp(tmp, "no_prio_queueing:1")) {
238 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
239 card->qdio.default_out_queue = 1;
240 } else if (!strcmp(tmp, "no_prio_queueing:2")) {
241 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
242 card->qdio.default_out_queue = 2;
243 } else if (!strcmp(tmp, "no_prio_queueing:3")) {
244 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
245 card->qdio.default_out_queue = 3;
246 } else if (!strcmp(tmp, "no_prio_queueing")) {
247 card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
248 card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
249 } else {
4a71df50
FB
250 return -EINVAL;
251 }
252 return count;
253}
254
255static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
256 qeth_dev_prioqing_store);
257
258static ssize_t qeth_dev_bufcnt_show(struct device *dev,
259 struct device_attribute *attr, char *buf)
260{
261 struct qeth_card *card = dev_get_drvdata(dev);
262
263 if (!card)
264 return -EINVAL;
265
266 return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
267}
268
269static ssize_t qeth_dev_bufcnt_store(struct device *dev,
270 struct device_attribute *attr, const char *buf, size_t count)
271{
272 struct qeth_card *card = dev_get_drvdata(dev);
273 char *tmp;
274 int cnt, old_cnt;
275 int rc;
276
277 if (!card)
278 return -EINVAL;
279
280 if ((card->state != CARD_STATE_DOWN) &&
281 (card->state != CARD_STATE_RECOVER))
282 return -EPERM;
283
284 old_cnt = card->qdio.in_buf_pool.buf_count;
285 cnt = simple_strtoul(buf, &tmp, 10);
286 cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
287 ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
288 if (old_cnt != cnt) {
289 rc = qeth_realloc_buffer_pool(card, cnt);
4a71df50
FB
290 }
291 return count;
292}
293
294static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
295 qeth_dev_bufcnt_store);
296
297static ssize_t qeth_dev_recover_store(struct device *dev,
298 struct device_attribute *attr, const char *buf, size_t count)
299{
300 struct qeth_card *card = dev_get_drvdata(dev);
301 char *tmp;
302 int i;
303
304 if (!card)
305 return -EINVAL;
306
307 if (card->state != CARD_STATE_UP)
308 return -EPERM;
309
310 i = simple_strtoul(buf, &tmp, 16);
311 if (i == 1)
312 qeth_schedule_recovery(card);
313
314 return count;
315}
316
317static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
318
319static ssize_t qeth_dev_performance_stats_show(struct device *dev,
320 struct device_attribute *attr, char *buf)
321{
322 struct qeth_card *card = dev_get_drvdata(dev);
323
324 if (!card)
325 return -EINVAL;
326
327 return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
328}
329
330static ssize_t qeth_dev_performance_stats_store(struct device *dev,
331 struct device_attribute *attr, const char *buf, size_t count)
332{
333 struct qeth_card *card = dev_get_drvdata(dev);
334 char *tmp;
335 int i;
336
337 if (!card)
338 return -EINVAL;
339
340 i = simple_strtoul(buf, &tmp, 16);
341 if ((i == 0) || (i == 1)) {
342 if (i == card->options.performance_stats)
343 return count;
344 card->options.performance_stats = i;
345 if (i == 0)
346 memset(&card->perf_stats, 0,
347 sizeof(struct qeth_perf_stats));
348 card->perf_stats.initial_rx_packets = card->stats.rx_packets;
349 card->perf_stats.initial_tx_packets = card->stats.tx_packets;
350 } else {
4a71df50
FB
351 return -EINVAL;
352 }
353 return count;
354}
355
356static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
357 qeth_dev_performance_stats_store);
358
359static ssize_t qeth_dev_layer2_show(struct device *dev,
360 struct device_attribute *attr, char *buf)
361{
362 struct qeth_card *card = dev_get_drvdata(dev);
363
364 if (!card)
365 return -EINVAL;
366
7c6a3ed5 367 return sprintf(buf, "%i\n", card->options.layer2);
4a71df50
FB
368}
369
370static ssize_t qeth_dev_layer2_store(struct device *dev,
371 struct device_attribute *attr, const char *buf, size_t count)
372{
373 struct qeth_card *card = dev_get_drvdata(dev);
374 char *tmp;
375 int i, rc;
376 enum qeth_discipline_id newdis;
377
378 if (!card)
379 return -EINVAL;
380
381 if (((card->state != CARD_STATE_DOWN) &&
382 (card->state != CARD_STATE_RECOVER)))
383 return -EPERM;
384
385 i = simple_strtoul(buf, &tmp, 16);
386 switch (i) {
387 case 0:
388 newdis = QETH_DISCIPLINE_LAYER3;
389 break;
390 case 1:
391 newdis = QETH_DISCIPLINE_LAYER2;
392 break;
393 default:
4a71df50
FB
394 return -EINVAL;
395 }
396
397 if (card->options.layer2 == newdis) {
398 return count;
399 } else {
400 if (card->discipline.ccwgdriver) {
401 card->discipline.ccwgdriver->remove(card->gdev);
402 qeth_core_free_discipline(card);
403 }
404 }
405
406 rc = qeth_core_load_discipline(card, newdis);
407 if (rc)
408 return rc;
409
410 rc = card->discipline.ccwgdriver->probe(card->gdev);
411 if (rc)
412 return rc;
413 return count;
414}
415
416static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
417 qeth_dev_layer2_store);
418
d64ecc22
EL
419#define ATTR_QETH_ISOLATION_NONE ("none")
420#define ATTR_QETH_ISOLATION_FWD ("forward")
421#define ATTR_QETH_ISOLATION_DROP ("drop")
422
423static ssize_t qeth_dev_isolation_show(struct device *dev,
424 struct device_attribute *attr, char *buf)
425{
426 struct qeth_card *card = dev_get_drvdata(dev);
427
428 if (!card)
429 return -EINVAL;
430
431 switch (card->options.isolation) {
432 case ISOLATION_MODE_NONE:
433 return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_NONE);
434 case ISOLATION_MODE_FWD:
435 return snprintf(buf, 9, "%s\n", ATTR_QETH_ISOLATION_FWD);
436 case ISOLATION_MODE_DROP:
437 return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_DROP);
438 default:
439 return snprintf(buf, 5, "%s\n", "N/A");
440 }
441}
442
443static ssize_t qeth_dev_isolation_store(struct device *dev,
444 struct device_attribute *attr, const char *buf, size_t count)
445{
446 struct qeth_card *card = dev_get_drvdata(dev);
447 enum qeth_ipa_isolation_modes isolation;
448 int rc = 0;
449 char *tmp, *curtoken;
450 curtoken = (char *) buf;
451
452 if (!card) {
453 rc = -EINVAL;
454 goto out;
455 }
456
457 /* check for unknown, too, in case we do not yet know who we are */
458 if (card->info.type != QETH_CARD_TYPE_OSAE &&
459 card->info.type != QETH_CARD_TYPE_UNKNOWN) {
460 rc = -EOPNOTSUPP;
461 dev_err(&card->gdev->dev, "Adapter does not "
462 "support QDIO data connection isolation\n");
463 goto out;
464 }
465
466 /* parse input into isolation mode */
467 tmp = strsep(&curtoken, "\n");
468 if (!strcmp(tmp, ATTR_QETH_ISOLATION_NONE)) {
469 isolation = ISOLATION_MODE_NONE;
470 } else if (!strcmp(tmp, ATTR_QETH_ISOLATION_FWD)) {
471 isolation = ISOLATION_MODE_FWD;
472 } else if (!strcmp(tmp, ATTR_QETH_ISOLATION_DROP)) {
473 isolation = ISOLATION_MODE_DROP;
474 } else {
475 rc = -EINVAL;
476 goto out;
477 }
478 rc = count;
479
480 /* defer IP assist if device is offline (until discipline->set_online)*/
481 card->options.isolation = isolation;
482 if (card->state == CARD_STATE_SOFTSETUP ||
483 card->state == CARD_STATE_UP) {
484 int ipa_rc = qeth_set_access_ctrl_online(card);
485 if (ipa_rc != 0)
486 rc = ipa_rc;
487 }
488out:
489 return rc;
490}
491
492static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show,
493 qeth_dev_isolation_store);
494
4a71df50
FB
495static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value)
496{
497
498 if (!card)
499 return -EINVAL;
500
501 return sprintf(buf, "%i\n", value);
502}
503
504static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
505 const char *buf, size_t count, int *value, int max_value)
506{
507 char *tmp;
508 int i;
509
510 if (!card)
511 return -EINVAL;
512
513 if ((card->state != CARD_STATE_DOWN) &&
514 (card->state != CARD_STATE_RECOVER))
515 return -EPERM;
516
517 i = simple_strtoul(buf, &tmp, 10);
518 if (i <= max_value) {
519 *value = i;
520 } else {
4a71df50
FB
521 return -EINVAL;
522 }
523 return count;
524}
525
526static ssize_t qeth_dev_blkt_total_show(struct device *dev,
527 struct device_attribute *attr, char *buf)
528{
529 struct qeth_card *card = dev_get_drvdata(dev);
530
531 return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
532}
533
534static ssize_t qeth_dev_blkt_total_store(struct device *dev,
535 struct device_attribute *attr, const char *buf, size_t count)
536{
537 struct qeth_card *card = dev_get_drvdata(dev);
538
539 return qeth_dev_blkt_store(card, buf, count,
540 &card->info.blkt.time_total, 1000);
541}
542
543
544
545static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
546 qeth_dev_blkt_total_store);
547
548static ssize_t qeth_dev_blkt_inter_show(struct device *dev,
549 struct device_attribute *attr, char *buf)
550{
551 struct qeth_card *card = dev_get_drvdata(dev);
552
553 return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
554}
555
556static ssize_t qeth_dev_blkt_inter_store(struct device *dev,
557 struct device_attribute *attr, const char *buf, size_t count)
558{
559 struct qeth_card *card = dev_get_drvdata(dev);
560
561 return qeth_dev_blkt_store(card, buf, count,
562 &card->info.blkt.inter_packet, 100);
563}
564
565static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
566 qeth_dev_blkt_inter_store);
567
568static ssize_t qeth_dev_blkt_inter_jumbo_show(struct device *dev,
569 struct device_attribute *attr, char *buf)
570{
571 struct qeth_card *card = dev_get_drvdata(dev);
572
573 return qeth_dev_blkt_show(buf, card,
574 card->info.blkt.inter_packet_jumbo);
575}
576
577static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev,
578 struct device_attribute *attr, const char *buf, size_t count)
579{
580 struct qeth_card *card = dev_get_drvdata(dev);
581
582 return qeth_dev_blkt_store(card, buf, count,
583 &card->info.blkt.inter_packet_jumbo, 100);
584}
585
586static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
587 qeth_dev_blkt_inter_jumbo_store);
588
589static struct attribute *qeth_blkt_device_attrs[] = {
590 &dev_attr_total.attr,
591 &dev_attr_inter.attr,
592 &dev_attr_inter_jumbo.attr,
593 NULL,
594};
595
596static struct attribute_group qeth_device_blkt_group = {
597 .name = "blkt",
598 .attrs = qeth_blkt_device_attrs,
599};
600
601static struct attribute *qeth_device_attrs[] = {
602 &dev_attr_state.attr,
603 &dev_attr_chpid.attr,
604 &dev_attr_if_name.attr,
605 &dev_attr_card_type.attr,
606 &dev_attr_inbuf_size.attr,
607 &dev_attr_portno.attr,
608 &dev_attr_portname.attr,
609 &dev_attr_priority_queueing.attr,
610 &dev_attr_buffer_count.attr,
611 &dev_attr_recover.attr,
612 &dev_attr_performance_stats.attr,
613 &dev_attr_layer2.attr,
d64ecc22 614 &dev_attr_isolation.attr,
4a71df50
FB
615 NULL,
616};
617
618static struct attribute_group qeth_device_attr_group = {
619 .attrs = qeth_device_attrs,
620};
621
622static struct attribute *qeth_osn_device_attrs[] = {
623 &dev_attr_state.attr,
624 &dev_attr_chpid.attr,
625 &dev_attr_if_name.attr,
626 &dev_attr_card_type.attr,
627 &dev_attr_buffer_count.attr,
628 &dev_attr_recover.attr,
629 NULL,
630};
631
632static struct attribute_group qeth_osn_device_attr_group = {
633 .attrs = qeth_osn_device_attrs,
634};
635
636int qeth_core_create_device_attributes(struct device *dev)
637{
638 int ret;
639 ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
640 if (ret)
641 return ret;
642 ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
643 if (ret)
644 sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
645
646 return 0;
647}
648
649void qeth_core_remove_device_attributes(struct device *dev)
650{
651 sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
652 sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
653}
654
655int qeth_core_create_osn_attributes(struct device *dev)
656{
657 return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
658}
659
660void qeth_core_remove_osn_attributes(struct device *dev)
661{
662 sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
663 return;
664}