diff options
author | Frank Blaschka <frank.blaschka@de.ibm.com> | 2008-02-15 03:19:43 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-03-17 07:49:26 -0400 |
commit | 19a3da6c6e1e74ecac129a079139aaebb63fe6c8 (patch) | |
tree | 69c52c4a489f128ea056ee6a8860d3f431292dea /drivers/s390/net/qeth_sys.c | |
parent | 4a71df50047f0db65ea09b1be155852e81a45eba (diff) |
qeth: remove old qeth files
Remove all obsolete qeth files.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/s390/net/qeth_sys.c')
-rw-r--r-- | drivers/s390/net/qeth_sys.c | 1858 |
1 files changed, 0 insertions, 1858 deletions
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c deleted file mode 100644 index 2cc3f3a0e393..000000000000 --- a/drivers/s390/net/qeth_sys.c +++ /dev/null | |||
@@ -1,1858 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * linux/drivers/s390/net/qeth_sys.c | ||
4 | * | ||
5 | * Linux on zSeries OSA Express and HiperSockets support | ||
6 | * This file contains code related to sysfs. | ||
7 | * | ||
8 | * Copyright 2000,2003 IBM Corporation | ||
9 | * | ||
10 | * Author(s): Thomas Spatzier <tspat@de.ibm.com> | ||
11 | * Frank Pavlic <fpavlic@de.ibm.com> | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/list.h> | ||
15 | #include <linux/rwsem.h> | ||
16 | |||
17 | #include <asm/ebcdic.h> | ||
18 | |||
19 | #include "qeth.h" | ||
20 | #include "qeth_mpc.h" | ||
21 | #include "qeth_fs.h" | ||
22 | |||
23 | /*****************************************************************************/ | ||
24 | /* */ | ||
25 | /* /sys-fs stuff UNDER DEVELOPMENT !!! */ | ||
26 | /* */ | ||
27 | /*****************************************************************************/ | ||
28 | //low/high watermark | ||
29 | |||
30 | static ssize_t | ||
31 | qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
32 | { | ||
33 | struct qeth_card *card = dev->driver_data; | ||
34 | if (!card) | ||
35 | return -EINVAL; | ||
36 | |||
37 | switch (card->state) { | ||
38 | case CARD_STATE_DOWN: | ||
39 | return sprintf(buf, "DOWN\n"); | ||
40 | case CARD_STATE_HARDSETUP: | ||
41 | return sprintf(buf, "HARDSETUP\n"); | ||
42 | case CARD_STATE_SOFTSETUP: | ||
43 | return sprintf(buf, "SOFTSETUP\n"); | ||
44 | case CARD_STATE_UP: | ||
45 | if (card->lan_online) | ||
46 | return sprintf(buf, "UP (LAN ONLINE)\n"); | ||
47 | else | ||
48 | return sprintf(buf, "UP (LAN OFFLINE)\n"); | ||
49 | case CARD_STATE_RECOVER: | ||
50 | return sprintf(buf, "RECOVER\n"); | ||
51 | default: | ||
52 | return sprintf(buf, "UNKNOWN\n"); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL); | ||
57 | |||
58 | static ssize_t | ||
59 | qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
60 | { | ||
61 | struct qeth_card *card = dev->driver_data; | ||
62 | if (!card) | ||
63 | return -EINVAL; | ||
64 | |||
65 | return sprintf(buf, "%02X\n", card->info.chpid); | ||
66 | } | ||
67 | |||
68 | static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL); | ||
69 | |||
70 | static ssize_t | ||
71 | qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
72 | { | ||
73 | struct qeth_card *card = dev->driver_data; | ||
74 | if (!card) | ||
75 | return -EINVAL; | ||
76 | return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card)); | ||
77 | } | ||
78 | |||
79 | static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL); | ||
80 | |||
81 | static ssize_t | ||
82 | qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
83 | { | ||
84 | struct qeth_card *card = dev->driver_data; | ||
85 | if (!card) | ||
86 | return -EINVAL; | ||
87 | |||
88 | return sprintf(buf, "%s\n", qeth_get_cardname_short(card)); | ||
89 | } | ||
90 | |||
91 | static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL); | ||
92 | |||
93 | static ssize_t | ||
94 | qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
95 | { | ||
96 | struct qeth_card *card = dev->driver_data; | ||
97 | if (!card) | ||
98 | return -EINVAL; | ||
99 | |||
100 | return sprintf(buf, "%i\n", card->info.portno); | ||
101 | } | ||
102 | |||
103 | static ssize_t | ||
104 | qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
105 | { | ||
106 | struct qeth_card *card = dev->driver_data; | ||
107 | char *tmp; | ||
108 | unsigned int portno; | ||
109 | |||
110 | if (!card) | ||
111 | return -EINVAL; | ||
112 | |||
113 | if ((card->state != CARD_STATE_DOWN) && | ||
114 | (card->state != CARD_STATE_RECOVER)) | ||
115 | return -EPERM; | ||
116 | |||
117 | portno = simple_strtoul(buf, &tmp, 16); | ||
118 | if (portno > MAX_PORTNO){ | ||
119 | PRINT_WARN("portno 0x%X is out of range\n", portno); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | card->info.portno = portno; | ||
124 | return count; | ||
125 | } | ||
126 | |||
127 | static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store); | ||
128 | |||
129 | static ssize_t | ||
130 | qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
131 | { | ||
132 | struct qeth_card *card = dev->driver_data; | ||
133 | char portname[9] = {0, }; | ||
134 | |||
135 | if (!card) | ||
136 | return -EINVAL; | ||
137 | |||
138 | if (card->info.portname_required) { | ||
139 | memcpy(portname, card->info.portname + 1, 8); | ||
140 | EBCASC(portname, 8); | ||
141 | return sprintf(buf, "%s\n", portname); | ||
142 | } else | ||
143 | return sprintf(buf, "no portname required\n"); | ||
144 | } | ||
145 | |||
146 | static ssize_t | ||
147 | qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
148 | { | ||
149 | struct qeth_card *card = dev->driver_data; | ||
150 | char *tmp; | ||
151 | int i; | ||
152 | |||
153 | if (!card) | ||
154 | return -EINVAL; | ||
155 | |||
156 | if ((card->state != CARD_STATE_DOWN) && | ||
157 | (card->state != CARD_STATE_RECOVER)) | ||
158 | return -EPERM; | ||
159 | |||
160 | tmp = strsep((char **) &buf, "\n"); | ||
161 | if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) | ||
162 | return -EINVAL; | ||
163 | |||
164 | card->info.portname[0] = strlen(tmp); | ||
165 | /* for beauty reasons */ | ||
166 | for (i = 1; i < 9; i++) | ||
167 | card->info.portname[i] = ' '; | ||
168 | strcpy(card->info.portname + 1, tmp); | ||
169 | ASCEBC(card->info.portname + 1, 8); | ||
170 | |||
171 | return count; | ||
172 | } | ||
173 | |||
174 | static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show, | ||
175 | qeth_dev_portname_store); | ||
176 | |||
177 | static ssize_t | ||
178 | qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
179 | { | ||
180 | struct qeth_card *card = dev->driver_data; | ||
181 | |||
182 | if (!card) | ||
183 | return -EINVAL; | ||
184 | |||
185 | return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card)); | ||
186 | } | ||
187 | |||
188 | static ssize_t | ||
189 | qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
190 | { | ||
191 | struct qeth_card *card = dev->driver_data; | ||
192 | char *tmp; | ||
193 | |||
194 | if (!card) | ||
195 | return -EINVAL; | ||
196 | |||
197 | if ((card->state != CARD_STATE_DOWN) && | ||
198 | (card->state != CARD_STATE_RECOVER)) | ||
199 | return -EPERM; | ||
200 | |||
201 | tmp = strsep((char **) &buf, "\n"); | ||
202 | if (!strcmp(tmp, "sw_checksumming")) | ||
203 | card->options.checksum_type = SW_CHECKSUMMING; | ||
204 | else if (!strcmp(tmp, "hw_checksumming")) | ||
205 | card->options.checksum_type = HW_CHECKSUMMING; | ||
206 | else if (!strcmp(tmp, "no_checksumming")) | ||
207 | card->options.checksum_type = NO_CHECKSUMMING; | ||
208 | else { | ||
209 | PRINT_WARN("Unknown checksumming type '%s'\n", tmp); | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | return count; | ||
213 | } | ||
214 | |||
215 | static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show, | ||
216 | qeth_dev_checksum_store); | ||
217 | |||
218 | static ssize_t | ||
219 | qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
220 | { | ||
221 | struct qeth_card *card = dev->driver_data; | ||
222 | |||
223 | if (!card) | ||
224 | return -EINVAL; | ||
225 | |||
226 | switch (card->qdio.do_prio_queueing) { | ||
227 | case QETH_PRIO_Q_ING_PREC: | ||
228 | return sprintf(buf, "%s\n", "by precedence"); | ||
229 | case QETH_PRIO_Q_ING_TOS: | ||
230 | return sprintf(buf, "%s\n", "by type of service"); | ||
231 | default: | ||
232 | return sprintf(buf, "always queue %i\n", | ||
233 | card->qdio.default_out_queue); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | static ssize_t | ||
238 | qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
239 | { | ||
240 | struct qeth_card *card = dev->driver_data; | ||
241 | char *tmp; | ||
242 | |||
243 | if (!card) | ||
244 | return -EINVAL; | ||
245 | |||
246 | if ((card->state != CARD_STATE_DOWN) && | ||
247 | (card->state != CARD_STATE_RECOVER)) | ||
248 | return -EPERM; | ||
249 | |||
250 | /* check if 1920 devices are supported , | ||
251 | * if though we have to permit priority queueing | ||
252 | */ | ||
253 | if (card->qdio.no_out_queues == 1) { | ||
254 | PRINT_WARN("Priority queueing disabled due " | ||
255 | "to hardware limitations!\n"); | ||
256 | card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; | ||
257 | return -EPERM; | ||
258 | } | ||
259 | |||
260 | tmp = strsep((char **) &buf, "\n"); | ||
261 | if (!strcmp(tmp, "prio_queueing_prec")) | ||
262 | card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC; | ||
263 | else if (!strcmp(tmp, "prio_queueing_tos")) | ||
264 | card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS; | ||
265 | else if (!strcmp(tmp, "no_prio_queueing:0")) { | ||
266 | card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; | ||
267 | card->qdio.default_out_queue = 0; | ||
268 | } else if (!strcmp(tmp, "no_prio_queueing:1")) { | ||
269 | card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; | ||
270 | card->qdio.default_out_queue = 1; | ||
271 | } else if (!strcmp(tmp, "no_prio_queueing:2")) { | ||
272 | card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; | ||
273 | card->qdio.default_out_queue = 2; | ||
274 | } else if (!strcmp(tmp, "no_prio_queueing:3")) { | ||
275 | card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; | ||
276 | card->qdio.default_out_queue = 3; | ||
277 | } else if (!strcmp(tmp, "no_prio_queueing")) { | ||
278 | card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; | ||
279 | card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; | ||
280 | } else { | ||
281 | PRINT_WARN("Unknown queueing type '%s'\n", tmp); | ||
282 | return -EINVAL; | ||
283 | } | ||
284 | return count; | ||
285 | } | ||
286 | |||
287 | static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show, | ||
288 | qeth_dev_prioqing_store); | ||
289 | |||
290 | static ssize_t | ||
291 | qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
292 | { | ||
293 | struct qeth_card *card = dev->driver_data; | ||
294 | |||
295 | if (!card) | ||
296 | return -EINVAL; | ||
297 | |||
298 | return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count); | ||
299 | } | ||
300 | |||
301 | static ssize_t | ||
302 | qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
303 | { | ||
304 | struct qeth_card *card = dev->driver_data; | ||
305 | char *tmp; | ||
306 | int cnt, old_cnt; | ||
307 | int rc; | ||
308 | |||
309 | if (!card) | ||
310 | return -EINVAL; | ||
311 | |||
312 | if ((card->state != CARD_STATE_DOWN) && | ||
313 | (card->state != CARD_STATE_RECOVER)) | ||
314 | return -EPERM; | ||
315 | |||
316 | old_cnt = card->qdio.in_buf_pool.buf_count; | ||
317 | cnt = simple_strtoul(buf, &tmp, 10); | ||
318 | cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN : | ||
319 | ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt); | ||
320 | if (old_cnt != cnt) { | ||
321 | if ((rc = qeth_realloc_buffer_pool(card, cnt))) | ||
322 | PRINT_WARN("Error (%d) while setting " | ||
323 | "buffer count.\n", rc); | ||
324 | } | ||
325 | return count; | ||
326 | } | ||
327 | |||
328 | static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show, | ||
329 | qeth_dev_bufcnt_store); | ||
330 | |||
331 | static ssize_t | ||
332 | qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route, | ||
333 | char *buf) | ||
334 | { | ||
335 | switch (route->type) { | ||
336 | case PRIMARY_ROUTER: | ||
337 | return sprintf(buf, "%s\n", "primary router"); | ||
338 | case SECONDARY_ROUTER: | ||
339 | return sprintf(buf, "%s\n", "secondary router"); | ||
340 | case MULTICAST_ROUTER: | ||
341 | if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) | ||
342 | return sprintf(buf, "%s\n", "multicast router+"); | ||
343 | else | ||
344 | return sprintf(buf, "%s\n", "multicast router"); | ||
345 | case PRIMARY_CONNECTOR: | ||
346 | if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) | ||
347 | return sprintf(buf, "%s\n", "primary connector+"); | ||
348 | else | ||
349 | return sprintf(buf, "%s\n", "primary connector"); | ||
350 | case SECONDARY_CONNECTOR: | ||
351 | if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) | ||
352 | return sprintf(buf, "%s\n", "secondary connector+"); | ||
353 | else | ||
354 | return sprintf(buf, "%s\n", "secondary connector"); | ||
355 | default: | ||
356 | return sprintf(buf, "%s\n", "no"); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | static ssize_t | ||
361 | qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
362 | { | ||
363 | struct qeth_card *card = dev->driver_data; | ||
364 | |||
365 | if (!card) | ||
366 | return -EINVAL; | ||
367 | |||
368 | return qeth_dev_route_show(card, &card->options.route4, buf); | ||
369 | } | ||
370 | |||
371 | static ssize_t | ||
372 | qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route, | ||
373 | enum qeth_prot_versions prot, const char *buf, size_t count) | ||
374 | { | ||
375 | enum qeth_routing_types old_route_type = route->type; | ||
376 | char *tmp; | ||
377 | int rc; | ||
378 | |||
379 | tmp = strsep((char **) &buf, "\n"); | ||
380 | |||
381 | if (!strcmp(tmp, "no_router")){ | ||
382 | route->type = NO_ROUTER; | ||
383 | } else if (!strcmp(tmp, "primary_connector")) { | ||
384 | route->type = PRIMARY_CONNECTOR; | ||
385 | } else if (!strcmp(tmp, "secondary_connector")) { | ||
386 | route->type = SECONDARY_CONNECTOR; | ||
387 | } else if (!strcmp(tmp, "primary_router")) { | ||
388 | route->type = PRIMARY_ROUTER; | ||
389 | } else if (!strcmp(tmp, "secondary_router")) { | ||
390 | route->type = SECONDARY_ROUTER; | ||
391 | } else if (!strcmp(tmp, "multicast_router")) { | ||
392 | route->type = MULTICAST_ROUTER; | ||
393 | } else { | ||
394 | PRINT_WARN("Invalid routing type '%s'.\n", tmp); | ||
395 | return -EINVAL; | ||
396 | } | ||
397 | if (((card->state == CARD_STATE_SOFTSETUP) || | ||
398 | (card->state == CARD_STATE_UP)) && | ||
399 | (old_route_type != route->type)){ | ||
400 | if (prot == QETH_PROT_IPV4) | ||
401 | rc = qeth_setrouting_v4(card); | ||
402 | else if (prot == QETH_PROT_IPV6) | ||
403 | rc = qeth_setrouting_v6(card); | ||
404 | } | ||
405 | return count; | ||
406 | } | ||
407 | |||
408 | static ssize_t | ||
409 | qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
410 | { | ||
411 | struct qeth_card *card = dev->driver_data; | ||
412 | |||
413 | if (!card) | ||
414 | return -EINVAL; | ||
415 | |||
416 | return qeth_dev_route_store(card, &card->options.route4, | ||
417 | QETH_PROT_IPV4, buf, count); | ||
418 | } | ||
419 | |||
420 | static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store); | ||
421 | |||
422 | #ifdef CONFIG_QETH_IPV6 | ||
423 | static ssize_t | ||
424 | qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
425 | { | ||
426 | struct qeth_card *card = dev->driver_data; | ||
427 | |||
428 | if (!card) | ||
429 | return -EINVAL; | ||
430 | |||
431 | if (!qeth_is_supported(card, IPA_IPV6)) | ||
432 | return sprintf(buf, "%s\n", "n/a"); | ||
433 | |||
434 | return qeth_dev_route_show(card, &card->options.route6, buf); | ||
435 | } | ||
436 | |||
437 | static ssize_t | ||
438 | qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
439 | { | ||
440 | struct qeth_card *card = dev->driver_data; | ||
441 | |||
442 | if (!card) | ||
443 | return -EINVAL; | ||
444 | |||
445 | if (!qeth_is_supported(card, IPA_IPV6)){ | ||
446 | PRINT_WARN("IPv6 not supported for interface %s.\n" | ||
447 | "Routing status no changed.\n", | ||
448 | QETH_CARD_IFNAME(card)); | ||
449 | return -ENOTSUPP; | ||
450 | } | ||
451 | |||
452 | return qeth_dev_route_store(card, &card->options.route6, | ||
453 | QETH_PROT_IPV6, buf, count); | ||
454 | } | ||
455 | |||
456 | static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store); | ||
457 | #endif | ||
458 | |||
459 | static ssize_t | ||
460 | qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
461 | { | ||
462 | struct qeth_card *card = dev->driver_data; | ||
463 | |||
464 | if (!card) | ||
465 | return -EINVAL; | ||
466 | |||
467 | return sprintf(buf, "%i\n", card->options.add_hhlen); | ||
468 | } | ||
469 | |||
470 | static ssize_t | ||
471 | qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
472 | { | ||
473 | struct qeth_card *card = dev->driver_data; | ||
474 | char *tmp; | ||
475 | int i; | ||
476 | |||
477 | if (!card) | ||
478 | return -EINVAL; | ||
479 | |||
480 | if ((card->state != CARD_STATE_DOWN) && | ||
481 | (card->state != CARD_STATE_RECOVER)) | ||
482 | return -EPERM; | ||
483 | |||
484 | i = simple_strtoul(buf, &tmp, 10); | ||
485 | if ((i < 0) || (i > MAX_ADD_HHLEN)) { | ||
486 | PRINT_WARN("add_hhlen out of range\n"); | ||
487 | return -EINVAL; | ||
488 | } | ||
489 | card->options.add_hhlen = i; | ||
490 | |||
491 | return count; | ||
492 | } | ||
493 | |||
494 | static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show, | ||
495 | qeth_dev_add_hhlen_store); | ||
496 | |||
497 | static ssize_t | ||
498 | qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
499 | { | ||
500 | struct qeth_card *card = dev->driver_data; | ||
501 | |||
502 | if (!card) | ||
503 | return -EINVAL; | ||
504 | |||
505 | return sprintf(buf, "%i\n", card->options.fake_ll? 1:0); | ||
506 | } | ||
507 | |||
508 | static ssize_t | ||
509 | qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
510 | { | ||
511 | struct qeth_card *card = dev->driver_data; | ||
512 | char *tmp; | ||
513 | int i; | ||
514 | |||
515 | if (!card) | ||
516 | return -EINVAL; | ||
517 | |||
518 | if ((card->state != CARD_STATE_DOWN) && | ||
519 | (card->state != CARD_STATE_RECOVER)) | ||
520 | return -EPERM; | ||
521 | |||
522 | i = simple_strtoul(buf, &tmp, 16); | ||
523 | if ((i != 0) && (i != 1)) { | ||
524 | PRINT_WARN("fake_ll: write 0 or 1 to this file!\n"); | ||
525 | return -EINVAL; | ||
526 | } | ||
527 | card->options.fake_ll = i; | ||
528 | return count; | ||
529 | } | ||
530 | |||
531 | static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show, | ||
532 | qeth_dev_fake_ll_store); | ||
533 | |||
534 | static ssize_t | ||
535 | qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
536 | { | ||
537 | struct qeth_card *card = dev->driver_data; | ||
538 | |||
539 | if (!card) | ||
540 | return -EINVAL; | ||
541 | |||
542 | return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0); | ||
543 | } | ||
544 | |||
545 | static ssize_t | ||
546 | qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
547 | { | ||
548 | struct qeth_card *card = dev->driver_data; | ||
549 | char *tmp; | ||
550 | int i; | ||
551 | |||
552 | if (!card) | ||
553 | return -EINVAL; | ||
554 | |||
555 | if ((card->state != CARD_STATE_DOWN) && | ||
556 | (card->state != CARD_STATE_RECOVER)) | ||
557 | return -EPERM; | ||
558 | |||
559 | i = simple_strtoul(buf, &tmp, 16); | ||
560 | if ((i == 0) || (i == 1)) | ||
561 | card->options.fake_broadcast = i; | ||
562 | else { | ||
563 | PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n"); | ||
564 | return -EINVAL; | ||
565 | } | ||
566 | return count; | ||
567 | } | ||
568 | |||
569 | static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show, | ||
570 | qeth_dev_fake_broadcast_store); | ||
571 | |||
572 | static ssize_t | ||
573 | qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
574 | { | ||
575 | struct qeth_card *card = dev->driver_data; | ||
576 | char *tmp; | ||
577 | int i; | ||
578 | |||
579 | if (!card) | ||
580 | return -EINVAL; | ||
581 | |||
582 | if (card->state != CARD_STATE_UP) | ||
583 | return -EPERM; | ||
584 | |||
585 | i = simple_strtoul(buf, &tmp, 16); | ||
586 | if (i == 1) | ||
587 | qeth_schedule_recovery(card); | ||
588 | |||
589 | return count; | ||
590 | } | ||
591 | |||
592 | static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store); | ||
593 | |||
594 | static ssize_t | ||
595 | qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
596 | { | ||
597 | struct qeth_card *card = dev->driver_data; | ||
598 | |||
599 | if (!card) | ||
600 | return -EINVAL; | ||
601 | |||
602 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || | ||
603 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) | ||
604 | return sprintf(buf, "n/a\n"); | ||
605 | |||
606 | return sprintf(buf, "%s\n", (card->options.broadcast_mode == | ||
607 | QETH_TR_BROADCAST_ALLRINGS)? | ||
608 | "all rings":"local"); | ||
609 | } | ||
610 | |||
611 | static ssize_t | ||
612 | qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
613 | { | ||
614 | struct qeth_card *card = dev->driver_data; | ||
615 | char *tmp; | ||
616 | |||
617 | if (!card) | ||
618 | return -EINVAL; | ||
619 | |||
620 | if ((card->state != CARD_STATE_DOWN) && | ||
621 | (card->state != CARD_STATE_RECOVER)) | ||
622 | return -EPERM; | ||
623 | |||
624 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || | ||
625 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){ | ||
626 | PRINT_WARN("Device is not a tokenring device!\n"); | ||
627 | return -EINVAL; | ||
628 | } | ||
629 | |||
630 | tmp = strsep((char **) &buf, "\n"); | ||
631 | |||
632 | if (!strcmp(tmp, "local")){ | ||
633 | card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL; | ||
634 | return count; | ||
635 | } else if (!strcmp(tmp, "all_rings")) { | ||
636 | card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; | ||
637 | return count; | ||
638 | } else { | ||
639 | PRINT_WARN("broadcast_mode: invalid mode %s!\n", | ||
640 | tmp); | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | return count; | ||
644 | } | ||
645 | |||
646 | static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show, | ||
647 | qeth_dev_broadcast_mode_store); | ||
648 | |||
649 | static ssize_t | ||
650 | qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
651 | { | ||
652 | struct qeth_card *card = dev->driver_data; | ||
653 | |||
654 | if (!card) | ||
655 | return -EINVAL; | ||
656 | |||
657 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || | ||
658 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) | ||
659 | return sprintf(buf, "n/a\n"); | ||
660 | |||
661 | return sprintf(buf, "%i\n", (card->options.macaddr_mode == | ||
662 | QETH_TR_MACADDR_CANONICAL)? 1:0); | ||
663 | } | ||
664 | |||
665 | static ssize_t | ||
666 | qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf, | ||
667 | size_t count) | ||
668 | { | ||
669 | struct qeth_card *card = dev->driver_data; | ||
670 | char *tmp; | ||
671 | int i; | ||
672 | |||
673 | if (!card) | ||
674 | return -EINVAL; | ||
675 | |||
676 | if ((card->state != CARD_STATE_DOWN) && | ||
677 | (card->state != CARD_STATE_RECOVER)) | ||
678 | return -EPERM; | ||
679 | |||
680 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || | ||
681 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){ | ||
682 | PRINT_WARN("Device is not a tokenring device!\n"); | ||
683 | return -EINVAL; | ||
684 | } | ||
685 | |||
686 | i = simple_strtoul(buf, &tmp, 16); | ||
687 | if ((i == 0) || (i == 1)) | ||
688 | card->options.macaddr_mode = i? | ||
689 | QETH_TR_MACADDR_CANONICAL : | ||
690 | QETH_TR_MACADDR_NONCANONICAL; | ||
691 | else { | ||
692 | PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n"); | ||
693 | return -EINVAL; | ||
694 | } | ||
695 | return count; | ||
696 | } | ||
697 | |||
698 | static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show, | ||
699 | qeth_dev_canonical_macaddr_store); | ||
700 | |||
701 | static ssize_t | ||
702 | qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
703 | { | ||
704 | struct qeth_card *card = dev->driver_data; | ||
705 | |||
706 | if (!card) | ||
707 | return -EINVAL; | ||
708 | |||
709 | return sprintf(buf, "%i\n", card->options.layer2 ? 1:0); | ||
710 | } | ||
711 | |||
712 | static ssize_t | ||
713 | qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
714 | { | ||
715 | struct qeth_card *card = dev->driver_data; | ||
716 | char *tmp; | ||
717 | int i; | ||
718 | |||
719 | if (!card) | ||
720 | return -EINVAL; | ||
721 | if (card->info.type == QETH_CARD_TYPE_IQD) { | ||
722 | PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); | ||
723 | return -EPERM; | ||
724 | } | ||
725 | |||
726 | if (((card->state != CARD_STATE_DOWN) && | ||
727 | (card->state != CARD_STATE_RECOVER))) | ||
728 | return -EPERM; | ||
729 | |||
730 | i = simple_strtoul(buf, &tmp, 16); | ||
731 | if ((i == 0) || (i == 1)) | ||
732 | card->options.layer2 = i; | ||
733 | else { | ||
734 | PRINT_WARN("layer2: write 0 or 1 to this file!\n"); | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | return count; | ||
738 | } | ||
739 | |||
740 | static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, | ||
741 | qeth_dev_layer2_store); | ||
742 | |||
743 | static ssize_t | ||
744 | qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
745 | { | ||
746 | struct qeth_card *card = dev->driver_data; | ||
747 | |||
748 | if (!card) | ||
749 | return -EINVAL; | ||
750 | |||
751 | return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0); | ||
752 | } | ||
753 | |||
754 | static ssize_t | ||
755 | qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
756 | { | ||
757 | struct qeth_card *card = dev->driver_data; | ||
758 | char *tmp; | ||
759 | int i; | ||
760 | |||
761 | if (!card) | ||
762 | return -EINVAL; | ||
763 | |||
764 | i = simple_strtoul(buf, &tmp, 16); | ||
765 | if ((i == 0) || (i == 1)) { | ||
766 | if (i == card->options.performance_stats) | ||
767 | return count; | ||
768 | card->options.performance_stats = i; | ||
769 | if (i == 0) | ||
770 | memset(&card->perf_stats, 0, | ||
771 | sizeof(struct qeth_perf_stats)); | ||
772 | card->perf_stats.initial_rx_packets = card->stats.rx_packets; | ||
773 | card->perf_stats.initial_tx_packets = card->stats.tx_packets; | ||
774 | } else { | ||
775 | PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); | ||
776 | return -EINVAL; | ||
777 | } | ||
778 | return count; | ||
779 | } | ||
780 | |||
781 | static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, | ||
782 | qeth_dev_performance_stats_store); | ||
783 | |||
784 | static ssize_t | ||
785 | qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
786 | { | ||
787 | struct qeth_card *card = dev->driver_data; | ||
788 | |||
789 | if (!card) | ||
790 | return -EINVAL; | ||
791 | |||
792 | switch (card->options.large_send) { | ||
793 | case QETH_LARGE_SEND_NO: | ||
794 | return sprintf(buf, "%s\n", "no"); | ||
795 | case QETH_LARGE_SEND_EDDP: | ||
796 | return sprintf(buf, "%s\n", "EDDP"); | ||
797 | case QETH_LARGE_SEND_TSO: | ||
798 | return sprintf(buf, "%s\n", "TSO"); | ||
799 | default: | ||
800 | return sprintf(buf, "%s\n", "N/A"); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | static ssize_t | ||
805 | qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
806 | { | ||
807 | struct qeth_card *card = dev->driver_data; | ||
808 | enum qeth_large_send_types type; | ||
809 | int rc = 0; | ||
810 | char *tmp; | ||
811 | |||
812 | if (!card) | ||
813 | return -EINVAL; | ||
814 | tmp = strsep((char **) &buf, "\n"); | ||
815 | if (!strcmp(tmp, "no")){ | ||
816 | type = QETH_LARGE_SEND_NO; | ||
817 | } else if (!strcmp(tmp, "EDDP")) { | ||
818 | type = QETH_LARGE_SEND_EDDP; | ||
819 | } else if (!strcmp(tmp, "TSO")) { | ||
820 | type = QETH_LARGE_SEND_TSO; | ||
821 | } else { | ||
822 | PRINT_WARN("large_send: invalid mode %s!\n", tmp); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | if (card->options.large_send == type) | ||
826 | return count; | ||
827 | if ((rc = qeth_set_large_send(card, type))) | ||
828 | return rc; | ||
829 | return count; | ||
830 | } | ||
831 | |||
832 | static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show, | ||
833 | qeth_dev_large_send_store); | ||
834 | |||
835 | static ssize_t | ||
836 | qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value ) | ||
837 | { | ||
838 | |||
839 | if (!card) | ||
840 | return -EINVAL; | ||
841 | |||
842 | return sprintf(buf, "%i\n", value); | ||
843 | } | ||
844 | |||
845 | static ssize_t | ||
846 | qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count, | ||
847 | int *value, int max_value) | ||
848 | { | ||
849 | char *tmp; | ||
850 | int i; | ||
851 | |||
852 | if (!card) | ||
853 | return -EINVAL; | ||
854 | |||
855 | if ((card->state != CARD_STATE_DOWN) && | ||
856 | (card->state != CARD_STATE_RECOVER)) | ||
857 | return -EPERM; | ||
858 | |||
859 | i = simple_strtoul(buf, &tmp, 10); | ||
860 | if (i <= max_value) { | ||
861 | *value = i; | ||
862 | } else { | ||
863 | PRINT_WARN("blkt total time: write values between" | ||
864 | " 0 and %d to this file!\n", max_value); | ||
865 | return -EINVAL; | ||
866 | } | ||
867 | return count; | ||
868 | } | ||
869 | |||
870 | static ssize_t | ||
871 | qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
872 | { | ||
873 | struct qeth_card *card = dev->driver_data; | ||
874 | |||
875 | return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total); | ||
876 | } | ||
877 | |||
878 | |||
879 | static ssize_t | ||
880 | qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
881 | { | ||
882 | struct qeth_card *card = dev->driver_data; | ||
883 | |||
884 | return qeth_dev_blkt_store(card, buf, count, | ||
885 | &card->info.blkt.time_total,1000); | ||
886 | } | ||
887 | |||
888 | |||
889 | |||
890 | static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show, | ||
891 | qeth_dev_blkt_total_store); | ||
892 | |||
893 | static ssize_t | ||
894 | qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
895 | { | ||
896 | struct qeth_card *card = dev->driver_data; | ||
897 | |||
898 | return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet); | ||
899 | } | ||
900 | |||
901 | |||
902 | static ssize_t | ||
903 | qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
904 | { | ||
905 | struct qeth_card *card = dev->driver_data; | ||
906 | |||
907 | return qeth_dev_blkt_store(card, buf, count, | ||
908 | &card->info.blkt.inter_packet,100); | ||
909 | } | ||
910 | |||
911 | static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show, | ||
912 | qeth_dev_blkt_inter_store); | ||
913 | |||
914 | static ssize_t | ||
915 | qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
916 | { | ||
917 | struct qeth_card *card = dev->driver_data; | ||
918 | |||
919 | return qeth_dev_blkt_show(buf, card, | ||
920 | card->info.blkt.inter_packet_jumbo); | ||
921 | } | ||
922 | |||
923 | |||
924 | static ssize_t | ||
925 | qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
926 | { | ||
927 | struct qeth_card *card = dev->driver_data; | ||
928 | |||
929 | return qeth_dev_blkt_store(card, buf, count, | ||
930 | &card->info.blkt.inter_packet_jumbo,100); | ||
931 | } | ||
932 | |||
933 | static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show, | ||
934 | qeth_dev_blkt_inter_jumbo_store); | ||
935 | |||
936 | static struct device_attribute * qeth_blkt_device_attrs[] = { | ||
937 | &dev_attr_total, | ||
938 | &dev_attr_inter, | ||
939 | &dev_attr_inter_jumbo, | ||
940 | NULL, | ||
941 | }; | ||
942 | |||
943 | static struct attribute_group qeth_device_blkt_group = { | ||
944 | .name = "blkt", | ||
945 | .attrs = (struct attribute **)qeth_blkt_device_attrs, | ||
946 | }; | ||
947 | |||
948 | static struct device_attribute * qeth_device_attrs[] = { | ||
949 | &dev_attr_state, | ||
950 | &dev_attr_chpid, | ||
951 | &dev_attr_if_name, | ||
952 | &dev_attr_card_type, | ||
953 | &dev_attr_portno, | ||
954 | &dev_attr_portname, | ||
955 | &dev_attr_checksumming, | ||
956 | &dev_attr_priority_queueing, | ||
957 | &dev_attr_buffer_count, | ||
958 | &dev_attr_route4, | ||
959 | #ifdef CONFIG_QETH_IPV6 | ||
960 | &dev_attr_route6, | ||
961 | #endif | ||
962 | &dev_attr_add_hhlen, | ||
963 | &dev_attr_fake_ll, | ||
964 | &dev_attr_fake_broadcast, | ||
965 | &dev_attr_recover, | ||
966 | &dev_attr_broadcast_mode, | ||
967 | &dev_attr_canonical_macaddr, | ||
968 | &dev_attr_layer2, | ||
969 | &dev_attr_large_send, | ||
970 | &dev_attr_performance_stats, | ||
971 | NULL, | ||
972 | }; | ||
973 | |||
974 | static struct attribute_group qeth_device_attr_group = { | ||
975 | .attrs = (struct attribute **)qeth_device_attrs, | ||
976 | }; | ||
977 | |||
978 | static struct device_attribute * qeth_osn_device_attrs[] = { | ||
979 | &dev_attr_state, | ||
980 | &dev_attr_chpid, | ||
981 | &dev_attr_if_name, | ||
982 | &dev_attr_card_type, | ||
983 | &dev_attr_buffer_count, | ||
984 | &dev_attr_recover, | ||
985 | NULL, | ||
986 | }; | ||
987 | |||
988 | static struct attribute_group qeth_osn_device_attr_group = { | ||
989 | .attrs = (struct attribute **)qeth_osn_device_attrs, | ||
990 | }; | ||
991 | |||
992 | #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \ | ||
993 | struct device_attribute dev_attr_##_id = { \ | ||
994 | .attr = {.name=__stringify(_name), .mode=_mode, },\ | ||
995 | .show = _show, \ | ||
996 | .store = _store, \ | ||
997 | }; | ||
998 | |||
999 | static int | ||
1000 | qeth_check_layer2(struct qeth_card *card) | ||
1001 | { | ||
1002 | if (card->options.layer2) | ||
1003 | return -EPERM; | ||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | |||
1008 | static ssize_t | ||
1009 | qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1010 | { | ||
1011 | struct qeth_card *card = dev->driver_data; | ||
1012 | |||
1013 | if (!card) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | if (qeth_check_layer2(card)) | ||
1017 | return -EPERM; | ||
1018 | return sprintf(buf, "%i\n", card->ipato.enabled? 1:0); | ||
1019 | } | ||
1020 | |||
1021 | static ssize_t | ||
1022 | qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1023 | { | ||
1024 | struct qeth_card *card = dev->driver_data; | ||
1025 | char *tmp; | ||
1026 | |||
1027 | if (!card) | ||
1028 | return -EINVAL; | ||
1029 | |||
1030 | if ((card->state != CARD_STATE_DOWN) && | ||
1031 | (card->state != CARD_STATE_RECOVER)) | ||
1032 | return -EPERM; | ||
1033 | |||
1034 | if (qeth_check_layer2(card)) | ||
1035 | return -EPERM; | ||
1036 | |||
1037 | tmp = strsep((char **) &buf, "\n"); | ||
1038 | if (!strcmp(tmp, "toggle")){ | ||
1039 | card->ipato.enabled = (card->ipato.enabled)? 0 : 1; | ||
1040 | } else if (!strcmp(tmp, "1")){ | ||
1041 | card->ipato.enabled = 1; | ||
1042 | } else if (!strcmp(tmp, "0")){ | ||
1043 | card->ipato.enabled = 0; | ||
1044 | } else { | ||
1045 | PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to " | ||
1046 | "this file\n"); | ||
1047 | return -EINVAL; | ||
1048 | } | ||
1049 | return count; | ||
1050 | } | ||
1051 | |||
1052 | static QETH_DEVICE_ATTR(ipato_enable, enable, 0644, | ||
1053 | qeth_dev_ipato_enable_show, | ||
1054 | qeth_dev_ipato_enable_store); | ||
1055 | |||
1056 | static ssize_t | ||
1057 | qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1058 | { | ||
1059 | struct qeth_card *card = dev->driver_data; | ||
1060 | |||
1061 | if (!card) | ||
1062 | return -EINVAL; | ||
1063 | |||
1064 | if (qeth_check_layer2(card)) | ||
1065 | return -EPERM; | ||
1066 | |||
1067 | return sprintf(buf, "%i\n", card->ipato.invert4? 1:0); | ||
1068 | } | ||
1069 | |||
1070 | static ssize_t | ||
1071 | qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1072 | { | ||
1073 | struct qeth_card *card = dev->driver_data; | ||
1074 | char *tmp; | ||
1075 | |||
1076 | if (!card) | ||
1077 | return -EINVAL; | ||
1078 | |||
1079 | if (qeth_check_layer2(card)) | ||
1080 | return -EPERM; | ||
1081 | |||
1082 | tmp = strsep((char **) &buf, "\n"); | ||
1083 | if (!strcmp(tmp, "toggle")){ | ||
1084 | card->ipato.invert4 = (card->ipato.invert4)? 0 : 1; | ||
1085 | } else if (!strcmp(tmp, "1")){ | ||
1086 | card->ipato.invert4 = 1; | ||
1087 | } else if (!strcmp(tmp, "0")){ | ||
1088 | card->ipato.invert4 = 0; | ||
1089 | } else { | ||
1090 | PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to " | ||
1091 | "this file\n"); | ||
1092 | return -EINVAL; | ||
1093 | } | ||
1094 | return count; | ||
1095 | } | ||
1096 | |||
1097 | static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644, | ||
1098 | qeth_dev_ipato_invert4_show, | ||
1099 | qeth_dev_ipato_invert4_store); | ||
1100 | |||
1101 | static ssize_t | ||
1102 | qeth_dev_ipato_add_show(char *buf, struct qeth_card *card, | ||
1103 | enum qeth_prot_versions proto) | ||
1104 | { | ||
1105 | struct qeth_ipato_entry *ipatoe; | ||
1106 | unsigned long flags; | ||
1107 | char addr_str[40]; | ||
1108 | int entry_len; /* length of 1 entry string, differs between v4 and v6 */ | ||
1109 | int i = 0; | ||
1110 | |||
1111 | if (qeth_check_layer2(card)) | ||
1112 | return -EPERM; | ||
1113 | |||
1114 | entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; | ||
1115 | /* add strlen for "/<mask>\n" */ | ||
1116 | entry_len += (proto == QETH_PROT_IPV4)? 5 : 6; | ||
1117 | spin_lock_irqsave(&card->ip_lock, flags); | ||
1118 | list_for_each_entry(ipatoe, &card->ipato.entries, entry){ | ||
1119 | if (ipatoe->proto != proto) | ||
1120 | continue; | ||
1121 | /* String must not be longer than PAGE_SIZE. So we check if | ||
1122 | * string length gets near PAGE_SIZE. Then we can savely display | ||
1123 | * the next IPv6 address (worst case, compared to IPv4) */ | ||
1124 | if ((PAGE_SIZE - i) <= entry_len) | ||
1125 | break; | ||
1126 | qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str); | ||
1127 | i += snprintf(buf + i, PAGE_SIZE - i, | ||
1128 | "%s/%i\n", addr_str, ipatoe->mask_bits); | ||
1129 | } | ||
1130 | spin_unlock_irqrestore(&card->ip_lock, flags); | ||
1131 | i += snprintf(buf + i, PAGE_SIZE - i, "\n"); | ||
1132 | |||
1133 | return i; | ||
1134 | } | ||
1135 | |||
1136 | static ssize_t | ||
1137 | qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1138 | { | ||
1139 | struct qeth_card *card = dev->driver_data; | ||
1140 | |||
1141 | if (!card) | ||
1142 | return -EINVAL; | ||
1143 | |||
1144 | return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4); | ||
1145 | } | ||
1146 | |||
1147 | static int | ||
1148 | qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, | ||
1149 | u8 *addr, int *mask_bits) | ||
1150 | { | ||
1151 | const char *start, *end; | ||
1152 | char *tmp; | ||
1153 | char buffer[40] = {0, }; | ||
1154 | |||
1155 | start = buf; | ||
1156 | /* get address string */ | ||
1157 | end = strchr(start, '/'); | ||
1158 | if (!end || (end - start >= 40)){ | ||
1159 | PRINT_WARN("Invalid format for ipato_addx/delx. " | ||
1160 | "Use <ip addr>/<mask bits>\n"); | ||
1161 | return -EINVAL; | ||
1162 | } | ||
1163 | strncpy(buffer, start, end - start); | ||
1164 | if (qeth_string_to_ipaddr(buffer, proto, addr)){ | ||
1165 | PRINT_WARN("Invalid IP address format!\n"); | ||
1166 | return -EINVAL; | ||
1167 | } | ||
1168 | start = end + 1; | ||
1169 | *mask_bits = simple_strtoul(start, &tmp, 10); | ||
1170 | if (!strlen(start) || | ||
1171 | (tmp == start) || | ||
1172 | (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) { | ||
1173 | PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n"); | ||
1174 | return -EINVAL; | ||
1175 | } | ||
1176 | return 0; | ||
1177 | } | ||
1178 | |||
1179 | static ssize_t | ||
1180 | qeth_dev_ipato_add_store(const char *buf, size_t count, | ||
1181 | struct qeth_card *card, enum qeth_prot_versions proto) | ||
1182 | { | ||
1183 | struct qeth_ipato_entry *ipatoe; | ||
1184 | u8 addr[16]; | ||
1185 | int mask_bits; | ||
1186 | int rc; | ||
1187 | |||
1188 | if (qeth_check_layer2(card)) | ||
1189 | return -EPERM; | ||
1190 | if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) | ||
1191 | return rc; | ||
1192 | |||
1193 | if (!(ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){ | ||
1194 | PRINT_WARN("No memory to allocate ipato entry\n"); | ||
1195 | return -ENOMEM; | ||
1196 | } | ||
1197 | ipatoe->proto = proto; | ||
1198 | memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16); | ||
1199 | ipatoe->mask_bits = mask_bits; | ||
1200 | |||
1201 | if ((rc = qeth_add_ipato_entry(card, ipatoe))){ | ||
1202 | kfree(ipatoe); | ||
1203 | return rc; | ||
1204 | } | ||
1205 | |||
1206 | return count; | ||
1207 | } | ||
1208 | |||
1209 | static ssize_t | ||
1210 | qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1211 | { | ||
1212 | struct qeth_card *card = dev->driver_data; | ||
1213 | |||
1214 | if (!card) | ||
1215 | return -EINVAL; | ||
1216 | |||
1217 | return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4); | ||
1218 | } | ||
1219 | |||
1220 | static QETH_DEVICE_ATTR(ipato_add4, add4, 0644, | ||
1221 | qeth_dev_ipato_add4_show, | ||
1222 | qeth_dev_ipato_add4_store); | ||
1223 | |||
1224 | static ssize_t | ||
1225 | qeth_dev_ipato_del_store(const char *buf, size_t count, | ||
1226 | struct qeth_card *card, enum qeth_prot_versions proto) | ||
1227 | { | ||
1228 | u8 addr[16]; | ||
1229 | int mask_bits; | ||
1230 | int rc; | ||
1231 | |||
1232 | if (qeth_check_layer2(card)) | ||
1233 | return -EPERM; | ||
1234 | if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) | ||
1235 | return rc; | ||
1236 | |||
1237 | qeth_del_ipato_entry(card, proto, addr, mask_bits); | ||
1238 | |||
1239 | return count; | ||
1240 | } | ||
1241 | |||
1242 | static ssize_t | ||
1243 | qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1244 | { | ||
1245 | struct qeth_card *card = dev->driver_data; | ||
1246 | |||
1247 | if (!card) | ||
1248 | return -EINVAL; | ||
1249 | |||
1250 | return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4); | ||
1251 | } | ||
1252 | |||
1253 | static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL, | ||
1254 | qeth_dev_ipato_del4_store); | ||
1255 | |||
1256 | #ifdef CONFIG_QETH_IPV6 | ||
1257 | static ssize_t | ||
1258 | qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1259 | { | ||
1260 | struct qeth_card *card = dev->driver_data; | ||
1261 | |||
1262 | if (!card) | ||
1263 | return -EINVAL; | ||
1264 | |||
1265 | if (qeth_check_layer2(card)) | ||
1266 | return -EPERM; | ||
1267 | |||
1268 | return sprintf(buf, "%i\n", card->ipato.invert6? 1:0); | ||
1269 | } | ||
1270 | |||
1271 | static ssize_t | ||
1272 | qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1273 | { | ||
1274 | struct qeth_card *card = dev->driver_data; | ||
1275 | char *tmp; | ||
1276 | |||
1277 | if (!card) | ||
1278 | return -EINVAL; | ||
1279 | |||
1280 | if (qeth_check_layer2(card)) | ||
1281 | return -EPERM; | ||
1282 | |||
1283 | tmp = strsep((char **) &buf, "\n"); | ||
1284 | if (!strcmp(tmp, "toggle")){ | ||
1285 | card->ipato.invert6 = (card->ipato.invert6)? 0 : 1; | ||
1286 | } else if (!strcmp(tmp, "1")){ | ||
1287 | card->ipato.invert6 = 1; | ||
1288 | } else if (!strcmp(tmp, "0")){ | ||
1289 | card->ipato.invert6 = 0; | ||
1290 | } else { | ||
1291 | PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to " | ||
1292 | "this file\n"); | ||
1293 | return -EINVAL; | ||
1294 | } | ||
1295 | return count; | ||
1296 | } | ||
1297 | |||
1298 | static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644, | ||
1299 | qeth_dev_ipato_invert6_show, | ||
1300 | qeth_dev_ipato_invert6_store); | ||
1301 | |||
1302 | |||
1303 | static ssize_t | ||
1304 | qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1305 | { | ||
1306 | struct qeth_card *card = dev->driver_data; | ||
1307 | |||
1308 | if (!card) | ||
1309 | return -EINVAL; | ||
1310 | |||
1311 | return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6); | ||
1312 | } | ||
1313 | |||
1314 | static ssize_t | ||
1315 | qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1316 | { | ||
1317 | struct qeth_card *card = dev->driver_data; | ||
1318 | |||
1319 | if (!card) | ||
1320 | return -EINVAL; | ||
1321 | |||
1322 | return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6); | ||
1323 | } | ||
1324 | |||
1325 | static QETH_DEVICE_ATTR(ipato_add6, add6, 0644, | ||
1326 | qeth_dev_ipato_add6_show, | ||
1327 | qeth_dev_ipato_add6_store); | ||
1328 | |||
1329 | static ssize_t | ||
1330 | qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1331 | { | ||
1332 | struct qeth_card *card = dev->driver_data; | ||
1333 | |||
1334 | if (!card) | ||
1335 | return -EINVAL; | ||
1336 | |||
1337 | return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6); | ||
1338 | } | ||
1339 | |||
1340 | static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL, | ||
1341 | qeth_dev_ipato_del6_store); | ||
1342 | #endif /* CONFIG_QETH_IPV6 */ | ||
1343 | |||
1344 | static struct device_attribute * qeth_ipato_device_attrs[] = { | ||
1345 | &dev_attr_ipato_enable, | ||
1346 | &dev_attr_ipato_invert4, | ||
1347 | &dev_attr_ipato_add4, | ||
1348 | &dev_attr_ipato_del4, | ||
1349 | #ifdef CONFIG_QETH_IPV6 | ||
1350 | &dev_attr_ipato_invert6, | ||
1351 | &dev_attr_ipato_add6, | ||
1352 | &dev_attr_ipato_del6, | ||
1353 | #endif | ||
1354 | NULL, | ||
1355 | }; | ||
1356 | |||
1357 | static struct attribute_group qeth_device_ipato_group = { | ||
1358 | .name = "ipa_takeover", | ||
1359 | .attrs = (struct attribute **)qeth_ipato_device_attrs, | ||
1360 | }; | ||
1361 | |||
1362 | static ssize_t | ||
1363 | qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, | ||
1364 | enum qeth_prot_versions proto) | ||
1365 | { | ||
1366 | struct qeth_ipaddr *ipaddr; | ||
1367 | char addr_str[40]; | ||
1368 | int entry_len; /* length of 1 entry string, differs between v4 and v6 */ | ||
1369 | unsigned long flags; | ||
1370 | int i = 0; | ||
1371 | |||
1372 | if (qeth_check_layer2(card)) | ||
1373 | return -EPERM; | ||
1374 | |||
1375 | entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; | ||
1376 | entry_len += 2; /* \n + terminator */ | ||
1377 | spin_lock_irqsave(&card->ip_lock, flags); | ||
1378 | list_for_each_entry(ipaddr, &card->ip_list, entry){ | ||
1379 | if (ipaddr->proto != proto) | ||
1380 | continue; | ||
1381 | if (ipaddr->type != QETH_IP_TYPE_VIPA) | ||
1382 | continue; | ||
1383 | /* String must not be longer than PAGE_SIZE. So we check if | ||
1384 | * string length gets near PAGE_SIZE. Then we can savely display | ||
1385 | * the next IPv6 address (worst case, compared to IPv4) */ | ||
1386 | if ((PAGE_SIZE - i) <= entry_len) | ||
1387 | break; | ||
1388 | qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str); | ||
1389 | i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); | ||
1390 | } | ||
1391 | spin_unlock_irqrestore(&card->ip_lock, flags); | ||
1392 | i += snprintf(buf + i, PAGE_SIZE - i, "\n"); | ||
1393 | |||
1394 | return i; | ||
1395 | } | ||
1396 | |||
1397 | static ssize_t | ||
1398 | qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1399 | { | ||
1400 | struct qeth_card *card = dev->driver_data; | ||
1401 | |||
1402 | if (!card) | ||
1403 | return -EINVAL; | ||
1404 | |||
1405 | return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4); | ||
1406 | } | ||
1407 | |||
1408 | static int | ||
1409 | qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto, | ||
1410 | u8 *addr) | ||
1411 | { | ||
1412 | if (qeth_string_to_ipaddr(buf, proto, addr)){ | ||
1413 | PRINT_WARN("Invalid IP address format!\n"); | ||
1414 | return -EINVAL; | ||
1415 | } | ||
1416 | return 0; | ||
1417 | } | ||
1418 | |||
1419 | static ssize_t | ||
1420 | qeth_dev_vipa_add_store(const char *buf, size_t count, | ||
1421 | struct qeth_card *card, enum qeth_prot_versions proto) | ||
1422 | { | ||
1423 | u8 addr[16] = {0, }; | ||
1424 | int rc; | ||
1425 | |||
1426 | if (qeth_check_layer2(card)) | ||
1427 | return -EPERM; | ||
1428 | if ((rc = qeth_parse_vipae(buf, proto, addr))) | ||
1429 | return rc; | ||
1430 | |||
1431 | if ((rc = qeth_add_vipa(card, proto, addr))) | ||
1432 | return rc; | ||
1433 | |||
1434 | return count; | ||
1435 | } | ||
1436 | |||
1437 | static ssize_t | ||
1438 | qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1439 | { | ||
1440 | struct qeth_card *card = dev->driver_data; | ||
1441 | |||
1442 | if (!card) | ||
1443 | return -EINVAL; | ||
1444 | |||
1445 | return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4); | ||
1446 | } | ||
1447 | |||
1448 | static QETH_DEVICE_ATTR(vipa_add4, add4, 0644, | ||
1449 | qeth_dev_vipa_add4_show, | ||
1450 | qeth_dev_vipa_add4_store); | ||
1451 | |||
1452 | static ssize_t | ||
1453 | qeth_dev_vipa_del_store(const char *buf, size_t count, | ||
1454 | struct qeth_card *card, enum qeth_prot_versions proto) | ||
1455 | { | ||
1456 | u8 addr[16]; | ||
1457 | int rc; | ||
1458 | |||
1459 | if (qeth_check_layer2(card)) | ||
1460 | return -EPERM; | ||
1461 | if ((rc = qeth_parse_vipae(buf, proto, addr))) | ||
1462 | return rc; | ||
1463 | |||
1464 | qeth_del_vipa(card, proto, addr); | ||
1465 | |||
1466 | return count; | ||
1467 | } | ||
1468 | |||
1469 | static ssize_t | ||
1470 | qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1471 | { | ||
1472 | struct qeth_card *card = dev->driver_data; | ||
1473 | |||
1474 | if (!card) | ||
1475 | return -EINVAL; | ||
1476 | |||
1477 | return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4); | ||
1478 | } | ||
1479 | |||
1480 | static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL, | ||
1481 | qeth_dev_vipa_del4_store); | ||
1482 | |||
1483 | #ifdef CONFIG_QETH_IPV6 | ||
1484 | static ssize_t | ||
1485 | qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1486 | { | ||
1487 | struct qeth_card *card = dev->driver_data; | ||
1488 | |||
1489 | if (!card) | ||
1490 | return -EINVAL; | ||
1491 | |||
1492 | return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6); | ||
1493 | } | ||
1494 | |||
1495 | static ssize_t | ||
1496 | qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1497 | { | ||
1498 | struct qeth_card *card = dev->driver_data; | ||
1499 | |||
1500 | if (!card) | ||
1501 | return -EINVAL; | ||
1502 | |||
1503 | return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6); | ||
1504 | } | ||
1505 | |||
1506 | static QETH_DEVICE_ATTR(vipa_add6, add6, 0644, | ||
1507 | qeth_dev_vipa_add6_show, | ||
1508 | qeth_dev_vipa_add6_store); | ||
1509 | |||
1510 | static ssize_t | ||
1511 | qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1512 | { | ||
1513 | struct qeth_card *card = dev->driver_data; | ||
1514 | |||
1515 | if (!card) | ||
1516 | return -EINVAL; | ||
1517 | |||
1518 | if (qeth_check_layer2(card)) | ||
1519 | return -EPERM; | ||
1520 | |||
1521 | return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6); | ||
1522 | } | ||
1523 | |||
1524 | static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL, | ||
1525 | qeth_dev_vipa_del6_store); | ||
1526 | #endif /* CONFIG_QETH_IPV6 */ | ||
1527 | |||
1528 | static struct device_attribute * qeth_vipa_device_attrs[] = { | ||
1529 | &dev_attr_vipa_add4, | ||
1530 | &dev_attr_vipa_del4, | ||
1531 | #ifdef CONFIG_QETH_IPV6 | ||
1532 | &dev_attr_vipa_add6, | ||
1533 | &dev_attr_vipa_del6, | ||
1534 | #endif | ||
1535 | NULL, | ||
1536 | }; | ||
1537 | |||
1538 | static struct attribute_group qeth_device_vipa_group = { | ||
1539 | .name = "vipa", | ||
1540 | .attrs = (struct attribute **)qeth_vipa_device_attrs, | ||
1541 | }; | ||
1542 | |||
1543 | static ssize_t | ||
1544 | qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, | ||
1545 | enum qeth_prot_versions proto) | ||
1546 | { | ||
1547 | struct qeth_ipaddr *ipaddr; | ||
1548 | char addr_str[40]; | ||
1549 | int entry_len; /* length of 1 entry string, differs between v4 and v6 */ | ||
1550 | unsigned long flags; | ||
1551 | int i = 0; | ||
1552 | |||
1553 | if (qeth_check_layer2(card)) | ||
1554 | return -EPERM; | ||
1555 | |||
1556 | entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; | ||
1557 | entry_len += 2; /* \n + terminator */ | ||
1558 | spin_lock_irqsave(&card->ip_lock, flags); | ||
1559 | list_for_each_entry(ipaddr, &card->ip_list, entry){ | ||
1560 | if (ipaddr->proto != proto) | ||
1561 | continue; | ||
1562 | if (ipaddr->type != QETH_IP_TYPE_RXIP) | ||
1563 | continue; | ||
1564 | /* String must not be longer than PAGE_SIZE. So we check if | ||
1565 | * string length gets near PAGE_SIZE. Then we can savely display | ||
1566 | * the next IPv6 address (worst case, compared to IPv4) */ | ||
1567 | if ((PAGE_SIZE - i) <= entry_len) | ||
1568 | break; | ||
1569 | qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str); | ||
1570 | i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); | ||
1571 | } | ||
1572 | spin_unlock_irqrestore(&card->ip_lock, flags); | ||
1573 | i += snprintf(buf + i, PAGE_SIZE - i, "\n"); | ||
1574 | |||
1575 | return i; | ||
1576 | } | ||
1577 | |||
1578 | static ssize_t | ||
1579 | qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1580 | { | ||
1581 | struct qeth_card *card = dev->driver_data; | ||
1582 | |||
1583 | if (!card) | ||
1584 | return -EINVAL; | ||
1585 | |||
1586 | return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4); | ||
1587 | } | ||
1588 | |||
1589 | static int | ||
1590 | qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto, | ||
1591 | u8 *addr) | ||
1592 | { | ||
1593 | if (qeth_string_to_ipaddr(buf, proto, addr)){ | ||
1594 | PRINT_WARN("Invalid IP address format!\n"); | ||
1595 | return -EINVAL; | ||
1596 | } | ||
1597 | return 0; | ||
1598 | } | ||
1599 | |||
1600 | static ssize_t | ||
1601 | qeth_dev_rxip_add_store(const char *buf, size_t count, | ||
1602 | struct qeth_card *card, enum qeth_prot_versions proto) | ||
1603 | { | ||
1604 | u8 addr[16] = {0, }; | ||
1605 | int rc; | ||
1606 | |||
1607 | if (qeth_check_layer2(card)) | ||
1608 | return -EPERM; | ||
1609 | if ((rc = qeth_parse_rxipe(buf, proto, addr))) | ||
1610 | return rc; | ||
1611 | |||
1612 | if ((rc = qeth_add_rxip(card, proto, addr))) | ||
1613 | return rc; | ||
1614 | |||
1615 | return count; | ||
1616 | } | ||
1617 | |||
1618 | static ssize_t | ||
1619 | qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1620 | { | ||
1621 | struct qeth_card *card = dev->driver_data; | ||
1622 | |||
1623 | if (!card) | ||
1624 | return -EINVAL; | ||
1625 | |||
1626 | return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4); | ||
1627 | } | ||
1628 | |||
1629 | static QETH_DEVICE_ATTR(rxip_add4, add4, 0644, | ||
1630 | qeth_dev_rxip_add4_show, | ||
1631 | qeth_dev_rxip_add4_store); | ||
1632 | |||
1633 | static ssize_t | ||
1634 | qeth_dev_rxip_del_store(const char *buf, size_t count, | ||
1635 | struct qeth_card *card, enum qeth_prot_versions proto) | ||
1636 | { | ||
1637 | u8 addr[16]; | ||
1638 | int rc; | ||
1639 | |||
1640 | if (qeth_check_layer2(card)) | ||
1641 | return -EPERM; | ||
1642 | if ((rc = qeth_parse_rxipe(buf, proto, addr))) | ||
1643 | return rc; | ||
1644 | |||
1645 | qeth_del_rxip(card, proto, addr); | ||
1646 | |||
1647 | return count; | ||
1648 | } | ||
1649 | |||
1650 | static ssize_t | ||
1651 | qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1652 | { | ||
1653 | struct qeth_card *card = dev->driver_data; | ||
1654 | |||
1655 | if (!card) | ||
1656 | return -EINVAL; | ||
1657 | |||
1658 | return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4); | ||
1659 | } | ||
1660 | |||
1661 | static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL, | ||
1662 | qeth_dev_rxip_del4_store); | ||
1663 | |||
1664 | #ifdef CONFIG_QETH_IPV6 | ||
1665 | static ssize_t | ||
1666 | qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1667 | { | ||
1668 | struct qeth_card *card = dev->driver_data; | ||
1669 | |||
1670 | if (!card) | ||
1671 | return -EINVAL; | ||
1672 | |||
1673 | return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6); | ||
1674 | } | ||
1675 | |||
1676 | static ssize_t | ||
1677 | qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1678 | { | ||
1679 | struct qeth_card *card = dev->driver_data; | ||
1680 | |||
1681 | if (!card) | ||
1682 | return -EINVAL; | ||
1683 | |||
1684 | return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6); | ||
1685 | } | ||
1686 | |||
1687 | static QETH_DEVICE_ATTR(rxip_add6, add6, 0644, | ||
1688 | qeth_dev_rxip_add6_show, | ||
1689 | qeth_dev_rxip_add6_store); | ||
1690 | |||
1691 | static ssize_t | ||
1692 | qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
1693 | { | ||
1694 | struct qeth_card *card = dev->driver_data; | ||
1695 | |||
1696 | if (!card) | ||
1697 | return -EINVAL; | ||
1698 | |||
1699 | return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6); | ||
1700 | } | ||
1701 | |||
1702 | static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL, | ||
1703 | qeth_dev_rxip_del6_store); | ||
1704 | #endif /* CONFIG_QETH_IPV6 */ | ||
1705 | |||
1706 | static struct device_attribute * qeth_rxip_device_attrs[] = { | ||
1707 | &dev_attr_rxip_add4, | ||
1708 | &dev_attr_rxip_del4, | ||
1709 | #ifdef CONFIG_QETH_IPV6 | ||
1710 | &dev_attr_rxip_add6, | ||
1711 | &dev_attr_rxip_del6, | ||
1712 | #endif | ||
1713 | NULL, | ||
1714 | }; | ||
1715 | |||
1716 | static struct attribute_group qeth_device_rxip_group = { | ||
1717 | .name = "rxip", | ||
1718 | .attrs = (struct attribute **)qeth_rxip_device_attrs, | ||
1719 | }; | ||
1720 | |||
1721 | int | ||
1722 | qeth_create_device_attributes(struct device *dev) | ||
1723 | { | ||
1724 | int ret; | ||
1725 | struct qeth_card *card = dev->driver_data; | ||
1726 | |||
1727 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
1728 | return sysfs_create_group(&dev->kobj, | ||
1729 | &qeth_osn_device_attr_group); | ||
1730 | |||
1731 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group))) | ||
1732 | return ret; | ||
1733 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){ | ||
1734 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
1735 | return ret; | ||
1736 | } | ||
1737 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group))){ | ||
1738 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
1739 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); | ||
1740 | return ret; | ||
1741 | } | ||
1742 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group))){ | ||
1743 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
1744 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); | ||
1745 | sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); | ||
1746 | return ret; | ||
1747 | } | ||
1748 | if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){ | ||
1749 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
1750 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); | ||
1751 | sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); | ||
1752 | sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group); | ||
1753 | return ret; | ||
1754 | } | ||
1755 | return 0; | ||
1756 | } | ||
1757 | |||
1758 | void | ||
1759 | qeth_remove_device_attributes(struct device *dev) | ||
1760 | { | ||
1761 | struct qeth_card *card = dev->driver_data; | ||
1762 | |||
1763 | if (card->info.type == QETH_CARD_TYPE_OSN) { | ||
1764 | sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group); | ||
1765 | return; | ||
1766 | } | ||
1767 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
1768 | sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); | ||
1769 | sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); | ||
1770 | sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group); | ||
1771 | sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group); | ||
1772 | } | ||
1773 | |||
1774 | /**********************/ | ||
1775 | /* DRIVER ATTRIBUTES */ | ||
1776 | /**********************/ | ||
1777 | static ssize_t | ||
1778 | qeth_driver_group_store(struct device_driver *ddrv, const char *buf, | ||
1779 | size_t count) | ||
1780 | { | ||
1781 | const char *start, *end; | ||
1782 | char bus_ids[3][BUS_ID_SIZE], *argv[3]; | ||
1783 | int i; | ||
1784 | int err; | ||
1785 | |||
1786 | start = buf; | ||
1787 | for (i = 0; i < 3; i++) { | ||
1788 | static const char delim[] = { ',', ',', '\n' }; | ||
1789 | int len; | ||
1790 | |||
1791 | if (!(end = strchr(start, delim[i]))) | ||
1792 | return -EINVAL; | ||
1793 | len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start); | ||
1794 | strncpy(bus_ids[i], start, len); | ||
1795 | bus_ids[i][len] = '\0'; | ||
1796 | start = end + 1; | ||
1797 | argv[i] = bus_ids[i]; | ||
1798 | } | ||
1799 | err = ccwgroup_create(qeth_root_dev, qeth_ccwgroup_driver.driver_id, | ||
1800 | &qeth_ccw_driver, 3, argv); | ||
1801 | if (err) | ||
1802 | return err; | ||
1803 | else | ||
1804 | return count; | ||
1805 | } | ||
1806 | |||
1807 | |||
1808 | static DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store); | ||
1809 | |||
1810 | static ssize_t | ||
1811 | qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf, | ||
1812 | size_t count) | ||
1813 | { | ||
1814 | int rc; | ||
1815 | int signum; | ||
1816 | char *tmp, *tmp2; | ||
1817 | |||
1818 | tmp = strsep((char **) &buf, "\n"); | ||
1819 | if (!strncmp(tmp, "unregister", 10)){ | ||
1820 | if ((rc = qeth_notifier_unregister(current))) | ||
1821 | return rc; | ||
1822 | return count; | ||
1823 | } | ||
1824 | |||
1825 | signum = simple_strtoul(tmp, &tmp2, 10); | ||
1826 | if ((signum < 0) || (signum > 32)){ | ||
1827 | PRINT_WARN("Signal number %d is out of range\n", signum); | ||
1828 | return -EINVAL; | ||
1829 | } | ||
1830 | if ((rc = qeth_notifier_register(current, signum))) | ||
1831 | return rc; | ||
1832 | |||
1833 | return count; | ||
1834 | } | ||
1835 | |||
1836 | static DRIVER_ATTR(notifier_register, 0200, NULL, | ||
1837 | qeth_driver_notifier_register_store); | ||
1838 | |||
1839 | int | ||
1840 | qeth_create_driver_attributes(void) | ||
1841 | { | ||
1842 | int rc; | ||
1843 | |||
1844 | if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver, | ||
1845 | &driver_attr_group))) | ||
1846 | return rc; | ||
1847 | return driver_create_file(&qeth_ccwgroup_driver.driver, | ||
1848 | &driver_attr_notifier_register); | ||
1849 | } | ||
1850 | |||
1851 | void | ||
1852 | qeth_remove_driver_attributes(void) | ||
1853 | { | ||
1854 | driver_remove_file(&qeth_ccwgroup_driver.driver, | ||
1855 | &driver_attr_group); | ||
1856 | driver_remove_file(&qeth_ccwgroup_driver.driver, | ||
1857 | &driver_attr_notifier_register); | ||
1858 | } | ||