blob: 69425a7a6e98a5b71f4fbb6df2826ad61c1bb2a7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Michael Holzheu66a464d2005-06-25 14:55:33 -07002 * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * IUCV network driver
5 *
6 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
8 *
9 * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com)
10 *
11 * Documentation used:
12 * the source of the original IUCV driver by:
13 * Stefan Hegewald <hegewald@de.ibm.com>
14 * Hartmut Penner <hpenner@de.ibm.com>
15 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
16 * Martin Schwidefsky (schwidefsky@de.ibm.com)
17 * Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2, or (at your option)
22 * any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 *
Michael Holzheu66a464d2005-06-25 14:55:33 -070033 * RELEASE-TAG: IUCV network driver $Revision: 1.66 $
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 *
35 */
36
37#undef DEBUG
38
39#include <linux/module.h>
40#include <linux/init.h>
41#include <linux/kernel.h>
42#include <linux/slab.h>
43#include <linux/errno.h>
44#include <linux/types.h>
45#include <linux/interrupt.h>
46#include <linux/timer.h>
47#include <linux/sched.h>
48#include <linux/bitops.h>
49
50#include <linux/signal.h>
51#include <linux/string.h>
52#include <linux/device.h>
53
54#include <linux/ip.h>
55#include <linux/if_arp.h>
56#include <linux/tcp.h>
57#include <linux/skbuff.h>
58#include <linux/ctype.h>
59#include <net/dst.h>
60
61#include <asm/io.h>
62#include <asm/uaccess.h>
63
64#include "iucv.h"
65#include "fsm.h"
66
67MODULE_AUTHOR
68 ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
69MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
70
71
72#define PRINTK_HEADER " iucv: " /* for debugging */
73
74static struct device_driver netiucv_driver = {
75 .name = "netiucv",
76 .bus = &iucv_bus,
77};
78
79/**
80 * Per connection profiling data
81 */
82struct connection_profile {
83 unsigned long maxmulti;
84 unsigned long maxcqueue;
85 unsigned long doios_single;
86 unsigned long doios_multi;
87 unsigned long txlen;
88 unsigned long tx_time;
89 struct timespec send_stamp;
90 unsigned long tx_pending;
91 unsigned long tx_max_pending;
92};
93
94/**
95 * Representation of one iucv connection
96 */
97struct iucv_connection {
98 struct iucv_connection *next;
99 iucv_handle_t handle;
100 __u16 pathid;
101 struct sk_buff *rx_buff;
102 struct sk_buff *tx_buff;
103 struct sk_buff_head collect_queue;
104 struct sk_buff_head commit_queue;
105 spinlock_t collect_lock;
106 int collect_len;
107 int max_buffsize;
108 fsm_timer timer;
109 fsm_instance *fsm;
110 struct net_device *netdev;
111 struct connection_profile prof;
112 char userid[9];
113};
114
115/**
116 * Linked list of all connection structs.
117 */
118static struct iucv_connection *iucv_connections;
119
120/**
121 * Representation of event-data for the
122 * connection state machine.
123 */
124struct iucv_event {
125 struct iucv_connection *conn;
126 void *data;
127};
128
129/**
130 * Private part of the network device structure
131 */
132struct netiucv_priv {
133 struct net_device_stats stats;
134 unsigned long tbusy;
135 fsm_instance *fsm;
136 struct iucv_connection *conn;
137 struct device *dev;
138};
139
140/**
141 * Link level header for a packet.
142 */
143typedef struct ll_header_t {
144 __u16 next;
145} ll_header;
146
147#define NETIUCV_HDRLEN (sizeof(ll_header))
148#define NETIUCV_BUFSIZE_MAX 32768
149#define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX
150#define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)
151#define NETIUCV_MTU_DEFAULT 9216
152#define NETIUCV_QUEUELEN_DEFAULT 50
153#define NETIUCV_TIMEOUT_5SEC 5000
154
155/**
156 * Compatibility macros for busy handling
157 * of network devices.
158 */
159static __inline__ void netiucv_clear_busy(struct net_device *dev)
160{
161 clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy));
162 netif_wake_queue(dev);
163}
164
165static __inline__ int netiucv_test_and_set_busy(struct net_device *dev)
166{
167 netif_stop_queue(dev);
168 return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);
169}
170
171static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
172static __u8 iucvMagic[16] = {
173 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
174 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
175};
176
177/**
178 * This mask means the 16-byte IUCV "magic" and the origin userid must
179 * match exactly as specified in order to give connection_pending()
180 * control.
181 */
182static __u8 netiucv_mask[] = {
183 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
184 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
185 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
186};
187
188/**
189 * Convert an iucv userId to its printable
190 * form (strip whitespace at end).
191 *
192 * @param An iucv userId
193 *
194 * @returns The printable string (static data!!)
195 */
196static __inline__ char *
197netiucv_printname(char *name)
198{
199 static char tmp[9];
200 char *p = tmp;
201 memcpy(tmp, name, 8);
202 tmp[8] = '\0';
203 while (*p && (!isspace(*p)))
204 p++;
205 *p = '\0';
206 return tmp;
207}
208
209/**
210 * States of the interface statemachine.
211 */
212enum dev_states {
213 DEV_STATE_STOPPED,
214 DEV_STATE_STARTWAIT,
215 DEV_STATE_STOPWAIT,
216 DEV_STATE_RUNNING,
217 /**
218 * MUST be always the last element!!
219 */
220 NR_DEV_STATES
221};
222
223static const char *dev_state_names[] = {
224 "Stopped",
225 "StartWait",
226 "StopWait",
227 "Running",
228};
229
230/**
231 * Events of the interface statemachine.
232 */
233enum dev_events {
234 DEV_EVENT_START,
235 DEV_EVENT_STOP,
236 DEV_EVENT_CONUP,
237 DEV_EVENT_CONDOWN,
238 /**
239 * MUST be always the last element!!
240 */
241 NR_DEV_EVENTS
242};
243
244static const char *dev_event_names[] = {
245 "Start",
246 "Stop",
247 "Connection up",
248 "Connection down",
249};
250
251/**
252 * Events of the connection statemachine
253 */
254enum conn_events {
255 /**
256 * Events, representing callbacks from
257 * lowlevel iucv layer)
258 */
259 CONN_EVENT_CONN_REQ,
260 CONN_EVENT_CONN_ACK,
261 CONN_EVENT_CONN_REJ,
262 CONN_EVENT_CONN_SUS,
263 CONN_EVENT_CONN_RES,
264 CONN_EVENT_RX,
265 CONN_EVENT_TXDONE,
266
267 /**
268 * Events, representing errors return codes from
269 * calls to lowlevel iucv layer
270 */
271
272 /**
273 * Event, representing timer expiry.
274 */
275 CONN_EVENT_TIMER,
276
277 /**
278 * Events, representing commands from upper levels.
279 */
280 CONN_EVENT_START,
281 CONN_EVENT_STOP,
282
283 /**
284 * MUST be always the last element!!
285 */
286 NR_CONN_EVENTS,
287};
288
289static const char *conn_event_names[] = {
290 "Remote connection request",
291 "Remote connection acknowledge",
292 "Remote connection reject",
293 "Connection suspended",
294 "Connection resumed",
295 "Data received",
296 "Data sent",
297
298 "Timer",
299
300 "Start",
301 "Stop",
302};
303
304/**
305 * States of the connection statemachine.
306 */
307enum conn_states {
308 /**
309 * Connection not assigned to any device,
310 * initial state, invalid
311 */
312 CONN_STATE_INVALID,
313
314 /**
315 * Userid assigned but not operating
316 */
317 CONN_STATE_STOPPED,
318
319 /**
320 * Connection registered,
321 * no connection request sent yet,
322 * no connection request received
323 */
324 CONN_STATE_STARTWAIT,
325
326 /**
327 * Connection registered and connection request sent,
328 * no acknowledge and no connection request received yet.
329 */
330 CONN_STATE_SETUPWAIT,
331
332 /**
333 * Connection up and running idle
334 */
335 CONN_STATE_IDLE,
336
337 /**
338 * Data sent, awaiting CONN_EVENT_TXDONE
339 */
340 CONN_STATE_TX,
341
342 /**
343 * Error during registration.
344 */
345 CONN_STATE_REGERR,
346
347 /**
348 * Error during registration.
349 */
350 CONN_STATE_CONNERR,
351
352 /**
353 * MUST be always the last element!!
354 */
355 NR_CONN_STATES,
356};
357
358static const char *conn_state_names[] = {
359 "Invalid",
360 "Stopped",
361 "StartWait",
362 "SetupWait",
363 "Idle",
364 "TX",
365 "Terminating",
366 "Registration error",
367 "Connect error",
368};
369
370
371/**
372 * Debug Facility Stuff
373 */
374static debug_info_t *iucv_dbf_setup = NULL;
375static debug_info_t *iucv_dbf_data = NULL;
376static debug_info_t *iucv_dbf_trace = NULL;
377
378DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);
379
380static void
381iucv_unregister_dbf_views(void)
382{
383 if (iucv_dbf_setup)
384 debug_unregister(iucv_dbf_setup);
385 if (iucv_dbf_data)
386 debug_unregister(iucv_dbf_data);
387 if (iucv_dbf_trace)
388 debug_unregister(iucv_dbf_trace);
389}
390static int
391iucv_register_dbf_views(void)
392{
393 iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
Michael Holzheu66a464d2005-06-25 14:55:33 -0700394 IUCV_DBF_SETUP_PAGES,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 IUCV_DBF_SETUP_NR_AREAS,
396 IUCV_DBF_SETUP_LEN);
397 iucv_dbf_data = debug_register(IUCV_DBF_DATA_NAME,
Michael Holzheu66a464d2005-06-25 14:55:33 -0700398 IUCV_DBF_DATA_PAGES,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 IUCV_DBF_DATA_NR_AREAS,
400 IUCV_DBF_DATA_LEN);
401 iucv_dbf_trace = debug_register(IUCV_DBF_TRACE_NAME,
Michael Holzheu66a464d2005-06-25 14:55:33 -0700402 IUCV_DBF_TRACE_PAGES,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 IUCV_DBF_TRACE_NR_AREAS,
404 IUCV_DBF_TRACE_LEN);
405
406 if ((iucv_dbf_setup == NULL) || (iucv_dbf_data == NULL) ||
407 (iucv_dbf_trace == NULL)) {
408 iucv_unregister_dbf_views();
409 return -ENOMEM;
410 }
411 debug_register_view(iucv_dbf_setup, &debug_hex_ascii_view);
412 debug_set_level(iucv_dbf_setup, IUCV_DBF_SETUP_LEVEL);
413
414 debug_register_view(iucv_dbf_data, &debug_hex_ascii_view);
415 debug_set_level(iucv_dbf_data, IUCV_DBF_DATA_LEVEL);
416
417 debug_register_view(iucv_dbf_trace, &debug_hex_ascii_view);
418 debug_set_level(iucv_dbf_trace, IUCV_DBF_TRACE_LEVEL);
419
420 return 0;
421}
422
423/**
424 * Callback-wrappers, called from lowlevel iucv layer.
425 *****************************************************************************/
426
427static void
428netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
429{
430 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
431 struct iucv_event ev;
432
433 ev.conn = conn;
434 ev.data = (void *)eib;
435
436 fsm_event(conn->fsm, CONN_EVENT_RX, &ev);
437}
438
439static void
440netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
441{
442 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
443 struct iucv_event ev;
444
445 ev.conn = conn;
446 ev.data = (void *)eib;
447 fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);
448}
449
450static void
451netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
452{
453 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
454 struct iucv_event ev;
455
456 ev.conn = conn;
457 ev.data = (void *)eib;
458 fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);
459}
460
461static void
462netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
463{
464 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
465 struct iucv_event ev;
466
467 ev.conn = conn;
468 ev.data = (void *)eib;
469 fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
470}
471
472static void
473netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
474{
475 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
476 struct iucv_event ev;
477
478 ev.conn = conn;
479 ev.data = (void *)eib;
480 fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, &ev);
481}
482
483static void
484netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
485{
486 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
487 struct iucv_event ev;
488
489 ev.conn = conn;
490 ev.data = (void *)eib;
491 fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, &ev);
492}
493
494static void
495netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
496{
497 struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
498 struct iucv_event ev;
499
500 ev.conn = conn;
501 ev.data = (void *)eib;
502 fsm_event(conn->fsm, CONN_EVENT_CONN_RES, &ev);
503}
504
505static iucv_interrupt_ops_t netiucv_ops = {
506 .ConnectionPending = netiucv_callback_connreq,
507 .ConnectionComplete = netiucv_callback_connack,
508 .ConnectionSevered = netiucv_callback_connrej,
509 .ConnectionQuiesced = netiucv_callback_connsusp,
510 .ConnectionResumed = netiucv_callback_connres,
511 .MessagePending = netiucv_callback_rx,
512 .MessageComplete = netiucv_callback_txdone
513};
514
515/**
516 * Dummy NOP action for all statemachines
517 */
518static void
519fsm_action_nop(fsm_instance *fi, int event, void *arg)
520{
521}
522
523/**
524 * Actions of the connection statemachine
525 *****************************************************************************/
526
527/**
528 * Helper function for conn_action_rx()
529 * Unpack a just received skb and hand it over to
530 * upper layers.
531 *
532 * @param conn The connection where this skb has been received.
533 * @param pskb The received skb.
534 */
535//static __inline__ void
536static void
537netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
538{
539 struct net_device *dev = conn->netdev;
540 struct netiucv_priv *privptr = dev->priv;
541 __u16 offset = 0;
542
543 skb_put(pskb, NETIUCV_HDRLEN);
544 pskb->dev = dev;
545 pskb->ip_summed = CHECKSUM_NONE;
546 pskb->protocol = ntohs(ETH_P_IP);
547
548 while (1) {
549 struct sk_buff *skb;
550 ll_header *header = (ll_header *)pskb->data;
551
552 if (!header->next)
553 break;
554
555 skb_pull(pskb, NETIUCV_HDRLEN);
556 header->next -= offset;
557 offset += header->next;
558 header->next -= NETIUCV_HDRLEN;
559 if (skb_tailroom(pskb) < header->next) {
560 PRINT_WARN("%s: Illegal next field in iucv header: "
561 "%d > %d\n",
562 dev->name, header->next, skb_tailroom(pskb));
563 IUCV_DBF_TEXT_(data, 2, "Illegal next field: %d > %d\n",
564 header->next, skb_tailroom(pskb));
565 return;
566 }
567 skb_put(pskb, header->next);
568 pskb->mac.raw = pskb->data;
569 skb = dev_alloc_skb(pskb->len);
570 if (!skb) {
571 PRINT_WARN("%s Out of memory in netiucv_unpack_skb\n",
572 dev->name);
573 IUCV_DBF_TEXT(data, 2,
574 "Out of memory in netiucv_unpack_skb\n");
575 privptr->stats.rx_dropped++;
576 return;
577 }
578 memcpy(skb_put(skb, pskb->len), pskb->data, pskb->len);
579 skb->mac.raw = skb->data;
580 skb->dev = pskb->dev;
581 skb->protocol = pskb->protocol;
582 pskb->ip_summed = CHECKSUM_UNNECESSARY;
583 /*
584 * Since receiving is always initiated from a tasklet (in iucv.c),
585 * we must use netif_rx_ni() instead of netif_rx()
586 */
587 netif_rx_ni(skb);
588 dev->last_rx = jiffies;
589 privptr->stats.rx_packets++;
590 privptr->stats.rx_bytes += skb->len;
591 skb_pull(pskb, header->next);
592 skb_put(pskb, NETIUCV_HDRLEN);
593 }
594}
595
596static void
597conn_action_rx(fsm_instance *fi, int event, void *arg)
598{
599 struct iucv_event *ev = (struct iucv_event *)arg;
600 struct iucv_connection *conn = ev->conn;
601 iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
602 struct netiucv_priv *privptr =(struct netiucv_priv *)conn->netdev->priv;
603
604 __u32 msglen = eib->ln1msg2.ipbfln1f;
605 int rc;
606
607 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
608
609 if (!conn->netdev) {
610 /* FRITZ: How to tell iucv LL to drop the msg? */
611 PRINT_WARN("Received data for unlinked connection\n");
612 IUCV_DBF_TEXT(data, 2,
613 "Received data for unlinked connection\n");
614 return;
615 }
616 if (msglen > conn->max_buffsize) {
617 /* FRITZ: How to tell iucv LL to drop the msg? */
618 privptr->stats.rx_dropped++;
619 PRINT_WARN("msglen %d > max_buffsize %d\n",
620 msglen, conn->max_buffsize);
621 IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n",
622 msglen, conn->max_buffsize);
623 return;
624 }
625 conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head;
626 conn->rx_buff->len = 0;
627 rc = iucv_receive(conn->pathid, eib->ipmsgid, eib->iptrgcls,
628 conn->rx_buff->data, msglen, NULL, NULL, NULL);
629 if (rc || msglen < 5) {
630 privptr->stats.rx_errors++;
631 PRINT_WARN("iucv_receive returned %08x\n", rc);
632 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc);
633 return;
634 }
635 netiucv_unpack_skb(conn, conn->rx_buff);
636}
637
638static void
639conn_action_txdone(fsm_instance *fi, int event, void *arg)
640{
641 struct iucv_event *ev = (struct iucv_event *)arg;
642 struct iucv_connection *conn = ev->conn;
643 iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
644 struct netiucv_priv *privptr = NULL;
645 /* Shut up, gcc! skb is always below 2G. */
646 __u32 single_flag = eib->ipmsgtag;
647 __u32 txbytes = 0;
648 __u32 txpackets = 0;
649 __u32 stat_maxcq = 0;
650 struct sk_buff *skb;
651 unsigned long saveflags;
652 ll_header header;
653
654 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
655
656 if (conn && conn->netdev && conn->netdev->priv)
657 privptr = (struct netiucv_priv *)conn->netdev->priv;
658 conn->prof.tx_pending--;
659 if (single_flag) {
660 if ((skb = skb_dequeue(&conn->commit_queue))) {
661 atomic_dec(&skb->users);
662 dev_kfree_skb_any(skb);
663 if (privptr) {
664 privptr->stats.tx_packets++;
665 privptr->stats.tx_bytes +=
666 (skb->len - NETIUCV_HDRLEN
667 - NETIUCV_HDRLEN);
668 }
669 }
670 }
671 conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head;
672 conn->tx_buff->len = 0;
673 spin_lock_irqsave(&conn->collect_lock, saveflags);
674 while ((skb = skb_dequeue(&conn->collect_queue))) {
675 header.next = conn->tx_buff->len + skb->len + NETIUCV_HDRLEN;
676 memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
677 NETIUCV_HDRLEN);
678 memcpy(skb_put(conn->tx_buff, skb->len), skb->data, skb->len);
679 txbytes += skb->len;
680 txpackets++;
681 stat_maxcq++;
682 atomic_dec(&skb->users);
683 dev_kfree_skb_any(skb);
684 }
685 if (conn->collect_len > conn->prof.maxmulti)
686 conn->prof.maxmulti = conn->collect_len;
687 conn->collect_len = 0;
688 spin_unlock_irqrestore(&conn->collect_lock, saveflags);
689 if (conn->tx_buff->len) {
690 int rc;
691
692 header.next = 0;
693 memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
694 NETIUCV_HDRLEN);
695
696 conn->prof.send_stamp = xtime;
697 rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,
698 conn->tx_buff->data, conn->tx_buff->len);
699 conn->prof.doios_multi++;
700 conn->prof.txlen += conn->tx_buff->len;
701 conn->prof.tx_pending++;
702 if (conn->prof.tx_pending > conn->prof.tx_max_pending)
703 conn->prof.tx_max_pending = conn->prof.tx_pending;
704 if (rc) {
705 conn->prof.tx_pending--;
706 fsm_newstate(fi, CONN_STATE_IDLE);
707 if (privptr)
708 privptr->stats.tx_errors += txpackets;
709 PRINT_WARN("iucv_send returned %08x\n", rc);
710 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
711 } else {
712 if (privptr) {
713 privptr->stats.tx_packets += txpackets;
714 privptr->stats.tx_bytes += txbytes;
715 }
716 if (stat_maxcq > conn->prof.maxcqueue)
717 conn->prof.maxcqueue = stat_maxcq;
718 }
719 } else
720 fsm_newstate(fi, CONN_STATE_IDLE);
721}
722
723static void
724conn_action_connaccept(fsm_instance *fi, int event, void *arg)
725{
726 struct iucv_event *ev = (struct iucv_event *)arg;
727 struct iucv_connection *conn = ev->conn;
728 iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
729 struct net_device *netdev = conn->netdev;
730 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
731 int rc;
732 __u16 msglimit;
733 __u8 udata[16];
734
735 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
736
737 rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,
738 conn->handle, conn, NULL, &msglimit);
739 if (rc) {
740 PRINT_WARN("%s: IUCV accept failed with error %d\n",
741 netdev->name, rc);
742 IUCV_DBF_TEXT_(setup, 2, "rc %d from iucv_accept", rc);
743 return;
744 }
745 fsm_newstate(fi, CONN_STATE_IDLE);
746 conn->pathid = eib->ippathid;
747 netdev->tx_queue_len = msglimit;
748 fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
749}
750
751static void
752conn_action_connreject(fsm_instance *fi, int event, void *arg)
753{
754 struct iucv_event *ev = (struct iucv_event *)arg;
755 struct iucv_connection *conn = ev->conn;
756 struct net_device *netdev = conn->netdev;
757 iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
758 __u8 udata[16];
759
760 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
761
762 iucv_sever(eib->ippathid, udata);
763 if (eib->ippathid != conn->pathid) {
764 PRINT_INFO("%s: IR Connection Pending; "
765 "pathid %d does not match original pathid %d\n",
766 netdev->name, eib->ippathid, conn->pathid);
767 IUCV_DBF_TEXT_(data, 2,
768 "connreject: IR pathid %d, conn. pathid %d\n",
769 eib->ippathid, conn->pathid);
770 iucv_sever(conn->pathid, udata);
771 }
772}
773
774static void
775conn_action_connack(fsm_instance *fi, int event, void *arg)
776{
777 struct iucv_event *ev = (struct iucv_event *)arg;
778 struct iucv_connection *conn = ev->conn;
779 iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
780 struct net_device *netdev = conn->netdev;
781 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
782
783 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
784
785 fsm_deltimer(&conn->timer);
786 fsm_newstate(fi, CONN_STATE_IDLE);
787 if (eib->ippathid != conn->pathid) {
788 PRINT_INFO("%s: IR Connection Complete; "
789 "pathid %d does not match original pathid %d\n",
790 netdev->name, eib->ippathid, conn->pathid);
791 IUCV_DBF_TEXT_(data, 2,
792 "connack: IR pathid %d, conn. pathid %d\n",
793 eib->ippathid, conn->pathid);
794 conn->pathid = eib->ippathid;
795 }
796 netdev->tx_queue_len = eib->ipmsglim;
797 fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
798}
799
800static void
801conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
802{
803 struct iucv_connection *conn = (struct iucv_connection *)arg;
804 __u8 udata[16];
805
806 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
807
808 fsm_deltimer(&conn->timer);
809 iucv_sever(conn->pathid, udata);
810 fsm_newstate(fi, CONN_STATE_STARTWAIT);
811}
812
813static void
814conn_action_connsever(fsm_instance *fi, int event, void *arg)
815{
816 struct iucv_event *ev = (struct iucv_event *)arg;
817 struct iucv_connection *conn = ev->conn;
818 struct net_device *netdev = conn->netdev;
819 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
820 __u8 udata[16];
821
822 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
823
824 fsm_deltimer(&conn->timer);
825 iucv_sever(conn->pathid, udata);
826 PRINT_INFO("%s: Remote dropped connection\n", netdev->name);
827 IUCV_DBF_TEXT(data, 2,
828 "conn_action_connsever: Remote dropped connection\n");
829 fsm_newstate(fi, CONN_STATE_STARTWAIT);
830 fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
831}
832
833static void
834conn_action_start(fsm_instance *fi, int event, void *arg)
835{
836 struct iucv_event *ev = (struct iucv_event *)arg;
837 struct iucv_connection *conn = ev->conn;
838 __u16 msglimit;
839 int rc;
840
841 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
842
843 if (!conn->handle) {
844 IUCV_DBF_TEXT(trace, 5, "calling iucv_register_program\n");
845 conn->handle =
846 iucv_register_program(iucvMagic, conn->userid,
847 netiucv_mask,
848 &netiucv_ops, conn);
849 fsm_newstate(fi, CONN_STATE_STARTWAIT);
850 if (!conn->handle) {
851 fsm_newstate(fi, CONN_STATE_REGERR);
852 conn->handle = NULL;
853 IUCV_DBF_TEXT(setup, 2,
854 "NULL from iucv_register_program\n");
855 return;
856 }
857
858 PRINT_DEBUG("%s('%s'): registered successfully\n",
859 conn->netdev->name, conn->userid);
860 }
861
862 PRINT_DEBUG("%s('%s'): connecting ...\n",
863 conn->netdev->name, conn->userid);
864
865 /* We must set the state before calling iucv_connect because the callback
866 * handler could be called at any point after the connection request is
867 * sent */
868
869 fsm_newstate(fi, CONN_STATE_SETUPWAIT);
870 rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
871 conn->userid, iucv_host, 0, NULL, &msglimit,
872 conn->handle, conn);
873 switch (rc) {
874 case 0:
875 conn->netdev->tx_queue_len = msglimit;
876 fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
877 CONN_EVENT_TIMER, conn);
878 return;
879 case 11:
880 PRINT_INFO("%s: User %s is currently not available.\n",
881 conn->netdev->name,
882 netiucv_printname(conn->userid));
883 fsm_newstate(fi, CONN_STATE_STARTWAIT);
884 return;
885 case 12:
886 PRINT_INFO("%s: User %s is currently not ready.\n",
887 conn->netdev->name,
888 netiucv_printname(conn->userid));
889 fsm_newstate(fi, CONN_STATE_STARTWAIT);
890 return;
891 case 13:
892 PRINT_WARN("%s: Too many IUCV connections.\n",
893 conn->netdev->name);
894 fsm_newstate(fi, CONN_STATE_CONNERR);
895 break;
896 case 14:
897 PRINT_WARN(
898 "%s: User %s has too many IUCV connections.\n",
899 conn->netdev->name,
900 netiucv_printname(conn->userid));
901 fsm_newstate(fi, CONN_STATE_CONNERR);
902 break;
903 case 15:
904 PRINT_WARN(
905 "%s: No IUCV authorization in CP directory.\n",
906 conn->netdev->name);
907 fsm_newstate(fi, CONN_STATE_CONNERR);
908 break;
909 default:
910 PRINT_WARN("%s: iucv_connect returned error %d\n",
911 conn->netdev->name, rc);
912 fsm_newstate(fi, CONN_STATE_CONNERR);
913 break;
914 }
915 IUCV_DBF_TEXT_(setup, 5, "iucv_connect rc is %d\n", rc);
916 IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
917 iucv_unregister_program(conn->handle);
918 conn->handle = NULL;
919}
920
921static void
922netiucv_purge_skb_queue(struct sk_buff_head *q)
923{
924 struct sk_buff *skb;
925
926 while ((skb = skb_dequeue(q))) {
927 atomic_dec(&skb->users);
928 dev_kfree_skb_any(skb);
929 }
930}
931
932static void
933conn_action_stop(fsm_instance *fi, int event, void *arg)
934{
935 struct iucv_event *ev = (struct iucv_event *)arg;
936 struct iucv_connection *conn = ev->conn;
937 struct net_device *netdev = conn->netdev;
938 struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
939
940 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
941
942 fsm_deltimer(&conn->timer);
943 fsm_newstate(fi, CONN_STATE_STOPPED);
944 netiucv_purge_skb_queue(&conn->collect_queue);
945 if (conn->handle)
946 IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
947 iucv_unregister_program(conn->handle);
948 conn->handle = NULL;
949 netiucv_purge_skb_queue(&conn->commit_queue);
950 fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
951}
952
953static void
954conn_action_inval(fsm_instance *fi, int event, void *arg)
955{
956 struct iucv_event *ev = (struct iucv_event *)arg;
957 struct iucv_connection *conn = ev->conn;
958 struct net_device *netdev = conn->netdev;
959
960 PRINT_WARN("%s: Cannot connect without username\n",
961 netdev->name);
962 IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n");
963}
964
965static const fsm_node conn_fsm[] = {
966 { CONN_STATE_INVALID, CONN_EVENT_START, conn_action_inval },
967 { CONN_STATE_STOPPED, CONN_EVENT_START, conn_action_start },
968
969 { CONN_STATE_STOPPED, CONN_EVENT_STOP, conn_action_stop },
970 { CONN_STATE_STARTWAIT, CONN_EVENT_STOP, conn_action_stop },
971 { CONN_STATE_SETUPWAIT, CONN_EVENT_STOP, conn_action_stop },
972 { CONN_STATE_IDLE, CONN_EVENT_STOP, conn_action_stop },
973 { CONN_STATE_TX, CONN_EVENT_STOP, conn_action_stop },
974 { CONN_STATE_REGERR, CONN_EVENT_STOP, conn_action_stop },
975 { CONN_STATE_CONNERR, CONN_EVENT_STOP, conn_action_stop },
976
977 { CONN_STATE_STOPPED, CONN_EVENT_CONN_REQ, conn_action_connreject },
978 { CONN_STATE_STARTWAIT, CONN_EVENT_CONN_REQ, conn_action_connaccept },
979 { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REQ, conn_action_connaccept },
980 { CONN_STATE_IDLE, CONN_EVENT_CONN_REQ, conn_action_connreject },
981 { CONN_STATE_TX, CONN_EVENT_CONN_REQ, conn_action_connreject },
982
983 { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_ACK, conn_action_connack },
984 { CONN_STATE_SETUPWAIT, CONN_EVENT_TIMER, conn_action_conntimsev },
985
986 { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REJ, conn_action_connsever },
987 { CONN_STATE_IDLE, CONN_EVENT_CONN_REJ, conn_action_connsever },
988 { CONN_STATE_TX, CONN_EVENT_CONN_REJ, conn_action_connsever },
989
990 { CONN_STATE_IDLE, CONN_EVENT_RX, conn_action_rx },
991 { CONN_STATE_TX, CONN_EVENT_RX, conn_action_rx },
992
993 { CONN_STATE_TX, CONN_EVENT_TXDONE, conn_action_txdone },
994 { CONN_STATE_IDLE, CONN_EVENT_TXDONE, conn_action_txdone },
995};
996
997static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
998
999
1000/**
1001 * Actions for interface - statemachine.
1002 *****************************************************************************/
1003
1004/**
1005 * Startup connection by sending CONN_EVENT_START to it.
1006 *
1007 * @param fi An instance of an interface statemachine.
1008 * @param event The event, just happened.
1009 * @param arg Generic pointer, casted from struct net_device * upon call.
1010 */
1011static void
1012dev_action_start(fsm_instance *fi, int event, void *arg)
1013{
1014 struct net_device *dev = (struct net_device *)arg;
1015 struct netiucv_priv *privptr = dev->priv;
1016 struct iucv_event ev;
1017
1018 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1019
1020 ev.conn = privptr->conn;
1021 fsm_newstate(fi, DEV_STATE_STARTWAIT);
1022 fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
1023}
1024
1025/**
1026 * Shutdown connection by sending CONN_EVENT_STOP to it.
1027 *
1028 * @param fi An instance of an interface statemachine.
1029 * @param event The event, just happened.
1030 * @param arg Generic pointer, casted from struct net_device * upon call.
1031 */
1032static void
1033dev_action_stop(fsm_instance *fi, int event, void *arg)
1034{
1035 struct net_device *dev = (struct net_device *)arg;
1036 struct netiucv_priv *privptr = dev->priv;
1037 struct iucv_event ev;
1038
1039 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1040
1041 ev.conn = privptr->conn;
1042
1043 fsm_newstate(fi, DEV_STATE_STOPWAIT);
1044 fsm_event(privptr->conn->fsm, CONN_EVENT_STOP, &ev);
1045}
1046
1047/**
1048 * Called from connection statemachine
1049 * when a connection is up and running.
1050 *
1051 * @param fi An instance of an interface statemachine.
1052 * @param event The event, just happened.
1053 * @param arg Generic pointer, casted from struct net_device * upon call.
1054 */
1055static void
1056dev_action_connup(fsm_instance *fi, int event, void *arg)
1057{
1058 struct net_device *dev = (struct net_device *)arg;
1059 struct netiucv_priv *privptr = dev->priv;
1060
1061 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1062
1063 switch (fsm_getstate(fi)) {
1064 case DEV_STATE_STARTWAIT:
1065 fsm_newstate(fi, DEV_STATE_RUNNING);
1066 PRINT_INFO("%s: connected with remote side %s\n",
1067 dev->name, privptr->conn->userid);
1068 IUCV_DBF_TEXT(setup, 3,
1069 "connection is up and running\n");
1070 break;
1071 case DEV_STATE_STOPWAIT:
1072 PRINT_INFO(
1073 "%s: got connection UP event during shutdown!\n",
1074 dev->name);
1075 IUCV_DBF_TEXT(data, 2,
1076 "dev_action_connup: in DEV_STATE_STOPWAIT\n");
1077 break;
1078 }
1079}
1080
1081/**
1082 * Called from connection statemachine
1083 * when a connection has been shutdown.
1084 *
1085 * @param fi An instance of an interface statemachine.
1086 * @param event The event, just happened.
1087 * @param arg Generic pointer, casted from struct net_device * upon call.
1088 */
1089static void
1090dev_action_conndown(fsm_instance *fi, int event, void *arg)
1091{
1092 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1093
1094 switch (fsm_getstate(fi)) {
1095 case DEV_STATE_RUNNING:
1096 fsm_newstate(fi, DEV_STATE_STARTWAIT);
1097 break;
1098 case DEV_STATE_STOPWAIT:
1099 fsm_newstate(fi, DEV_STATE_STOPPED);
1100 IUCV_DBF_TEXT(setup, 3, "connection is down\n");
1101 break;
1102 }
1103}
1104
1105static const fsm_node dev_fsm[] = {
1106 { DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start },
1107
1108 { DEV_STATE_STOPWAIT, DEV_EVENT_START, dev_action_start },
1109 { DEV_STATE_STOPWAIT, DEV_EVENT_CONDOWN, dev_action_conndown },
1110
1111 { DEV_STATE_STARTWAIT, DEV_EVENT_STOP, dev_action_stop },
1112 { DEV_STATE_STARTWAIT, DEV_EVENT_CONUP, dev_action_connup },
1113
1114 { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop },
1115 { DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown },
1116 { DEV_STATE_RUNNING, DEV_EVENT_CONUP, fsm_action_nop },
1117};
1118
1119static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
1120
1121/**
1122 * Transmit a packet.
1123 * This is a helper function for netiucv_tx().
1124 *
1125 * @param conn Connection to be used for sending.
1126 * @param skb Pointer to struct sk_buff of packet to send.
1127 * The linklevel header has already been set up
1128 * by netiucv_tx().
1129 *
1130 * @return 0 on success, -ERRNO on failure. (Never fails.)
1131 */
1132static int
1133netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
1134 unsigned long saveflags;
1135 ll_header header;
1136 int rc = 0;
1137
1138 if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) {
1139 int l = skb->len + NETIUCV_HDRLEN;
1140
1141 spin_lock_irqsave(&conn->collect_lock, saveflags);
1142 if (conn->collect_len + l >
1143 (conn->max_buffsize - NETIUCV_HDRLEN)) {
1144 rc = -EBUSY;
1145 IUCV_DBF_TEXT(data, 2,
1146 "EBUSY from netiucv_transmit_skb\n");
1147 } else {
1148 atomic_inc(&skb->users);
1149 skb_queue_tail(&conn->collect_queue, skb);
1150 conn->collect_len += l;
1151 }
1152 spin_unlock_irqrestore(&conn->collect_lock, saveflags);
1153 } else {
1154 struct sk_buff *nskb = skb;
1155 /**
1156 * Copy the skb to a new allocated skb in lowmem only if the
1157 * data is located above 2G in memory or tailroom is < 2.
1158 */
1159 unsigned long hi =
1160 ((unsigned long)(skb->tail + NETIUCV_HDRLEN)) >> 31;
1161 int copied = 0;
1162 if (hi || (skb_tailroom(skb) < 2)) {
1163 nskb = alloc_skb(skb->len + NETIUCV_HDRLEN +
1164 NETIUCV_HDRLEN, GFP_ATOMIC | GFP_DMA);
1165 if (!nskb) {
1166 PRINT_WARN("%s: Could not allocate tx_skb\n",
1167 conn->netdev->name);
1168 IUCV_DBF_TEXT(data, 2, "alloc_skb failed\n");
1169 rc = -ENOMEM;
1170 return rc;
1171 } else {
1172 skb_reserve(nskb, NETIUCV_HDRLEN);
1173 memcpy(skb_put(nskb, skb->len),
1174 skb->data, skb->len);
1175 }
1176 copied = 1;
1177 }
1178 /**
1179 * skb now is below 2G and has enough room. Add headers.
1180 */
1181 header.next = nskb->len + NETIUCV_HDRLEN;
1182 memcpy(skb_push(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
1183 header.next = 0;
1184 memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
1185
1186 fsm_newstate(conn->fsm, CONN_STATE_TX);
1187 conn->prof.send_stamp = xtime;
1188
1189 rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
1190 0, nskb->data, nskb->len);
1191 /* Shut up, gcc! nskb is always below 2G. */
1192 conn->prof.doios_single++;
1193 conn->prof.txlen += skb->len;
1194 conn->prof.tx_pending++;
1195 if (conn->prof.tx_pending > conn->prof.tx_max_pending)
1196 conn->prof.tx_max_pending = conn->prof.tx_pending;
1197 if (rc) {
1198 struct netiucv_priv *privptr;
1199 fsm_newstate(conn->fsm, CONN_STATE_IDLE);
1200 conn->prof.tx_pending--;
1201 privptr = (struct netiucv_priv *)conn->netdev->priv;
1202 if (privptr)
1203 privptr->stats.tx_errors++;
1204 if (copied)
1205 dev_kfree_skb(nskb);
1206 else {
1207 /**
1208 * Remove our headers. They get added
1209 * again on retransmit.
1210 */
1211 skb_pull(skb, NETIUCV_HDRLEN);
1212 skb_trim(skb, skb->len - NETIUCV_HDRLEN);
1213 }
1214 PRINT_WARN("iucv_send returned %08x\n", rc);
1215 IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
1216 } else {
1217 if (copied)
1218 dev_kfree_skb(skb);
1219 atomic_inc(&nskb->users);
1220 skb_queue_tail(&conn->commit_queue, nskb);
1221 }
1222 }
1223
1224 return rc;
1225}
1226
1227/**
1228 * Interface API for upper network layers
1229 *****************************************************************************/
1230
1231/**
1232 * Open an interface.
1233 * Called from generic network layer when ifconfig up is run.
1234 *
1235 * @param dev Pointer to interface struct.
1236 *
1237 * @return 0 on success, -ERRNO on failure. (Never fails.)
1238 */
1239static int
1240netiucv_open(struct net_device *dev) {
1241 fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START,dev);
1242 return 0;
1243}
1244
1245/**
1246 * Close an interface.
1247 * Called from generic network layer when ifconfig down is run.
1248 *
1249 * @param dev Pointer to interface struct.
1250 *
1251 * @return 0 on success, -ERRNO on failure. (Never fails.)
1252 */
1253static int
1254netiucv_close(struct net_device *dev) {
1255 fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);
1256 return 0;
1257}
1258
1259/**
1260 * Start transmission of a packet.
1261 * Called from generic network device layer.
1262 *
1263 * @param skb Pointer to buffer containing the packet.
1264 * @param dev Pointer to interface struct.
1265 *
1266 * @return 0 if packet consumed, !0 if packet rejected.
1267 * Note: If we return !0, then the packet is free'd by
1268 * the generic network layer.
1269 */
1270static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
1271{
1272 int rc = 0;
1273 struct netiucv_priv *privptr = dev->priv;
1274
1275 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1276 /**
1277 * Some sanity checks ...
1278 */
1279 if (skb == NULL) {
1280 PRINT_WARN("%s: NULL sk_buff passed\n", dev->name);
1281 IUCV_DBF_TEXT(data, 2, "netiucv_tx: skb is NULL\n");
1282 privptr->stats.tx_dropped++;
1283 return 0;
1284 }
1285 if (skb_headroom(skb) < NETIUCV_HDRLEN) {
1286 PRINT_WARN("%s: Got sk_buff with head room < %ld bytes\n",
1287 dev->name, NETIUCV_HDRLEN);
1288 IUCV_DBF_TEXT(data, 2,
1289 "netiucv_tx: skb_headroom < NETIUCV_HDRLEN\n");
1290 dev_kfree_skb(skb);
1291 privptr->stats.tx_dropped++;
1292 return 0;
1293 }
1294
1295 /**
1296 * If connection is not running, try to restart it
1297 * and throw away packet.
1298 */
1299 if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
1300 fsm_event(privptr->fsm, DEV_EVENT_START, dev);
1301 dev_kfree_skb(skb);
1302 privptr->stats.tx_dropped++;
1303 privptr->stats.tx_errors++;
1304 privptr->stats.tx_carrier_errors++;
1305 return 0;
1306 }
1307
1308 if (netiucv_test_and_set_busy(dev)) {
1309 IUCV_DBF_TEXT(data, 2, "EBUSY from netiucv_tx\n");
1310 return -EBUSY;
1311 }
1312 dev->trans_start = jiffies;
1313 if (netiucv_transmit_skb(privptr->conn, skb))
1314 rc = 1;
1315 netiucv_clear_busy(dev);
1316 return rc;
1317}
1318
1319/**
1320 * Returns interface statistics of a device.
1321 *
1322 * @param dev Pointer to interface struct.
1323 *
1324 * @return Pointer to stats struct of this interface.
1325 */
1326static struct net_device_stats *
1327netiucv_stats (struct net_device * dev)
1328{
1329 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1330 return &((struct netiucv_priv *)dev->priv)->stats;
1331}
1332
1333/**
1334 * Sets MTU of an interface.
1335 *
1336 * @param dev Pointer to interface struct.
1337 * @param new_mtu The new MTU to use for this interface.
1338 *
1339 * @return 0 on success, -EINVAL if MTU is out of valid range.
1340 * (valid range is 576 .. NETIUCV_MTU_MAX).
1341 */
1342static int
1343netiucv_change_mtu (struct net_device * dev, int new_mtu)
1344{
1345 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1346 if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX)) {
1347 IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
1348 return -EINVAL;
1349 }
1350 dev->mtu = new_mtu;
1351 return 0;
1352}
1353
1354/**
1355 * attributes in sysfs
1356 *****************************************************************************/
1357
1358static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001359user_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360{
1361 struct netiucv_priv *priv = dev->driver_data;
1362
1363 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1364 return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
1365}
1366
1367static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001368user_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
1370 struct netiucv_priv *priv = dev->driver_data;
1371 struct net_device *ndev = priv->conn->netdev;
1372 char *p;
1373 char *tmp;
1374 char username[10];
1375 int i;
1376
1377 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1378 if (count>9) {
1379 PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
1380 IUCV_DBF_TEXT_(setup, 2,
1381 "%d is length of username\n", (int)count);
1382 return -EINVAL;
1383 }
1384
1385 tmp = strsep((char **) &buf, "\n");
1386 for (i=0, p=tmp; i<8 && *p; i++, p++) {
1387 if (isalnum(*p) || (*p == '$'))
1388 username[i]= *p;
1389 else if (*p == '\n') {
1390 /* trailing lf, grr */
1391 break;
1392 } else {
1393 PRINT_WARN("netiucv: Invalid char %c in username!\n",
1394 *p);
1395 IUCV_DBF_TEXT_(setup, 2,
1396 "username: invalid character %c\n",
1397 *p);
1398 return -EINVAL;
1399 }
1400 }
1401 while (i<9)
1402 username[i++] = ' ';
1403 username[9] = '\0';
1404
1405 if (memcmp(username, priv->conn->userid, 8)) {
1406 /* username changed */
1407 if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
1408 PRINT_WARN(
1409 "netiucv: device %s active, connected to %s\n",
1410 dev->bus_id, priv->conn->userid);
1411 PRINT_WARN("netiucv: user cannot be updated\n");
1412 IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
1413 return -EBUSY;
1414 }
1415 }
1416 memcpy(priv->conn->userid, username, 9);
1417
1418 return count;
1419
1420}
1421
1422static DEVICE_ATTR(user, 0644, user_show, user_write);
1423
1424static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001425buffer_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426{
1427 struct netiucv_priv *priv = dev->driver_data;
1428
1429 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1430 return sprintf(buf, "%d\n", priv->conn->max_buffsize);
1431}
1432
1433static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001434buffer_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435{
1436 struct netiucv_priv *priv = dev->driver_data;
1437 struct net_device *ndev = priv->conn->netdev;
1438 char *e;
1439 int bs1;
1440
1441 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1442 if (count >= 39)
1443 return -EINVAL;
1444
1445 bs1 = simple_strtoul(buf, &e, 0);
1446
1447 if (e && (!isspace(*e))) {
1448 PRINT_WARN("netiucv: Invalid character in buffer!\n");
1449 IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %c\n", *e);
1450 return -EINVAL;
1451 }
1452 if (bs1 > NETIUCV_BUFSIZE_MAX) {
1453 PRINT_WARN("netiucv: Given buffer size %d too large.\n",
1454 bs1);
1455 IUCV_DBF_TEXT_(setup, 2,
1456 "buffer_write: buffer size %d too large\n",
1457 bs1);
1458 return -EINVAL;
1459 }
1460 if ((ndev->flags & IFF_RUNNING) &&
1461 (bs1 < (ndev->mtu + NETIUCV_HDRLEN + 2))) {
1462 PRINT_WARN("netiucv: Given buffer size %d too small.\n",
1463 bs1);
1464 IUCV_DBF_TEXT_(setup, 2,
1465 "buffer_write: buffer size %d too small\n",
1466 bs1);
1467 return -EINVAL;
1468 }
1469 if (bs1 < (576 + NETIUCV_HDRLEN + NETIUCV_HDRLEN)) {
1470 PRINT_WARN("netiucv: Given buffer size %d too small.\n",
1471 bs1);
1472 IUCV_DBF_TEXT_(setup, 2,
1473 "buffer_write: buffer size %d too small\n",
1474 bs1);
1475 return -EINVAL;
1476 }
1477
1478 priv->conn->max_buffsize = bs1;
1479 if (!(ndev->flags & IFF_RUNNING))
1480 ndev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN;
1481
1482 return count;
1483
1484}
1485
1486static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
1487
1488static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001489dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490{
1491 struct netiucv_priv *priv = dev->driver_data;
1492
1493 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1494 return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
1495}
1496
1497static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
1498
1499static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001500conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501{
1502 struct netiucv_priv *priv = dev->driver_data;
1503
1504 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1505 return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
1506}
1507
1508static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
1509
1510static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001511maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
1513 struct netiucv_priv *priv = dev->driver_data;
1514
1515 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1516 return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
1517}
1518
1519static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001520maxmulti_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521{
1522 struct netiucv_priv *priv = dev->driver_data;
1523
1524 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1525 priv->conn->prof.maxmulti = 0;
1526 return count;
1527}
1528
1529static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
1530
1531static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001532maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
1534 struct netiucv_priv *priv = dev->driver_data;
1535
1536 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1537 return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
1538}
1539
1540static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001541maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542{
1543 struct netiucv_priv *priv = dev->driver_data;
1544
1545 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1546 priv->conn->prof.maxcqueue = 0;
1547 return count;
1548}
1549
1550static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
1551
1552static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001553sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554{
1555 struct netiucv_priv *priv = dev->driver_data;
1556
1557 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1558 return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
1559}
1560
1561static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001562sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
1564 struct netiucv_priv *priv = dev->driver_data;
1565
1566 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1567 priv->conn->prof.doios_single = 0;
1568 return count;
1569}
1570
1571static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
1572
1573static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001574mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575{
1576 struct netiucv_priv *priv = dev->driver_data;
1577
1578 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1579 return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
1580}
1581
1582static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001583mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584{
1585 struct netiucv_priv *priv = dev->driver_data;
1586
1587 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1588 priv->conn->prof.doios_multi = 0;
1589 return count;
1590}
1591
1592static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
1593
1594static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001595txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596{
1597 struct netiucv_priv *priv = dev->driver_data;
1598
1599 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1600 return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
1601}
1602
1603static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001604txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605{
1606 struct netiucv_priv *priv = dev->driver_data;
1607
1608 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1609 priv->conn->prof.txlen = 0;
1610 return count;
1611}
1612
1613static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
1614
1615static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001616txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617{
1618 struct netiucv_priv *priv = dev->driver_data;
1619
1620 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1621 return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
1622}
1623
1624static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001625txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626{
1627 struct netiucv_priv *priv = dev->driver_data;
1628
1629 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1630 priv->conn->prof.tx_time = 0;
1631 return count;
1632}
1633
1634static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
1635
1636static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001637txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
1639 struct netiucv_priv *priv = dev->driver_data;
1640
1641 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1642 return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
1643}
1644
1645static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001646txpend_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
1648 struct netiucv_priv *priv = dev->driver_data;
1649
1650 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1651 priv->conn->prof.tx_pending = 0;
1652 return count;
1653}
1654
1655static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
1656
1657static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001658txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659{
1660 struct netiucv_priv *priv = dev->driver_data;
1661
1662 IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
1663 return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
1664}
1665
1666static ssize_t
Yani Ioannou3fd3c0a2005-05-17 06:43:27 -04001667txmpnd_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668{
1669 struct netiucv_priv *priv = dev->driver_data;
1670
1671 IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
1672 priv->conn->prof.tx_max_pending = 0;
1673 return count;
1674}
1675
1676static DEVICE_ATTR(tx_max_pending, 0644, txmpnd_show, txmpnd_write);
1677
1678static struct attribute *netiucv_attrs[] = {
1679 &dev_attr_buffer.attr,
1680 &dev_attr_user.attr,
1681 NULL,
1682};
1683
1684static struct attribute_group netiucv_attr_group = {
1685 .attrs = netiucv_attrs,
1686};
1687
1688static struct attribute *netiucv_stat_attrs[] = {
1689 &dev_attr_device_fsm_state.attr,
1690 &dev_attr_connection_fsm_state.attr,
1691 &dev_attr_max_tx_buffer_used.attr,
1692 &dev_attr_max_chained_skbs.attr,
1693 &dev_attr_tx_single_write_ops.attr,
1694 &dev_attr_tx_multi_write_ops.attr,
1695 &dev_attr_netto_bytes.attr,
1696 &dev_attr_max_tx_io_time.attr,
1697 &dev_attr_tx_pending.attr,
1698 &dev_attr_tx_max_pending.attr,
1699 NULL,
1700};
1701
1702static struct attribute_group netiucv_stat_attr_group = {
1703 .name = "stats",
1704 .attrs = netiucv_stat_attrs,
1705};
1706
1707static inline int
1708netiucv_add_files(struct device *dev)
1709{
1710 int ret;
1711
1712 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1713 ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group);
1714 if (ret)
1715 return ret;
1716 ret = sysfs_create_group(&dev->kobj, &netiucv_stat_attr_group);
1717 if (ret)
1718 sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
1719 return ret;
1720}
1721
1722static inline void
1723netiucv_remove_files(struct device *dev)
1724{
1725 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1726 sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
1727 sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
1728}
1729
1730static int
1731netiucv_register_device(struct net_device *ndev)
1732{
1733 struct netiucv_priv *priv = ndev->priv;
1734 struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL);
1735 int ret;
1736
1737
1738 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1739
1740 if (dev) {
1741 memset(dev, 0, sizeof(struct device));
1742 snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
1743 dev->bus = &iucv_bus;
1744 dev->parent = iucv_root;
1745 /*
1746 * The release function could be called after the
1747 * module has been unloaded. It's _only_ task is to
1748 * free the struct. Therefore, we specify kfree()
1749 * directly here. (Probably a little bit obfuscating
1750 * but legitime ...).
1751 */
1752 dev->release = (void (*)(struct device *))kfree;
1753 dev->driver = &netiucv_driver;
1754 } else
1755 return -ENOMEM;
1756
1757 ret = device_register(dev);
1758
1759 if (ret)
1760 return ret;
1761 ret = netiucv_add_files(dev);
1762 if (ret)
1763 goto out_unreg;
1764 priv->dev = dev;
1765 dev->driver_data = priv;
1766 return 0;
1767
1768out_unreg:
1769 device_unregister(dev);
1770 return ret;
1771}
1772
1773static void
1774netiucv_unregister_device(struct device *dev)
1775{
1776 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1777 netiucv_remove_files(dev);
1778 device_unregister(dev);
1779}
1780
1781/**
1782 * Allocate and initialize a new connection structure.
1783 * Add it to the list of netiucv connections;
1784 */
1785static struct iucv_connection *
1786netiucv_new_connection(struct net_device *dev, char *username)
1787{
1788 struct iucv_connection **clist = &iucv_connections;
1789 struct iucv_connection *conn =
1790 (struct iucv_connection *)
1791 kmalloc(sizeof(struct iucv_connection), GFP_KERNEL);
1792
1793 if (conn) {
1794 memset(conn, 0, sizeof(struct iucv_connection));
1795 skb_queue_head_init(&conn->collect_queue);
1796 skb_queue_head_init(&conn->commit_queue);
1797 conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
1798 conn->netdev = dev;
1799
1800 conn->rx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
1801 GFP_KERNEL | GFP_DMA);
1802 if (!conn->rx_buff) {
1803 kfree(conn);
1804 return NULL;
1805 }
1806 conn->tx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
1807 GFP_KERNEL | GFP_DMA);
1808 if (!conn->tx_buff) {
1809 kfree_skb(conn->rx_buff);
1810 kfree(conn);
1811 return NULL;
1812 }
1813 conn->fsm = init_fsm("netiucvconn", conn_state_names,
1814 conn_event_names, NR_CONN_STATES,
1815 NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
1816 GFP_KERNEL);
1817 if (!conn->fsm) {
1818 kfree_skb(conn->tx_buff);
1819 kfree_skb(conn->rx_buff);
1820 kfree(conn);
1821 return NULL;
1822 }
1823 fsm_settimer(conn->fsm, &conn->timer);
1824 fsm_newstate(conn->fsm, CONN_STATE_INVALID);
1825
1826 if (username) {
1827 memcpy(conn->userid, username, 9);
1828 fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
1829 }
1830
1831 conn->next = *clist;
1832 *clist = conn;
1833 }
1834 return conn;
1835}
1836
1837/**
1838 * Release a connection structure and remove it from the
1839 * list of netiucv connections.
1840 */
1841static void
1842netiucv_remove_connection(struct iucv_connection *conn)
1843{
1844 struct iucv_connection **clist = &iucv_connections;
1845
1846 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1847 if (conn == NULL)
1848 return;
1849 while (*clist) {
1850 if (*clist == conn) {
1851 *clist = conn->next;
1852 if (conn->handle) {
1853 iucv_unregister_program(conn->handle);
1854 conn->handle = NULL;
1855 }
1856 fsm_deltimer(&conn->timer);
1857 kfree_fsm(conn->fsm);
1858 kfree_skb(conn->rx_buff);
1859 kfree_skb(conn->tx_buff);
1860 return;
1861 }
1862 clist = &((*clist)->next);
1863 }
1864}
1865
1866/**
1867 * Release everything of a net device.
1868 */
1869static void
1870netiucv_free_netdevice(struct net_device *dev)
1871{
1872 struct netiucv_priv *privptr;
1873
1874 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1875
1876 if (!dev)
1877 return;
1878
1879 privptr = (struct netiucv_priv *)dev->priv;
1880 if (privptr) {
1881 if (privptr->conn)
1882 netiucv_remove_connection(privptr->conn);
1883 if (privptr->fsm)
1884 kfree_fsm(privptr->fsm);
1885 privptr->conn = NULL; privptr->fsm = NULL;
1886 /* privptr gets freed by free_netdev() */
1887 }
1888 free_netdev(dev);
1889}
1890
1891/**
1892 * Initialize a net device. (Called from kernel in alloc_netdev())
1893 */
1894static void
1895netiucv_setup_netdevice(struct net_device *dev)
1896{
1897 memset(dev->priv, 0, sizeof(struct netiucv_priv));
1898
1899 dev->mtu = NETIUCV_MTU_DEFAULT;
1900 dev->hard_start_xmit = netiucv_tx;
1901 dev->open = netiucv_open;
1902 dev->stop = netiucv_close;
1903 dev->get_stats = netiucv_stats;
1904 dev->change_mtu = netiucv_change_mtu;
1905 dev->destructor = netiucv_free_netdevice;
1906 dev->hard_header_len = NETIUCV_HDRLEN;
1907 dev->addr_len = 0;
1908 dev->type = ARPHRD_SLIP;
1909 dev->tx_queue_len = NETIUCV_QUEUELEN_DEFAULT;
1910 dev->flags = IFF_POINTOPOINT | IFF_NOARP;
1911 SET_MODULE_OWNER(dev);
1912}
1913
1914/**
1915 * Allocate and initialize everything of a net device.
1916 */
1917static struct net_device *
1918netiucv_init_netdevice(char *username)
1919{
1920 struct netiucv_priv *privptr;
1921 struct net_device *dev;
1922
1923 dev = alloc_netdev(sizeof(struct netiucv_priv), "iucv%d",
1924 netiucv_setup_netdevice);
1925 if (!dev)
1926 return NULL;
1927 if (dev_alloc_name(dev, dev->name) < 0) {
1928 free_netdev(dev);
1929 return NULL;
1930 }
1931
1932 privptr = (struct netiucv_priv *)dev->priv;
1933 privptr->fsm = init_fsm("netiucvdev", dev_state_names,
1934 dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
1935 dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
1936 if (!privptr->fsm) {
1937 free_netdev(dev);
1938 return NULL;
1939 }
1940 privptr->conn = netiucv_new_connection(dev, username);
1941 if (!privptr->conn) {
1942 kfree_fsm(privptr->fsm);
1943 free_netdev(dev);
1944 IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n");
1945 return NULL;
1946 }
1947 fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
1948
1949 return dev;
1950}
1951
1952static ssize_t
1953conn_write(struct device_driver *drv, const char *buf, size_t count)
1954{
1955 char *p;
1956 char username[10];
1957 int i, ret;
1958 struct net_device *dev;
1959
1960 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
1961 if (count>9) {
1962 PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
1963 IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
1964 return -EINVAL;
1965 }
1966
1967 for (i=0, p=(char *)buf; i<8 && *p; i++, p++) {
1968 if (isalnum(*p) || (*p == '$'))
1969 username[i]= *p;
1970 else if (*p == '\n') {
1971 /* trailing lf, grr */
1972 break;
1973 } else {
1974 PRINT_WARN("netiucv: Invalid character in username!\n");
1975 IUCV_DBF_TEXT_(setup, 2,
1976 "conn_write: invalid character %c\n", *p);
1977 return -EINVAL;
1978 }
1979 }
1980 while (i<9)
1981 username[i++] = ' ';
1982 username[9] = '\0';
1983 dev = netiucv_init_netdevice(username);
1984 if (!dev) {
1985 PRINT_WARN(
1986 "netiucv: Could not allocate network device structure "
1987 "for user '%s'\n", netiucv_printname(username));
1988 IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n");
1989 return -ENODEV;
1990 }
1991
1992 if ((ret = netiucv_register_device(dev))) {
1993 IUCV_DBF_TEXT_(setup, 2,
1994 "ret %d from netiucv_register_device\n", ret);
1995 goto out_free_ndev;
1996 }
1997
1998 /* sysfs magic */
1999 SET_NETDEV_DEV(dev,
2000 (struct device*)((struct netiucv_priv*)dev->priv)->dev);
2001
2002 if ((ret = register_netdev(dev))) {
2003 netiucv_unregister_device((struct device*)
2004 ((struct netiucv_priv*)dev->priv)->dev);
2005 goto out_free_ndev;
2006 }
2007
2008 PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
2009
2010 return count;
2011
2012out_free_ndev:
2013 PRINT_WARN("netiucv: Could not register '%s'\n", dev->name);
2014 IUCV_DBF_TEXT(setup, 2, "conn_write: could not register\n");
2015 netiucv_free_netdevice(dev);
2016 return ret;
2017}
2018
2019DRIVER_ATTR(connection, 0200, NULL, conn_write);
2020
2021static ssize_t
2022remove_write (struct device_driver *drv, const char *buf, size_t count)
2023{
2024 struct iucv_connection **clist = &iucv_connections;
2025 struct net_device *ndev;
2026 struct netiucv_priv *priv;
2027 struct device *dev;
2028 char name[IFNAMSIZ];
2029 char *p;
2030 int i;
2031
2032 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
2033
2034 if (count >= IFNAMSIZ)
2035 count = IFNAMSIZ-1;
2036
2037 for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
2038 if ((*p == '\n') | (*p == ' ')) {
2039 /* trailing lf, grr */
2040 break;
2041 } else {
2042 name[i]=*p;
2043 }
2044 }
2045 name[i] = '\0';
2046
2047 while (*clist) {
2048 ndev = (*clist)->netdev;
2049 priv = (struct netiucv_priv*)ndev->priv;
2050 dev = priv->dev;
2051
2052 if (strncmp(name, ndev->name, count)) {
2053 clist = &((*clist)->next);
2054 continue;
2055 }
2056 if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
2057 PRINT_WARN(
2058 "netiucv: net device %s active with peer %s\n",
2059 ndev->name, priv->conn->userid);
2060 PRINT_WARN("netiucv: %s cannot be removed\n",
2061 ndev->name);
2062 IUCV_DBF_TEXT(data, 2, "remove_write: still active\n");
2063 return -EBUSY;
2064 }
2065 unregister_netdev(ndev);
2066 netiucv_unregister_device(dev);
2067 return count;
2068 }
2069 PRINT_WARN("netiucv: net device %s unknown\n", name);
2070 IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
2071 return -EINVAL;
2072}
2073
2074DRIVER_ATTR(remove, 0200, NULL, remove_write);
2075
2076static void
2077netiucv_banner(void)
2078{
Michael Holzheu66a464d2005-06-25 14:55:33 -07002079 char vbuf[] = "$Revision: 1.66 $";
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 char *version = vbuf;
2081
2082 if ((version = strchr(version, ':'))) {
2083 char *p = strchr(version + 1, '$');
2084 if (p)
2085 *p = '\0';
2086 } else
2087 version = " ??? ";
2088 PRINT_INFO("NETIUCV driver Version%s initialized\n", version);
2089}
2090
2091static void __exit
2092netiucv_exit(void)
2093{
2094 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
2095 while (iucv_connections) {
2096 struct net_device *ndev = iucv_connections->netdev;
2097 struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
2098 struct device *dev = priv->dev;
2099
2100 unregister_netdev(ndev);
2101 netiucv_unregister_device(dev);
2102 }
2103
2104 driver_remove_file(&netiucv_driver, &driver_attr_connection);
2105 driver_remove_file(&netiucv_driver, &driver_attr_remove);
2106 driver_unregister(&netiucv_driver);
2107 iucv_unregister_dbf_views();
2108
2109 PRINT_INFO("NETIUCV driver unloaded\n");
2110 return;
2111}
2112
2113static int __init
2114netiucv_init(void)
2115{
2116 int ret;
2117
2118 ret = iucv_register_dbf_views();
2119 if (ret) {
2120 PRINT_WARN("netiucv_init failed, "
2121 "iucv_register_dbf_views rc = %d\n", ret);
2122 return ret;
2123 }
2124 IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
2125 ret = driver_register(&netiucv_driver);
2126 if (ret) {
2127 PRINT_ERR("NETIUCV: failed to register driver.\n");
2128 IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", ret);
2129 iucv_unregister_dbf_views();
2130 return ret;
2131 }
2132
2133 /* Add entry for specifying connections. */
2134 ret = driver_create_file(&netiucv_driver, &driver_attr_connection);
2135 if (!ret) {
2136 ret = driver_create_file(&netiucv_driver, &driver_attr_remove);
2137 netiucv_banner();
2138 } else {
2139 PRINT_ERR("NETIUCV: failed to add driver attribute.\n");
2140 IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret);
2141 driver_unregister(&netiucv_driver);
2142 iucv_unregister_dbf_views();
2143 }
2144 return ret;
2145}
2146
2147module_init(netiucv_init);
2148module_exit(netiucv_exit);
2149MODULE_LICENSE("GPL");