Commit fa2bb18e authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: iucv network driver.

clean up the IUCV driver
parent b83cd715
/* /*
* $Id: netiucv.c,v 1.12 2002/11/26 16:00:54 mschwide Exp $ * $Id: netiucv.c,v 1.16 2003/02/18 09:15:14 mschwide Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* RELEASE-TAG: IUCV network driver $Revision: 1.12 $ * RELEASE-TAG: IUCV network driver $Revision: 1.16 $
* *
*/ */
...@@ -65,25 +65,15 @@ ...@@ -65,25 +65,15 @@
#undef DEBUG #undef DEBUG
#ifdef MODULE
MODULE_AUTHOR MODULE_AUTHOR
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)"); ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver"); MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
MODULE_PARM (iucv, "1s");
MODULE_PARM_DESC (iucv,
"Specify the initial remote userids for iucv0 .. iucvn:\n"
"iucv=userid0:userid1:...:useridN");
#endif
static char *iucv = "";
typedef struct net_device net_device;
/** /**
* Per connection profiling data * Per connection profiling data
*/ */
typedef struct connection_profile_t { struct connection_profile {
unsigned long maxmulti; unsigned long maxmulti;
unsigned long maxcqueue; unsigned long maxcqueue;
unsigned long doios_single; unsigned long doios_single;
...@@ -91,56 +81,76 @@ typedef struct connection_profile_t { ...@@ -91,56 +81,76 @@ typedef struct connection_profile_t {
unsigned long txlen; unsigned long txlen;
unsigned long tx_time; unsigned long tx_time;
struct timespec send_stamp; struct timespec send_stamp;
} connection_profile; };
/** /**
* Representation of one iucv connection * Representation of one iucv connection
*/ */
typedef struct iucv_connection_t { struct iucv_connection {
struct iucv_connection_t *next; struct iucv_connection *next;
iucv_handle_t handle; iucv_handle_t handle;
__u16 pathid; __u16 pathid;
struct sk_buff *rx_buff; struct sk_buff *rx_buff;
struct sk_buff *tx_buff; struct sk_buff *tx_buff;
struct sk_buff_head collect_queue; struct sk_buff_head collect_queue;
spinlock_t collect_lock; spinlock_t collect_lock;
int collect_len; int collect_len;
int max_buffsize; int max_buffsize;
int flags; int flags;
fsm_timer timer; fsm_timer timer;
int retry; int retry;
fsm_instance *fsm; fsm_instance *fsm;
net_device *netdev; struct net_device *netdev;
connection_profile prof; struct connection_profile prof;
char userid[9]; char userid[9];
} iucv_connection; };
#define CONN_FLAGS_BUFSIZE_CHANGED 1 #define CONN_FLAGS_BUFSIZE_CHANGED 1
/** /**
* Linked list of all connection structs. * Linked list of all connection structs.
*/ */
static iucv_connection *connections; static struct iucv_connection *connections;
/* Keep track of interfaces. */
static int ifno;
static int
iucv_bus_match (struct device *dev, struct device_driver *drv)
{
return 0;
}
/* Hm - move to iucv.c and export? - CH */
static struct bus_type iucv_bus = {
.name = "iucv",
.match = iucv_bus_match,
};
static struct device iucv_root = {
.name = "IUCV",
.bus_id = "iucv",
};
/** /**
* Representation of event-data for the * Representation of event-data for the
* connection state machine. * connection state machine.
*/ */
typedef struct iucv_event_t { struct iucv_event {
iucv_connection *conn; struct iucv_connection *conn;
void *data; void *data;
} iucv_event; };
/** /**
* Private part of the network device structure * Private part of the network device structure
*/ */
typedef struct netiucv_priv_t { struct netiucv_priv {
struct net_device_stats stats; struct net_device_stats stats;
unsigned long tbusy; unsigned long tbusy;
fsm_instance *fsm; fsm_instance *fsm;
iucv_connection *conn; struct iucv_connection *conn;
struct platform_device pldev; struct device dev;
} netiucv_priv; };
/** /**
* Link level header for a packet. * Link level header for a packet.
...@@ -161,16 +171,16 @@ typedef struct ll_header_t { ...@@ -161,16 +171,16 @@ typedef struct ll_header_t {
* Compatibility macros for busy handling * Compatibility macros for busy handling
* of network devices. * of network devices.
*/ */
static __inline__ void netiucv_clear_busy(net_device *dev) static __inline__ void netiucv_clear_busy(struct net_device *dev)
{ {
clear_bit(0, &(((netiucv_priv *)dev->priv)->tbusy)); clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy));
netif_wake_queue(dev); netif_wake_queue(dev);
} }
static __inline__ int netiucv_test_and_set_busy(net_device *dev) static __inline__ int netiucv_test_and_set_busy(struct net_device *dev)
{ {
netif_stop_queue(dev); netif_stop_queue(dev);
return test_and_set_bit(0, &((netiucv_priv *)dev->priv)->tbusy); return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);
} }
#define SET_DEVICE_START(device, value) #define SET_DEVICE_START(device, value)
...@@ -387,8 +397,8 @@ static const char *conn_state_names[] = { ...@@ -387,8 +397,8 @@ static const char *conn_state_names[] = {
static void static void
netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data) netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -399,8 +409,8 @@ netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data) ...@@ -399,8 +409,8 @@ netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
static void static void
netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data) netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -410,8 +420,8 @@ netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data) ...@@ -410,8 +420,8 @@ netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
static void static void
netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data) netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -421,8 +431,8 @@ netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data) ...@@ -421,8 +431,8 @@ netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
static void static void
netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data) netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -432,8 +442,8 @@ netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data) ...@@ -432,8 +442,8 @@ netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
static void static void
netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data) netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -443,8 +453,8 @@ netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data) ...@@ -443,8 +453,8 @@ netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
static void static void
netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data) netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -454,8 +464,8 @@ netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data) ...@@ -454,8 +464,8 @@ netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
static void static void
netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data) netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
{ {
iucv_connection *conn = (iucv_connection *)pgm_data; struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
iucv_event ev; struct iucv_event ev;
ev.conn = conn; ev.conn = conn;
ev.data = (void *)eib; ev.data = (void *)eib;
...@@ -494,10 +504,10 @@ fsm_action_nop(fsm_instance *fi, int event, void *arg) ...@@ -494,10 +504,10 @@ fsm_action_nop(fsm_instance *fi, int event, void *arg)
*/ */
//static __inline__ void //static __inline__ void
static void static void
netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb) netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
{ {
net_device *dev = conn->netdev; struct net_device *dev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)dev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)dev->priv;
__u16 offset = 0; __u16 offset = 0;
skb_put(pskb, NETIUCV_HDRLEN); skb_put(pskb, NETIUCV_HDRLEN);
...@@ -518,7 +528,8 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb) ...@@ -518,7 +528,8 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb)
header->next -= NETIUCV_HDRLEN; header->next -= NETIUCV_HDRLEN;
if (skb_tailroom(pskb) < header->next) { if (skb_tailroom(pskb) < header->next) {
printk(KERN_WARNING printk(KERN_WARNING
"%s: Illegal next field in iucv header: %d > %d\n", "%s: Illegal next field in iucv header: "
"%d > %d\n",
dev->name, header->next, skb_tailroom(pskb)); dev->name, header->next, skb_tailroom(pskb));
return; return;
} }
...@@ -549,17 +560,16 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb) ...@@ -549,17 +560,16 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb)
static void static void
conn_action_rx(fsm_instance *fi, int event, void *arg) conn_action_rx(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
iucv_MessagePending *eib = (iucv_MessagePending *)ev->data; iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
netiucv_priv *privptr = (netiucv_priv *)conn->netdev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)conn->netdev->priv;
__u16 msglen = eib->ln1msg2.ipbfln1f; __u16 msglen = eib->ln1msg2.ipbfln1f;
int rc; int rc;
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
if (!conn->netdev) { if (!conn->netdev) {
/* FRITZ: How to tell iucv LL to drop the msg? */ /* FRITZ: How to tell iucv LL to drop the msg? */
printk(KERN_WARNING printk(KERN_WARNING
...@@ -585,10 +595,10 @@ conn_action_rx(fsm_instance *fi, int event, void *arg) ...@@ -585,10 +595,10 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
static void static void
conn_action_txdone(fsm_instance *fi, int event, void *arg) conn_action_txdone(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data; iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
netiucv_priv *privptr = NULL; struct netiucv_priv *privptr = NULL;
/* Shut up, gcc! skb is always below 2G. */ /* Shut up, gcc! skb is always below 2G. */
struct sk_buff *skb = (struct sk_buff *)(unsigned long)eib->ipmsgtag; struct sk_buff *skb = (struct sk_buff *)(unsigned long)eib->ipmsgtag;
__u32 txbytes = 0; __u32 txbytes = 0;
...@@ -597,12 +607,11 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) ...@@ -597,12 +607,11 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
unsigned long saveflags; unsigned long saveflags;
ll_header header; ll_header header;
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
fsm_deltimer(&conn->timer); fsm_deltimer(&conn->timer);
if (conn && conn->netdev && conn->netdev->priv) if (conn && conn->netdev && conn->netdev->priv)
privptr = (netiucv_priv *)conn->netdev->priv; privptr = (struct netiucv_priv *)conn->netdev->priv;
if (skb) { if (skb) {
if (privptr) { if (privptr) {
privptr->stats.tx_packets++; privptr->stats.tx_packets++;
...@@ -663,18 +672,17 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg) ...@@ -663,18 +672,17 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
static void static void
conn_action_connaccept(fsm_instance *fi, int event, void *arg) conn_action_connaccept(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data; iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
net_device *netdev = conn->netdev; struct net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
int rc; int rc;
__u16 msglimit; __u16 msglimit;
__u8 udata[16]; __u8 udata[16];
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0, rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,
conn->handle, conn, NULL, &msglimit); conn->handle, conn, NULL, &msglimit);
if (rc != 0) { if (rc != 0) {
...@@ -692,29 +700,27 @@ conn_action_connaccept(fsm_instance *fi, int event, void *arg) ...@@ -692,29 +700,27 @@ conn_action_connaccept(fsm_instance *fi, int event, void *arg)
static void static void
conn_action_connreject(fsm_instance *fi, int event, void *arg) conn_action_connreject(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
// iucv_connection *conn = ev->conn; // struct iucv_connection *conn = ev->conn;
iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data; iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
__u8 udata[16]; __u8 udata[16];
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
iucv_sever(eib->ippathid, udata); iucv_sever(eib->ippathid, udata);
} }
static void static void
conn_action_connack(fsm_instance *fi, int event, void *arg) conn_action_connack(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data; iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
net_device *netdev = conn->netdev; struct net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
fsm_newstate(fi, CONN_STATE_IDLE); fsm_newstate(fi, CONN_STATE_IDLE);
conn->pathid = eib->ippathid; conn->pathid = eib->ippathid;
netdev->tx_queue_len = eib->ipmsglim; netdev->tx_queue_len = eib->ipmsglim;
...@@ -724,16 +730,15 @@ conn_action_connack(fsm_instance *fi, int event, void *arg) ...@@ -724,16 +730,15 @@ conn_action_connack(fsm_instance *fi, int event, void *arg)
static void static void
conn_action_connsever(fsm_instance *fi, int event, void *arg) conn_action_connsever(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
// iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data; // iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data;
net_device *netdev = conn->netdev; struct net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
int state = fsm_getstate(fi); int state = fsm_getstate(fi);
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
switch (state) { switch (state) {
case CONN_STATE_IDLE: case CONN_STATE_IDLE:
case CONN_STATE_TX: case CONN_STATE_TX:
...@@ -751,14 +756,13 @@ conn_action_connsever(fsm_instance *fi, int event, void *arg) ...@@ -751,14 +756,13 @@ conn_action_connsever(fsm_instance *fi, int event, void *arg)
static void static void
conn_action_start(fsm_instance *fi, int event, void *arg) conn_action_start(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
int rc; int rc;
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
if (conn->handle == 0) { if (conn->handle == 0) {
conn->handle = conn->handle =
iucv_register_program(iucvMagic, conn->userid, mask, iucv_register_program(iucvMagic, conn->userid, mask,
...@@ -769,15 +773,14 @@ conn_action_start(fsm_instance *fi, int event, void *arg) ...@@ -769,15 +773,14 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
conn->handle = 0; conn->handle = 0;
return; return;
} }
#ifdef DEBUG
printk(KERN_DEBUG "%s('%s'): registered successfully\n", pr_debug("%s('%s'): registered successfully\n",
conn->netdev->name, conn->userid); conn->netdev->name, conn->userid);
#endif
} }
#ifdef DEBUG
printk(KERN_DEBUG "%s('%s'): connecting ...\n", pr_debug("%s('%s'): connecting ...\n",
conn->netdev->name, conn->userid); conn->netdev->name, conn->userid);
#endif
rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic, rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
conn->userid, iucv_host, 0, NULL, NULL, conn->handle, conn->userid, iucv_host, 0, NULL, NULL, conn->handle,
conn); conn);
...@@ -843,14 +846,13 @@ netiucv_purge_skb_queue(struct sk_buff_head *q) ...@@ -843,14 +846,13 @@ netiucv_purge_skb_queue(struct sk_buff_head *q)
static void static void
conn_action_stop(fsm_instance *fi, int event, void *arg) conn_action_stop(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
net_device *netdev = conn->netdev; struct net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
#ifdef DEBUG pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
fsm_newstate(fi, CONN_STATE_STOPPED); fsm_newstate(fi, CONN_STATE_STOPPED);
netiucv_purge_skb_queue(&conn->collect_queue); netiucv_purge_skb_queue(&conn->collect_queue);
if (conn->handle) if (conn->handle)
...@@ -862,9 +864,9 @@ conn_action_stop(fsm_instance *fi, int event, void *arg) ...@@ -862,9 +864,9 @@ conn_action_stop(fsm_instance *fi, int event, void *arg)
static void static void
conn_action_inval(fsm_instance *fi, int event, void *arg) conn_action_inval(fsm_instance *fi, int event, void *arg)
{ {
iucv_event *ev = (iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
net_device *netdev = conn->netdev; struct net_device *netdev = conn->netdev;
printk(KERN_WARNING printk(KERN_WARNING
"%s: Cannot connect without username\n", "%s: Cannot connect without username\n",
...@@ -913,18 +915,17 @@ static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node); ...@@ -913,18 +915,17 @@ static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
* *
* @param fi An instance of an interface statemachine. * @param fi An instance of an interface statemachine.
* @param event The event, just happened. * @param event The event, just happened.
* @param arg Generic pointer, casted from net_device * upon call. * @param arg Generic pointer, casted from struct net_device * upon call.
*/ */
static void static void
dev_action_start(fsm_instance *fi, int event, void *arg) dev_action_start(fsm_instance *fi, int event, void *arg)
{ {
net_device *dev = (net_device *)arg; struct net_device *dev = (struct net_device *)arg;
netiucv_priv *privptr = dev->priv; struct netiucv_priv *privptr = dev->priv;
iucv_event ev; struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
ev.conn = privptr->conn; ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STARTWAIT); fsm_newstate(fi, DEV_STATE_STARTWAIT);
fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev); fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
...@@ -935,18 +936,17 @@ dev_action_start(fsm_instance *fi, int event, void *arg) ...@@ -935,18 +936,17 @@ dev_action_start(fsm_instance *fi, int event, void *arg)
* *
* @param fi An instance of an interface statemachine. * @param fi An instance of an interface statemachine.
* @param event The event, just happened. * @param event The event, just happened.
* @param arg Generic pointer, casted from net_device * upon call. * @param arg Generic pointer, casted from struct net_device * upon call.
*/ */
static void static void
dev_action_stop(fsm_instance *fi, int event, void *arg) dev_action_stop(fsm_instance *fi, int event, void *arg)
{ {
net_device *dev = (net_device *)arg; struct net_device *dev = (struct net_device *)arg;
netiucv_priv *privptr = dev->priv; struct netiucv_priv *privptr = dev->priv;
iucv_event ev; struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
ev.conn = privptr->conn; ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STOPWAIT); fsm_newstate(fi, DEV_STATE_STOPWAIT);
...@@ -959,16 +959,15 @@ dev_action_stop(fsm_instance *fi, int event, void *arg) ...@@ -959,16 +959,15 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
* *
* @param fi An instance of an interface statemachine. * @param fi An instance of an interface statemachine.
* @param event The event, just happened. * @param event The event, just happened.
* @param arg Generic pointer, casted from net_device * upon call. * @param arg Generic pointer, casted from struct net_device * upon call.
*/ */
static void static void
dev_action_connup(fsm_instance *fi, int event, void *arg) dev_action_connup(fsm_instance *fi, int event, void *arg)
{ {
net_device *dev = (net_device *)arg; struct net_device *dev = (struct net_device *)arg;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
switch (fsm_getstate(fi)) { switch (fsm_getstate(fi)) {
case DEV_STATE_STARTWAIT: case DEV_STATE_STARTWAIT:
fsm_newstate(fi, DEV_STATE_RUNNING); fsm_newstate(fi, DEV_STATE_RUNNING);
...@@ -990,18 +989,17 @@ dev_action_connup(fsm_instance *fi, int event, void *arg) ...@@ -990,18 +989,17 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
* *
* @param fi An instance of an interface statemachine. * @param fi An instance of an interface statemachine.
* @param event The event, just happened. * @param event The event, just happened.
* @param arg Generic pointer, casted from net_device * upon call. * @param arg Generic pointer, casted from struct net_device * upon call.
*/ */
static void static void
dev_action_conndown(fsm_instance *fi, int event, void *arg) dev_action_conndown(fsm_instance *fi, int event, void *arg)
{ {
net_device *dev = (net_device *)arg; struct net_device *dev = (struct net_device *)arg;
netiucv_priv *privptr = dev->priv; struct netiucv_priv *privptr = dev->priv;
iucv_event ev; struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
switch (fsm_getstate(fi)) { switch (fsm_getstate(fi)) {
case DEV_STATE_RUNNING: case DEV_STATE_RUNNING:
fsm_newstate(fi, DEV_STATE_STARTWAIT); fsm_newstate(fi, DEV_STATE_STARTWAIT);
...@@ -1045,7 +1043,7 @@ static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node); ...@@ -1045,7 +1043,7 @@ static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
* @return 0 on success, -ERRNO on failure. (Never fails.) * @return 0 on success, -ERRNO on failure. (Never fails.)
*/ */
static int static int
netiucv_transmit_skb(iucv_connection *conn, struct sk_buff *skb) { netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
unsigned long saveflags; unsigned long saveflags;
ll_header header; ll_header header;
int rc = 0; int rc = 0;
...@@ -1141,10 +1139,10 @@ netiucv_transmit_skb(iucv_connection *conn, struct sk_buff *skb) { ...@@ -1141,10 +1139,10 @@ netiucv_transmit_skb(iucv_connection *conn, struct sk_buff *skb) {
* @return 0 on success, -ERRNO on failure. (Never fails.) * @return 0 on success, -ERRNO on failure. (Never fails.)
*/ */
static int static int
netiucv_open(net_device *dev) { netiucv_open(struct net_device *dev) {
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
SET_DEVICE_START(dev, 1); SET_DEVICE_START(dev, 1);
fsm_event(((netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START, dev); fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START, dev);
return 0; return 0;
} }
...@@ -1157,9 +1155,9 @@ netiucv_open(net_device *dev) { ...@@ -1157,9 +1155,9 @@ netiucv_open(net_device *dev) {
* @return 0 on success, -ERRNO on failure. (Never fails.) * @return 0 on success, -ERRNO on failure. (Never fails.)
*/ */
static int static int
netiucv_close(net_device *dev) { netiucv_close(struct net_device *dev) {
SET_DEVICE_START(dev, 0); SET_DEVICE_START(dev, 0);
fsm_event(((netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev); fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -1175,10 +1173,10 @@ netiucv_close(net_device *dev) { ...@@ -1175,10 +1173,10 @@ netiucv_close(net_device *dev) {
* Note: If we return !0, then the packet is free'd by * Note: If we return !0, then the packet is free'd by
* the generic network layer. * the generic network layer.
*/ */
static int netiucv_tx(struct sk_buff *skb, net_device *dev) static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
{ {
int rc = 0; int rc = 0;
netiucv_priv *privptr = (netiucv_priv *)dev->priv; struct netiucv_priv *privptr = (struct netiucv_priv *)dev->priv;
/** /**
* Some sanity checks ... * Some sanity checks ...
...@@ -1230,9 +1228,9 @@ static int netiucv_tx(struct sk_buff *skb, net_device *dev) ...@@ -1230,9 +1228,9 @@ static int netiucv_tx(struct sk_buff *skb, net_device *dev)
* @return Pointer to stats struct of this interface. * @return Pointer to stats struct of this interface.
*/ */
static struct net_device_stats * static struct net_device_stats *
netiucv_stats (net_device * dev) netiucv_stats (struct net_device * dev)
{ {
return &((netiucv_priv *)dev->priv)->stats; return &((struct netiucv_priv *)dev->priv)->stats;
} }
/** /**
...@@ -1245,7 +1243,7 @@ netiucv_stats (net_device * dev) ...@@ -1245,7 +1243,7 @@ netiucv_stats (net_device * dev)
* (valid range is 576 .. NETIUCV_MTU_MAX). * (valid range is 576 .. NETIUCV_MTU_MAX).
*/ */
static int static int
netiucv_change_mtu (net_device * dev, int new_mtu) netiucv_change_mtu (struct net_device * dev, int new_mtu)
{ {
if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX)) if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX))
return -EINVAL; return -EINVAL;
...@@ -1258,66 +1256,20 @@ netiucv_change_mtu (net_device * dev, int new_mtu) ...@@ -1258,66 +1256,20 @@ netiucv_change_mtu (net_device * dev, int new_mtu)
*****************************************************************************/ *****************************************************************************/
#define CTRL_BUFSIZE 40 #define CTRL_BUFSIZE 40
static ssize_t
user_show (struct device *dev, char *buf)
{
netiucv_priv *priv = dev->driver_data;
return snprintf(buf, PAGE_SIZE, "%s\n",
netiucv_printname(priv->conn->userid));
}
static ssize_t
user_write (struct device *dev, const char *buf, size_t count)
{
netiucv_priv *priv = dev->driver_data;
struct net_device *ndev = container_of((void *)priv, struct net_device, priv);
int i;
char *p;
char tmp[CTRL_BUFSIZE];
char user[9];
if (count >= 39)
return -EINVAL;
if (copy_from_user(tmp, buf, count))
return -EFAULT;
tmp[count+1] = '\0';
memset(user, ' ', sizeof(user));
user[8] = '\0';
for (p = tmp, i = 0; *p && (!isspace(*p)); p++) {
if (i > 7)
return -EINVAL;
user[i++] = *p;
}
if (memcmp(user, priv->conn->userid, 8) != 0) {
/* username changed */
if (ndev->flags & IFF_RUNNING)
return -EBUSY;
}
memcpy(priv->conn->userid, user, 9);
return count;
}
static DEVICE_ATTR(user, 0644, user_show, user_write);
static ssize_t static ssize_t
buffer_show (struct device *dev, char *buf) buffer_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%d\n", return sprintf(buf, "%d\n", priv->conn->max_buffsize);
priv->conn->max_buffsize);
} }
static ssize_t static ssize_t
buffer_write (struct device *dev, const char *buf, size_t count) buffer_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
struct net_device *ndev = container_of((void *)priv, struct net_device, priv); struct net_device *ndev =
container_of((void *)priv, struct net_device, priv);
char *e; char *e;
int bs1; int bs1;
char tmp[CTRL_BUFSIZE]; char tmp[CTRL_BUFSIZE];
...@@ -1354,10 +1306,9 @@ static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); ...@@ -1354,10 +1306,9 @@ static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
static ssize_t static ssize_t
dev_fsm_show (struct device *dev, char *buf) dev_fsm_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return snprintf(buf, PAGE_SIZE, "%s\n", return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
fsm_getstate_str(priv->fsm));
} }
static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL); static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
...@@ -1365,10 +1316,9 @@ static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL); ...@@ -1365,10 +1316,9 @@ static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
static ssize_t static ssize_t
conn_fsm_show (struct device *dev, char *buf) conn_fsm_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return snprintf(buf, PAGE_SIZE, "%s\n", return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
fsm_getstate_str(priv->conn->fsm));
} }
static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL); static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
...@@ -1376,7 +1326,7 @@ static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL); ...@@ -1376,7 +1326,7 @@ static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
static ssize_t static ssize_t
maxmulti_show (struct device *dev, char *buf) maxmulti_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti); return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
} }
...@@ -1384,7 +1334,7 @@ maxmulti_show (struct device *dev, char *buf) ...@@ -1384,7 +1334,7 @@ maxmulti_show (struct device *dev, char *buf)
static ssize_t static ssize_t
maxmulti_write (struct device *dev, const char *buf, size_t count) maxmulti_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
priv->conn->prof.maxmulti = 0; priv->conn->prof.maxmulti = 0;
return count; return count;
...@@ -1395,7 +1345,7 @@ static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write); ...@@ -1395,7 +1345,7 @@ static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
static ssize_t static ssize_t
maxcq_show (struct device *dev, char *buf) maxcq_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue); return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
} }
...@@ -1403,7 +1353,7 @@ maxcq_show (struct device *dev, char *buf) ...@@ -1403,7 +1353,7 @@ maxcq_show (struct device *dev, char *buf)
static ssize_t static ssize_t
maxcq_write (struct device *dev, const char *buf, size_t count) maxcq_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
priv->conn->prof.maxcqueue = 0; priv->conn->prof.maxcqueue = 0;
return count; return count;
...@@ -1414,7 +1364,7 @@ static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write); ...@@ -1414,7 +1364,7 @@ static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
static ssize_t static ssize_t
sdoio_show (struct device *dev, char *buf) sdoio_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%ld\n", priv->conn->prof.doios_single); return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
} }
...@@ -1422,7 +1372,7 @@ sdoio_show (struct device *dev, char *buf) ...@@ -1422,7 +1372,7 @@ sdoio_show (struct device *dev, char *buf)
static ssize_t static ssize_t
sdoio_write (struct device *dev, const char *buf, size_t count) sdoio_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
priv->conn->prof.doios_single = 0; priv->conn->prof.doios_single = 0;
return count; return count;
...@@ -1433,7 +1383,7 @@ static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write); ...@@ -1433,7 +1383,7 @@ static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
static ssize_t static ssize_t
mdoio_show (struct device *dev, char *buf) mdoio_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi); return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
} }
...@@ -1441,7 +1391,7 @@ mdoio_show (struct device *dev, char *buf) ...@@ -1441,7 +1391,7 @@ mdoio_show (struct device *dev, char *buf)
static ssize_t static ssize_t
mdoio_write (struct device *dev, const char *buf, size_t count) mdoio_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
priv->conn->prof.doios_multi = 0; priv->conn->prof.doios_multi = 0;
return count; return count;
...@@ -1452,7 +1402,7 @@ static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write); ...@@ -1452,7 +1402,7 @@ static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
static ssize_t static ssize_t
txlen_show (struct device *dev, char *buf) txlen_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%ld\n", priv->conn->prof.txlen); return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
} }
...@@ -1460,7 +1410,7 @@ txlen_show (struct device *dev, char *buf) ...@@ -1460,7 +1410,7 @@ txlen_show (struct device *dev, char *buf)
static ssize_t static ssize_t
txlen_write (struct device *dev, const char *buf, size_t count) txlen_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
priv->conn->prof.txlen = 0; priv->conn->prof.txlen = 0;
return count; return count;
...@@ -1471,7 +1421,7 @@ static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write); ...@@ -1471,7 +1421,7 @@ static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
static ssize_t static ssize_t
txtime_show (struct device *dev, char *buf) txtime_show (struct device *dev, char *buf)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%ld\n", priv->conn->prof.tx_time); return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
} }
...@@ -1479,7 +1429,7 @@ txtime_show (struct device *dev, char *buf) ...@@ -1479,7 +1429,7 @@ txtime_show (struct device *dev, char *buf)
static ssize_t static ssize_t
txtime_write (struct device *dev, const char *buf, size_t count) txtime_write (struct device *dev, const char *buf, size_t count)
{ {
netiucv_priv *priv = dev->driver_data; struct netiucv_priv *priv = dev->driver_data;
priv->conn->prof.tx_time = 0; priv->conn->prof.tx_time = 0;
return count; return count;
...@@ -1492,8 +1442,7 @@ netiucv_add_files(struct device *dev) ...@@ -1492,8 +1442,7 @@ netiucv_add_files(struct device *dev)
{ {
int ret = 0; int ret = 0;
if ((ret = device_create_file(dev, &dev_attr_user)) || if ((ret = device_create_file(dev, &dev_attr_buffer)) ||
(ret = device_create_file(dev, &dev_attr_buffer)) ||
(ret = device_create_file(dev, &dev_attr_device_fsm_state)) || (ret = device_create_file(dev, &dev_attr_device_fsm_state)) ||
(ret = device_create_file(dev, &dev_attr_connection_fsm_state)) || (ret = device_create_file(dev, &dev_attr_connection_fsm_state)) ||
(ret = device_create_file(dev, &dev_attr_max_tx_buffer_used)) || (ret = device_create_file(dev, &dev_attr_max_tx_buffer_used)) ||
...@@ -1510,7 +1459,6 @@ netiucv_add_files(struct device *dev) ...@@ -1510,7 +1459,6 @@ netiucv_add_files(struct device *dev)
device_remove_file(dev, &dev_attr_connection_fsm_state); device_remove_file(dev, &dev_attr_connection_fsm_state);
device_remove_file(dev, &dev_attr_device_fsm_state); device_remove_file(dev, &dev_attr_device_fsm_state);
device_remove_file(dev, &dev_attr_buffer); device_remove_file(dev, &dev_attr_buffer);
device_remove_file(dev, &dev_attr_user);
} }
return ret; return ret;
} }
...@@ -1518,53 +1466,53 @@ netiucv_add_files(struct device *dev) ...@@ -1518,53 +1466,53 @@ netiucv_add_files(struct device *dev)
static int static int
netiucv_register_device(struct net_device *ndev, int ifno) netiucv_register_device(struct net_device *ndev, int ifno)
{ {
netiucv_priv *priv = ndev->priv; struct netiucv_priv *priv = ndev->priv;
struct platform_device *pldev = &priv->pldev; struct device *dev = &priv->dev;
int ret; int ret;
char *str = "netiucv"; char *str = "netiucv";
snprintf(pldev->dev.name, DEVICE_NAME_SIZE, snprintf(dev->name, DEVICE_NAME_SIZE, "%s", priv->conn->userid);
"%s%x", str, ifno); snprintf(dev->bus_id, BUS_ID_SIZE, "%s%x", str, ifno);
pldev->name = str; dev->bus = &iucv_bus;
pldev->id = ifno; dev->parent = &iucv_root;
ret = platform_device_register(pldev); ret = device_register(dev);
if (ret) if (ret)
return ret; return ret;
ret = netiucv_add_files(&pldev->dev); ret = netiucv_add_files(dev);
if (ret) if (ret)
platform_device_unregister(pldev); device_unregister(dev);
else else
pldev->dev.driver_data = priv; dev->driver_data = priv;
return ret; return ret;
} }
#ifdef MODULE
static void static void
netiucv_unregister_device(struct net_device *ndev) netiucv_unregister_device(struct net_device *ndev)
{ {
netiucv_priv *priv = (netiucv_priv*)ndev->priv; struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
struct platform_device *pldev = &priv->pldev; struct device *dev = &priv->dev;
platform_device_unregister(pldev); device_unregister(dev);
} }
#endif
/** /**
* Allocate and initialize a new connection structure. * Allocate and initialize a new connection structure.
* Add it to the list of connections; * Add it to the list of connections;
*/ */
static iucv_connection * static struct iucv_connection *
netiucv_new_connection(net_device *dev, char *username) netiucv_new_connection(struct net_device *dev, char *username)
{ {
iucv_connection **clist = &connections; struct iucv_connection **clist = &connections;
iucv_connection *conn = struct iucv_connection *conn =
(iucv_connection *)kmalloc(sizeof(iucv_connection), GFP_KERNEL); (struct iucv_connection *)
kmalloc(sizeof(struct iucv_connection), GFP_KERNEL);
if (conn) { if (conn) {
memset(conn, 0, sizeof(iucv_connection)); memset(conn, 0, sizeof(struct iucv_connection));
skb_queue_head_init(&conn->collect_queue); skb_queue_head_init(&conn->collect_queue);
conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT; conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
conn->netdev = dev; conn->netdev = dev;
...@@ -1609,9 +1557,9 @@ netiucv_new_connection(net_device *dev, char *username) ...@@ -1609,9 +1557,9 @@ netiucv_new_connection(net_device *dev, char *username)
* list of connections. * list of connections.
*/ */
static void static void
netiucv_remove_connection(iucv_connection *conn) netiucv_remove_connection(struct iucv_connection *conn)
{ {
iucv_connection **clist = &connections; struct iucv_connection **clist = &connections;
if (conn == NULL) if (conn == NULL)
return; return;
...@@ -1635,26 +1583,26 @@ netiucv_remove_connection(iucv_connection *conn) ...@@ -1635,26 +1583,26 @@ netiucv_remove_connection(iucv_connection *conn)
/** /**
* Allocate and initialize everything of a net device. * Allocate and initialize everything of a net device.
*/ */
static net_device * static struct net_device *
netiucv_init_netdevice(int ifno, char *username) netiucv_init_netdevice(int ifno, char *username)
{ {
netiucv_priv *privptr; struct netiucv_priv *privptr;
int priv_size; int priv_size;
net_device *dev = kmalloc(sizeof(net_device), GFP_KERNEL); struct net_device *dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (!dev) if (!dev)
return NULL; return NULL;
memset(dev, 0, sizeof(net_device)); memset(dev, 0, sizeof(struct net_device));
sprintf(dev->name, "iucv%d", ifno); sprintf(dev->name, "iucv%d", ifno);
priv_size = sizeof(netiucv_priv); priv_size = sizeof(struct netiucv_priv);
dev->priv = kmalloc(priv_size, GFP_KERNEL); dev->priv = kmalloc(priv_size, GFP_KERNEL);
if (dev->priv == NULL) { if (dev->priv == NULL) {
kfree(dev); kfree(dev);
return NULL; return NULL;
} }
memset(dev->priv, 0, priv_size); memset(dev->priv, 0, priv_size);
privptr = (netiucv_priv *)dev->priv; privptr = (struct netiucv_priv *)dev->priv;
privptr->fsm = init_fsm("netiucvdev", dev_state_names, privptr->fsm = init_fsm("netiucvdev", dev_state_names,
dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS, dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
dev_fsm, DEV_FSM_LEN, GFP_KERNEL); dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
...@@ -1691,14 +1639,14 @@ netiucv_init_netdevice(int ifno, char *username) ...@@ -1691,14 +1639,14 @@ netiucv_init_netdevice(int ifno, char *username)
* Allocate and initialize everything of a net device. * Allocate and initialize everything of a net device.
*/ */
static void static void
netiucv_free_netdevice(net_device *dev) netiucv_free_netdevice(struct net_device *dev)
{ {
netiucv_priv *privptr; struct netiucv_priv *privptr;
if (!dev) if (!dev)
return; return;
privptr = (netiucv_priv *)dev->priv; privptr = (struct netiucv_priv *)dev->priv;
if (privptr) { if (privptr) {
if (privptr->conn) if (privptr->conn)
netiucv_remove_connection(privptr->conn); netiucv_remove_connection(privptr->conn);
...@@ -1709,10 +1657,67 @@ netiucv_free_netdevice(net_device *dev) ...@@ -1709,10 +1657,67 @@ netiucv_free_netdevice(net_device *dev)
kfree(dev); kfree(dev);
} }
static ssize_t
conn_write(struct device_driver *drv, const char *buf, size_t count)
{
char *p;
char username[10];
int i;
struct net_device *dev;
if (count>9) {
printk(KERN_WARNING
"netiucv: username too long (%d)!\n", (int)count);
return -EINVAL;
}
for (i=0, p=(char *)buf; i<8 && *p; i++, p++) {
if (isalnum(*p))
username[i]= *p;
else if (*p == '\n') {
/* trailing lf, grr */
break;
} else {
printk(KERN_WARNING
"netiucv: Invalid character in username!\n");
return -EINVAL;
}
}
while (i<9)
username[i++] = ' ';
username[9] = '\0';
dev = netiucv_init_netdevice(ifno, username);
if (!dev) {
printk(KERN_WARNING
"netiucv: Could not allocate network device structure "
"for user '%s'\n", netiucv_printname(username));
return -ENODEV;
}
if (register_netdev(dev)) {
printk(KERN_WARNING
"netiucv: Could not register '%s'\n", dev->name);
netiucv_free_netdevice(dev);
return -ENODEV;
}
printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username));
netiucv_register_device(dev, ifno);
ifno++;
return count;
}
DRIVER_ATTR(connection, 0200, NULL, conn_write);
static struct device_driver netiucv_driver = {
.name = "NETIUCV",
.bus = &iucv_bus,
};
static void static void
netiucv_banner(void) netiucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.12 $"; char vbuf[] = "$Revision: 1.16 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
...@@ -1724,101 +1729,65 @@ netiucv_banner(void) ...@@ -1724,101 +1729,65 @@ netiucv_banner(void)
printk(KERN_INFO "NETIUCV driver Version%s initialized\n", version); printk(KERN_INFO "NETIUCV driver Version%s initialized\n", version);
} }
#ifndef MODULE
static int __init
iucv_setup(char *param)
{
/**
* We do not parse parameters here because at the time of
* calling iucv_setup(), the kernel does not yet have
* memory management running. We delay this until probing
* is called.
*/
iucv = param;
return 1;
}
__setup ("iucv=", iucv_setup);
#else
static void __exit static void __exit
netiucv_exit(void) netiucv_exit(void)
{ {
while (connections) { while (connections) {
net_device *dev = connections->netdev; struct net_device *dev = connections->netdev;
unregister_netdev(dev); unregister_netdev(dev);
netiucv_unregister_device(dev); netiucv_unregister_device(dev);
netiucv_free_netdevice(dev); netiucv_free_netdevice(dev);
} }
driver_remove_file(&netiucv_driver, &driver_attr_connection);
driver_unregister(&netiucv_driver);
bus_unregister(&iucv_bus);
printk(KERN_INFO "NETIUCV driver unloaded\n"); printk(KERN_INFO "NETIUCV driver unloaded\n");
return; return;
} }
module_exit(netiucv_exit);
#endif
static int __init static int __init
netiucv_init(void) netiucv_init(void)
{ {
char *p = iucv; int ret;
int ifno = 0;
int i = 0; /* Move the bus stuff to iucv.c? - CH */
char username[10]; ret = bus_register(&iucv_bus);
if (ret != 0) {
printk(KERN_ERR "NETIUCV: failed to register bus.\n");
return ret;
}
while (p) { ret = driver_register(&netiucv_driver);
if (isalnum(*p)) { if (ret != 0) {
username[i++] = *p++; printk(KERN_ERR "NETIUCV: failed to register driver.\n");
username[i] = '\0'; bus_unregister(&iucv_bus);
if (i > 8) { return ret;
printk(KERN_WARNING
"netiucv: Invalid user name '%s'\n",
username);
while (*p && (*p != ':') && (*p != ','))
p++;
}
} else {
if (*p && (*p != ':') && (*p != ',')) {
printk(KERN_WARNING
"netiucv: Invalid delimiter '%c'\n",
*p);
while (*p && (*p != ':') && (*p != ','))
p++;
} else {
if (i) {
net_device *dev;
while (i < 9)
username[i++] = ' ';
username[9] = '\0';
dev = netiucv_init_netdevice(ifno,
username);
if (!dev)
printk(KERN_WARNING
"netiucv: Could not allocate network device structure for user '%s'\n", netiucv_printname(username));
else {
if (register_netdev(dev)) {
printk(KERN_WARNING
"netiucv: Could not register '%s'\n", dev->name);
netiucv_free_netdevice(dev);
} else {
printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username));
netiucv_register_device(dev, ifno);
ifno++;
}
}
}
if (!(*p))
break;
i = 0;
p++;
}
}
} }
netiucv_banner();
return 0;
}
ret = device_register(&iucv_root);
if (ret != 0) {
printk(KERN_ERR "NETIUCV: failed to register iucv root.\n");
driver_unregister(&netiucv_driver);
bus_unregister(&iucv_bus);
return ret;
}
/* Add entry for specifying connections. */
ret = driver_create_file(&netiucv_driver, &driver_attr_connection);
if (ret == 0)
netiucv_banner();
else {
printk(KERN_ERR "NETIUCV: failed to add driver attribute.\n");
device_unregister(&iucv_root);
driver_unregister(&netiucv_driver);
bus_unregister(&iucv_bus);
}
return ret;
}
module_init(netiucv_init); module_init(netiucv_init);
module_exit(netiucv_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment