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