summaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/netiucv.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-08 13:50:33 -0800
committerDavid S. Miller <davem@davemloft.net>2007-02-08 13:50:33 -0800
commiteebce38567373e3abbb640ab145d154831cc55df (patch)
treec2d6406c5215e8e22c6c30fdb6737da0119e8285 /drivers/s390/net/netiucv.c
parentc9101c5b3f1d018efa36d12cdcde89955642c73d (diff)
[S390]: Adapt netiucv driver to new IUCV API
Adapt netiucv network device driver to new IUCV API Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net/netiucv.c')
-rw-r--r--drivers/s390/net/netiucv.c1314
1 files changed, 652 insertions, 662 deletions
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3346088f47e0..6387b483f2bf 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,7 +1,7 @@
/*
* IUCV network driver
*
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
*
* Sysfs integration and all bugs therein by Cornelia Huck
@@ -58,13 +58,94 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-#include "iucv.h"
+#include <net/iucv/iucv.h>
#include "fsm.h"
MODULE_AUTHOR
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
+/**
+ * Debug Facility stuff
+ */
+#define IUCV_DBF_SETUP_NAME "iucv_setup"
+#define IUCV_DBF_SETUP_LEN 32
+#define IUCV_DBF_SETUP_PAGES 2
+#define IUCV_DBF_SETUP_NR_AREAS 1
+#define IUCV_DBF_SETUP_LEVEL 3
+
+#define IUCV_DBF_DATA_NAME "iucv_data"
+#define IUCV_DBF_DATA_LEN 128
+#define IUCV_DBF_DATA_PAGES 2
+#define IUCV_DBF_DATA_NR_AREAS 1
+#define IUCV_DBF_DATA_LEVEL 2
+
+#define IUCV_DBF_TRACE_NAME "iucv_trace"
+#define IUCV_DBF_TRACE_LEN 16
+#define IUCV_DBF_TRACE_PAGES 4
+#define IUCV_DBF_TRACE_NR_AREAS 1
+#define IUCV_DBF_TRACE_LEVEL 3
+
+#define IUCV_DBF_TEXT(name,level,text) \
+ do { \
+ debug_text_event(iucv_dbf_##name,level,text); \
+ } while (0)
+
+#define IUCV_DBF_HEX(name,level,addr,len) \
+ do { \
+ debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
+ } while (0)
+
+DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
+
+#define IUCV_DBF_TEXT_(name,level,text...) \
+ do { \
+ char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \
+ sprintf(iucv_dbf_txt_buf, text); \
+ debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
+ put_cpu_var(iucv_dbf_txt_buf); \
+ } while (0)
+
+#define IUCV_DBF_SPRINTF(name,level,text...) \
+ do { \
+ debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
+ debug_sprintf_event(iucv_dbf_trace, level, text ); \
+ } while (0)
+
+/**
+ * some more debug stuff
+ */
+#define IUCV_HEXDUMP16(importance,header,ptr) \
+PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+ *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+ *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+ *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+ *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+ *(((char*)ptr)+12),*(((char*)ptr)+13), \
+ *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+ *(((char*)ptr)+16),*(((char*)ptr)+17), \
+ *(((char*)ptr)+18),*(((char*)ptr)+19), \
+ *(((char*)ptr)+20),*(((char*)ptr)+21), \
+ *(((char*)ptr)+22),*(((char*)ptr)+23), \
+ *(((char*)ptr)+24),*(((char*)ptr)+25), \
+ *(((char*)ptr)+26),*(((char*)ptr)+27), \
+ *(((char*)ptr)+28),*(((char*)ptr)+29), \
+ *(((char*)ptr)+30),*(((char*)ptr)+31));
+
+static inline void iucv_hex_dump(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (i && !(i % 16))
+ printk("\n");
+ printk("%02x ", *(buf + i));
+ }
+ printk("\n");
+}
#define PRINTK_HEADER " iucv: " /* for debugging */
@@ -73,6 +154,25 @@ static struct device_driver netiucv_driver = {
.bus = &iucv_bus,
};
+static int netiucv_callback_connreq(struct iucv_path *,
+ u8 ipvmid[8], u8 ipuser[16]);
+static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *);
+static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *);
+
+static struct iucv_handler netiucv_handler = {
+ .path_pending = netiucv_callback_connreq,
+ .path_complete = netiucv_callback_connack,
+ .path_severed = netiucv_callback_connrej,
+ .path_quiesced = netiucv_callback_connsusp,
+ .path_resumed = netiucv_callback_connres,
+ .message_pending = netiucv_callback_rx,
+ .message_complete = netiucv_callback_txdone
+};
+
/**
* Per connection profiling data
*/
@@ -92,9 +192,8 @@ struct connection_profile {
* Representation of one iucv connection
*/
struct iucv_connection {
- struct iucv_connection *next;
- iucv_handle_t handle;
- __u16 pathid;
+ struct list_head list;
+ struct iucv_path *path;
struct sk_buff *rx_buff;
struct sk_buff *tx_buff;
struct sk_buff_head collect_queue;
@@ -112,12 +211,9 @@ struct iucv_connection {
/**
* Linked list of all connection structs.
*/
-struct iucv_connection_struct {
- struct iucv_connection *iucv_connections;
- rwlock_t iucv_rwlock;
-};
-
-static struct iucv_connection_struct iucv_conns;
+static struct list_head iucv_connection_list =
+ LIST_HEAD_INIT(iucv_connection_list);
+static rwlock_t iucv_connection_rwlock = RW_LOCK_UNLOCKED;
/**
* Representation of event-data for the
@@ -142,11 +238,11 @@ struct netiucv_priv {
/**
* Link level header for a packet.
*/
-typedef struct ll_header_t {
- __u16 next;
-} ll_header;
+struct ll_header {
+ u16 next;
+};
-#define NETIUCV_HDRLEN (sizeof(ll_header))
+#define NETIUCV_HDRLEN (sizeof(struct ll_header))
#define NETIUCV_BUFSIZE_MAX 32768
#define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX
#define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)
@@ -158,36 +254,26 @@ typedef struct ll_header_t {
* Compatibility macros for busy handling
* of network devices.
*/
-static __inline__ void netiucv_clear_busy(struct net_device *dev)
+static inline void netiucv_clear_busy(struct net_device *dev)
{
- clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy));
+ struct netiucv_priv *priv = netdev_priv(dev);
+ clear_bit(0, &priv->tbusy);
netif_wake_queue(dev);
}
-static __inline__ int netiucv_test_and_set_busy(struct net_device *dev)
+static inline int netiucv_test_and_set_busy(struct net_device *dev)
{
+ struct netiucv_priv *priv = netdev_priv(dev);
netif_stop_queue(dev);
- return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);
+ return test_and_set_bit(0, &priv->tbusy);
}
-static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static __u8 iucvMagic[16] = {
+static u8 iucvMagic[16] = {
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
};
/**
- * This mask means the 16-byte IUCV "magic" and the origin userid must
- * match exactly as specified in order to give connection_pending()
- * control.
- */
-static __u8 netiucv_mask[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-/**
* Convert an iucv userId to its printable
* form (strip whitespace at end).
*
@@ -195,8 +281,7 @@ static __u8 netiucv_mask[] = {
*
* @returns The printable string (static data!!)
*/
-static __inline__ char *
-netiucv_printname(char *name)
+static inline char *netiucv_printname(char *name)
{
static char tmp[9];
char *p = tmp;
@@ -379,8 +464,7 @@ static debug_info_t *iucv_dbf_trace = NULL;
DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);
-static void
-iucv_unregister_dbf_views(void)
+static void iucv_unregister_dbf_views(void)
{
if (iucv_dbf_setup)
debug_unregister(iucv_dbf_setup);
@@ -389,8 +473,7 @@ iucv_unregister_dbf_views(void)
if (iucv_dbf_trace)
debug_unregister(iucv_dbf_trace);
}
-static int
-iucv_register_dbf_views(void)
+static int iucv_register_dbf_views(void)
{
iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
IUCV_DBF_SETUP_PAGES,
@@ -422,125 +505,111 @@ iucv_register_dbf_views(void)
return 0;
}
-/**
+/*
* Callback-wrappers, called from lowlevel iucv layer.
- *****************************************************************************/
+ */
-static void
-netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
+static void netiucv_callback_rx(struct iucv_path *path,
+ struct iucv_message *msg)
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+ struct iucv_connection *conn = path->private;
struct iucv_event ev;
ev.conn = conn;
- ev.data = (void *)eib;
-
+ ev.data = msg;
fsm_event(conn->fsm, CONN_EVENT_RX, &ev);
}
-static void
-netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
+static void netiucv_callback_txdone(struct iucv_path *path,
+ struct iucv_message *msg)
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+ struct iucv_connection *conn = path->private;
struct iucv_event ev;
ev.conn = conn;
- ev.data = (void *)eib;
+ ev.data = msg;
fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);
}
-static void
-netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
+static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);
+ fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn);
}
-static void
-netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
+static int netiucv_callback_connreq(struct iucv_path *path,
+ u8 ipvmid[8], u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+ struct iucv_connection *conn = path->private;
struct iucv_event ev;
+ int rc;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
+ if (memcmp(iucvMagic, ipuser, sizeof(ipuser)))
+ /* ipuser must match iucvMagic. */
+ return -EINVAL;
+ rc = -EINVAL;
+ read_lock_bh(&iucv_connection_rwlock);
+ list_for_each_entry(conn, &iucv_connection_list, list) {
+ if (strncmp(ipvmid, conn->userid, 8))
+ continue;
+ /* Found a matching connection for this path. */
+ conn->path = path;
+ ev.conn = conn;
+ ev.data = path;
+ fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
+ rc = 0;
+ }
+ read_unlock_bh(&iucv_connection_rwlock);
+ return rc;
}
-static void
-netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
+static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, &ev);
+ fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn);
}
-static void
-netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
+static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, &ev);
+ fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn);
}
-static void
-netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
+static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_RES, &ev);
-}
-
-static iucv_interrupt_ops_t netiucv_ops = {
- .ConnectionPending = netiucv_callback_connreq,
- .ConnectionComplete = netiucv_callback_connack,
- .ConnectionSevered = netiucv_callback_connrej,
- .ConnectionQuiesced = netiucv_callback_connsusp,
- .ConnectionResumed = netiucv_callback_connres,
- .MessagePending = netiucv_callback_rx,
- .MessageComplete = netiucv_callback_txdone
-};
+ fsm_event(conn->fsm, CONN_EVENT_CONN_RES, conn);
+}
/**
* Dummy NOP action for all statemachines
*/
-static void
-fsm_action_nop(fsm_instance *fi, int event, void *arg)
+static void fsm_action_nop(fsm_instance *fi, int event, void *arg)
{
}
-/**
+/*
* Actions of the connection statemachine
- *****************************************************************************/
+ */
/**
- * Helper function for conn_action_rx()
- * Unpack a just received skb and hand it over to
- * upper layers.
+ * netiucv_unpack_skb
+ * @conn: The connection where this skb has been received.
+ * @pskb: The received skb.
*
- * @param conn The connection where this skb has been received.
- * @param pskb The received skb.
+ * Unpack a just received skb and hand it over to upper layers.
+ * Helper function for conn_action_rx.
*/
-//static __inline__ void
-static void
-netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
+static void netiucv_unpack_skb(struct iucv_connection *conn,
+ struct sk_buff *pskb)
{
struct net_device *dev = conn->netdev;
- struct netiucv_priv *privptr = dev->priv;
- __u16 offset = 0;
+ struct netiucv_priv *privptr = netdev_priv(dev);
+ u16 offset = 0;
skb_put(pskb, NETIUCV_HDRLEN);
pskb->dev = dev;
@@ -549,7 +618,7 @@ netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
while (1) {
struct sk_buff *skb;
- ll_header *header = (ll_header *)pskb->data;
+ struct ll_header *header = (struct ll_header *) pskb->data;
if (!header->next)
break;
@@ -595,40 +664,37 @@ netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
}
}
-static void
-conn_action_rx(fsm_instance *fi, int event, void *arg)
+static void conn_action_rx(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
- iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
- struct netiucv_priv *privptr =(struct netiucv_priv *)conn->netdev->priv;
-
- __u32 msglen = eib->ln1msg2.ipbfln1f;
+ struct iucv_message *msg = ev->data;
+ struct netiucv_priv *privptr = netdev_priv(conn->netdev);
int rc;
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
if (!conn->netdev) {
- /* FRITZ: How to tell iucv LL to drop the msg? */
+ iucv_message_reject(conn->path, msg);
PRINT_WARN("Received data for unlinked connection\n");
IUCV_DBF_TEXT(data, 2,
- "Received data for unlinked connection\n");
+ "Received data for unlinked connection\n");
return;
}
- if (msglen > conn->max_buffsize) {
- /* FRITZ: How to tell iucv LL to drop the msg? */
+ if (msg->length > conn->max_buffsize) {
+ iucv_message_reject(conn->path, msg);
privptr->stats.rx_dropped++;
PRINT_WARN("msglen %d > max_buffsize %d\n",
- msglen, conn->max_buffsize);
+ msg->length, conn->max_buffsize);
IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n",
- msglen, conn->max_buffsize);
+ msg->length, conn->max_buffsize);
return;
}
conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head;
conn->rx_buff->len = 0;
- rc = iucv_receive(conn->pathid, eib->ipmsgid, eib->iptrgcls,
- conn->rx_buff->data, msglen, NULL, NULL, NULL);
- if (rc || msglen < 5) {
+ rc = iucv_message_receive(conn->path, msg, 0, conn->rx_buff->data,
+ msg->length, NULL);
+ if (rc || msg->length < 5) {
privptr->stats.rx_errors++;
PRINT_WARN("iucv_receive returned %08x\n", rc);
IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc);
@@ -637,26 +703,26 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
netiucv_unpack_skb(conn, conn->rx_buff);
}
-static void
-conn_action_txdone(fsm_instance *fi, int event, void *arg)
+static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
- iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
+ struct iucv_message *msg = ev->data;
+ struct iucv_message txmsg;
struct netiucv_priv *privptr = NULL;
- /* Shut up, gcc! skb is always below 2G. */
- __u32 single_flag = eib->ipmsgtag;
- __u32 txbytes = 0;
- __u32 txpackets = 0;
- __u32 stat_maxcq = 0;
+ u32 single_flag = msg->tag;
+ u32 txbytes = 0;
+ u32 txpackets = 0;
+ u32 stat_maxcq = 0;
struct sk_buff *skb;
unsigned long saveflags;
- ll_header header;
+ struct ll_header header;
+ int rc;
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
- if (conn && conn->netdev && conn->netdev->priv)
- privptr = (struct netiucv_priv *)conn->netdev->priv;
+ if (conn && conn->netdev)
+ privptr = netdev_priv(conn->netdev);
conn->prof.tx_pending--;
if (single_flag) {
if ((skb = skb_dequeue(&conn->commit_queue))) {
@@ -688,56 +754,55 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
conn->prof.maxmulti = conn->collect_len;
conn->collect_len = 0;
spin_unlock_irqrestore(&conn->collect_lock, saveflags);
- if (conn->tx_buff->len) {
- int rc;
-
- header.next = 0;
- memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
- NETIUCV_HDRLEN);
+ if (conn->tx_buff->len == 0) {
+ fsm_newstate(fi, CONN_STATE_IDLE);
+ return;
+ }
- conn->prof.send_stamp = xtime;
- rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,
+ header.next = 0;
+ memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
+ conn->prof.send_stamp = xtime;
+ txmsg.class = 0;
+ txmsg.tag = 0;
+ rc = iucv_message_send(conn->path, &txmsg, 0, 0,
conn->tx_buff->data, conn->tx_buff->len);
- conn->prof.doios_multi++;
- conn->prof.txlen += conn->tx_buff->len;
- conn->prof.tx_pending++;
- if (conn->prof.tx_pending > conn->prof.tx_max_pending)
- conn->prof.tx_max_pending = conn->prof.tx_pending;
- if (rc) {
- conn->prof.tx_pending--;
- fsm_newstate(fi, CONN_STATE_IDLE);
- if (privptr)
- privptr->stats.tx_errors += txpackets;
- PRINT_WARN("iucv_send returned %08x\n", rc);
- IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
- } else {
- if (privptr) {
- privptr->stats.tx_packets += txpackets;
- privptr->stats.tx_bytes += txbytes;
- }
- if (stat_maxcq > conn->prof.maxcqueue)
- conn->prof.maxcqueue = stat_maxcq;
- }
- } else
+ conn->prof.doios_multi++;
+ conn->prof.txlen += conn->tx_buff->len;
+ conn->prof.tx_pending++;
+ if (conn->prof.tx_pending > conn->prof.tx_max_pending)
+ conn->prof.tx_max_pending = conn->prof.tx_pending;
+ if (rc) {
+ conn->prof.tx_pending--;
fsm_newstate(fi, CONN_STATE_IDLE);
+ if (privptr)
+ privptr->stats.tx_errors += txpackets;
+ PRINT_WARN("iucv_send returned %08x\n", rc);
+ IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
+ } else {
+ if (privptr) {
+ privptr->stats.tx_packets += txpackets;
+ privptr->stats.tx_bytes += txbytes;
+ }
+ if (stat_maxcq > conn->prof.maxcqueue)
+ conn->prof.maxcqueue = stat_maxcq;
+ }
}
-static void
-conn_action_connaccept(fsm_instance *fi, int event, void *arg)
+static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
- iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
+ struct iucv_path *path = ev->data;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
int rc;
- __u16 msglimit;
- __u8 udata[16];
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,
- conn->handle, conn, NULL, &msglimit);
+ conn->path = path;
+ path->msglim = NETIUCV_QUEUELEN_DEFAULT;
+ path->flags = 0;
+ rc = iucv_path_accept(path, &netiucv_handler, NULL, conn);
if (rc) {
PRINT_WARN("%s: IUCV accept failed with error %d\n",
netdev->name, rc);
@@ -745,183 +810,126 @@ conn_action_connaccept(fsm_instance *fi, int event, void *arg)
return;
}
fsm_newstate(fi, CONN_STATE_IDLE);
- conn->pathid = eib->ippathid;
- netdev->tx_queue_len = msglimit;
+ netdev->tx_queue_len = conn->path->msglim;
fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
}
-static void
-conn_action_connreject(fsm_instance *fi, int event, void *arg)
+static void conn_action_connreject(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
- struct net_device *netdev = conn->netdev;
- iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
- __u8 udata[16];
+ struct iucv_event *ev = arg;
+ struct iucv_path *path = ev->data;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
- iucv_sever(eib->ippathid, udata);
- if (eib->ippathid != conn->pathid) {
- PRINT_INFO("%s: IR Connection Pending; "
- "pathid %d does not match original pathid %d\n",
- netdev->name, eib->ippathid, conn->pathid);
- IUCV_DBF_TEXT_(data, 2,
- "connreject: IR pathid %d, conn. pathid %d\n",
- eib->ippathid, conn->pathid);
- iucv_sever(conn->pathid, udata);
- }
+ iucv_path_sever(path, NULL);
}
-static void
-conn_action_connack(fsm_instance *fi, int event, void *arg)
+static void conn_action_connack(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
- iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
+ struct iucv_connection *conn = arg;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_IDLE);
- if (eib->ippathid != conn->pathid) {
- PRINT_INFO("%s: IR Connection Complete; "
- "pathid %d does not match original pathid %d\n",
- netdev->name, eib->ippathid, conn->pathid);
- IUCV_DBF_TEXT_(data, 2,
- "connack: IR pathid %d, conn. pathid %d\n",
- eib->ippathid, conn->pathid);
- conn->pathid = eib->ippathid;
- }
- netdev->tx_queue_len = eib->ipmsglim;
+ netdev->tx_queue_len = conn->path->msglim;
fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
}
-static void
-conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
+static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
{
- struct iucv_connection *conn = (struct iucv_connection *)arg;
- __u8 udata[16];
+ struct iucv_connection *conn = arg;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
fsm_deltimer(&conn->timer);
- iucv_sever(conn->pathid, udata);
+ iucv_path_sever(conn->path, NULL);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
}
-static void
-conn_action_connsever(fsm_instance *fi, int event, void *arg)
+static void conn_action_connsever(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
+ struct iucv_connection *conn = arg;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
- __u8 udata[16];
+ struct netiucv_priv *privptr = netdev_priv(netdev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
fsm_deltimer(&conn->timer);
- iucv_sever(conn->pathid, udata);
+ iucv_path_sever(conn->path, NULL);
PRINT_INFO("%s: Remote dropped connection\n", netdev->name);
IUCV_DBF_TEXT(data, 2,
- "conn_action_connsever: Remote dropped connection\n");
+ "conn_action_connsever: Remote dropped connection\n");
fsm_newstate(fi, CONN_STATE_STARTWAIT);
fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
}
-static void
-conn_action_start(fsm_instance *fi, int event, void *arg)
+static void conn_action_start(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
- __u16 msglimit;
+ struct iucv_connection *conn = arg;
int rc;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- if (!conn->handle) {
- IUCV_DBF_TEXT(trace, 5, "calling iucv_register_program\n");
- conn->handle =
- iucv_register_program(iucvMagic, conn->userid,
- netiucv_mask,
- &netiucv_ops, conn);
- fsm_newstate(fi, CONN_STATE_STARTWAIT);
- if (!conn->handle) {
- fsm_newstate(fi, CONN_STATE_REGERR);
- conn->handle = NULL;
- IUCV_DBF_TEXT(setup, 2,
- "NULL from iucv_register_program\n");
- return;
- }
-
- PRINT_DEBUG("%s('%s'): registered successfully\n",
- conn->netdev->name, conn->userid);
- }
-
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
PRINT_DEBUG("%s('%s'): connecting ...\n",
- conn->netdev->name, conn->userid);
+ conn->netdev->name, conn->userid);
- /* We must set the state before calling iucv_connect because the callback
- * handler could be called at any point after the connection request is
- * sent */
+ /*
+ * We must set the state before calling iucv_connect because the
+ * callback handler could be called at any point after the connection
+ * request is sent
+ */
fsm_newstate(fi, CONN_STATE_SETUPWAIT);
- rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
- conn->userid, iucv_host, 0, NULL, &msglimit,
- conn->handle, conn);
+ conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL);
+ rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid,
+ NULL, iucvMagic, conn);
switch (rc) {
- case 0:
- conn->netdev->tx_queue_len = msglimit;
- fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
- CONN_EVENT_TIMER, conn);
- return;
- case 11:
- PRINT_INFO("%s: User %s is currently not available.\n",
- conn->netdev->name,
- netiucv_printname(conn->userid));
- fsm_newstate(fi, CONN_STATE_STARTWAIT);
- return;
- case 12:
- PRINT_INFO("%s: User %s is currently not ready.\n",
- conn->netdev->name,
- netiucv_printname(conn->userid));
- fsm_newstate(fi, CONN_STATE_STARTWAIT);
- return;
- case 13:
- PRINT_WARN("%s: Too many IUCV connections.\n",
- conn->netdev->name);
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
- case 14:
- PRINT_WARN(
- "%s: User %s has too many IUCV connections.\n",
- conn->netdev->name,
- netiucv_printname(conn->userid));
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
- case 15:
- PRINT_WARN(
- "%s: No IUCV authorization in CP directory.\n",
- conn->netdev->name);
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
- default:
- PRINT_WARN("%s: iucv_connect returned error %d\n",
- conn->netdev->name, rc);
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
+ case 0:
+ conn->netdev->tx_queue_len = conn->path->msglim;
+ fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
+ CONN_EVENT_TIMER, conn);
+ return;
+ case 11:
+ PRINT_INFO("%s: User %s is currently not available.\n",
+ conn->netdev->name,
+ netiucv_printname(conn->userid));
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
+ break;
+ case 12:
+ PRINT_INFO("%s: User %s is currently not ready.\n",
+ conn->netdev->name,
+ netiucv_printname(conn->userid));
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
+ break;
+ case 13:
+ PRINT_WARN("%s: Too many IUCV connections.\n",
+ conn->netdev->name);
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
+ case 14:
+ PRINT_WARN("%s: User %s has too many IUCV connections.\n",
+ conn->netdev->name,
+ netiucv_printname(conn->userid));
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
+ case 15:
+ PRINT_WARN("%s: No IUCV authorization in CP directory.\n",
+ conn->netdev->name);
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
+ default:
+ PRINT_WARN("%s: iucv_connect returned error %d\n",
+ conn->netdev->name, rc);
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
}
IUCV_DBF_TEXT_(setup, 5, "iucv_connect rc is %d\n", rc);
- IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
- iucv_unregister_program(conn->handle);
- conn->handle = NULL;
+ kfree(conn->path);
+ conn->path = NULL;
}
-static void
-netiucv_purge_skb_queue(struct sk_buff_head *q)
+static void netiucv_purge_skb_queue(struct sk_buff_head *q)
{
struct sk_buff *skb;
@@ -931,36 +939,34 @@ netiucv_purge_skb_queue(struct sk_buff_head *q)
}
}
-static void
-conn_action_stop(fsm_instance *fi, int event, void *arg)
+static void conn_action_stop(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_STOPPED);
netiucv_purge_skb_queue(&conn->collect_queue);
- if (conn->handle)
- IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
- iucv_unregister_program(conn->handle);
- conn->handle = NULL;
+ if (conn->path) {
+ IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n");
+ iucv_path_sever(conn->path, iucvMagic);
+ kfree(conn->path);
+ conn->path = NULL;
+ }
netiucv_purge_skb_queue(&conn->commit_queue);
fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
}
-static void
-conn_action_inval(fsm_instance *fi, int event, void *arg)
+static void conn_action_inval(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
+ struct iucv_connection *conn = arg;
struct net_device *netdev = conn->netdev;
- PRINT_WARN("%s: Cannot connect without username\n",
- netdev->name);
+ PRINT_WARN("%s: Cannot connect without username\n", netdev->name);
IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n");
}
@@ -999,29 +1005,27 @@ static const fsm_node conn_fsm[] = {
static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
-/**
+/*
* Actions for interface - statemachine.
- *****************************************************************************/
+ */
/**
- * Startup connection by sending CONN_EVENT_START to it.
+ * dev_action_start
+ * @fi: An instance of an interface statemachine.
+ * @event: The event, just happened.
+ * @arg: Generic pointer, casted from struct net_device * upon call.
*
- * @param fi An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg Generic pointer, casted from struct net_device * upon call.
+ * Startup connection by sending CONN_EVENT_START to it.
*/
-static void
-dev_action_start(fsm_instance *fi, int event, void *arg)
+static void dev_action_start(fsm_instance *fi, int event, void *arg)
{
- struct net_device *dev = (struct net_device *)arg;
- struct netiucv_priv *privptr = dev->priv;
- struct iucv_event ev;
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STARTWAIT);
- fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
+ fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
}
/**
@@ -1034,8 +1038,8 @@ dev_action_start(fsm_instance *fi, int event, void *arg)
static void
dev_action_stop(fsm_instance *fi, int event, void *arg)
{
- struct net_device *dev = (struct net_device *)arg;
- struct netiucv_priv *privptr = dev->priv;
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
struct iucv_event ev;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -1057,8 +1061,8 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
static void
dev_action_connup(fsm_instance *fi, int event, void *arg)
{
- struct net_device *dev = (struct net_device *)arg;
- struct netiucv_priv *privptr = dev->priv;
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -1131,11 +1135,13 @@ static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
*
* @return 0 on success, -ERRNO on failure. (Never fails.)
*/
-static int
-netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
+static int netiucv_transmit_skb(struct iucv_connection *conn,
+ struct sk_buff *skb)
+{
+ struct iucv_message msg;
unsigned long saveflags;
- ll_header header;
- int rc = 0;
+ struct ll_header header;
+ int rc;
if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) {
int l = skb->len + NETIUCV_HDRLEN;
@@ -1145,11 +1151,12 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
(conn->max_buffsize - NETIUCV_HDRLEN)) {
rc = -EBUSY;
IUCV_DBF_TEXT(data, 2,
- "EBUSY from netiucv_transmit_skb\n");
+ "EBUSY from netiucv_transmit_skb\n");
} else {
atomic_inc(&skb->users);
skb_queue_tail(&conn->collect_queue, skb);
conn->collect_len += l;
+ rc = 0;
}
spin_unlock_irqrestore(&conn->collect_lock, saveflags);
} else {
@@ -1188,9 +1195,10 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
fsm_newstate(conn->fsm, CONN_STATE_TX);
conn->prof.send_stamp = xtime;
- rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
- 0, nskb->data, nskb->len);
- /* Shut up, gcc! nskb is always below 2G. */
+ msg.tag = 1;
+ msg.class = 0;
+ rc = iucv_message_send(conn->path, &msg, 0, 0,
+ nskb->data, nskb->len);
conn->prof.doios_single++;
conn->prof.txlen += skb->len;
conn->prof.tx_pending++;
@@ -1200,7 +1208,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
struct netiucv_priv *privptr;
fsm_newstate(conn->fsm, CONN_STATE_IDLE);
conn->prof.tx_pending--;
- privptr = (struct netiucv_priv *)conn->netdev->priv;