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
*
......@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software
* 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 @@
#undef DEBUG
#ifdef MODULE
MODULE_AUTHOR
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
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
*/
typedef struct connection_profile_t {
struct connection_profile {
unsigned long maxmulti;
unsigned long maxcqueue;
unsigned long doios_single;
......@@ -91,13 +81,13 @@ typedef struct connection_profile_t {
unsigned long txlen;
unsigned long tx_time;
struct timespec send_stamp;
} connection_profile;
};
/**
* Representation of one iucv connection
*/
typedef struct iucv_connection_t {
struct iucv_connection_t *next;
struct iucv_connection {
struct iucv_connection *next;
iucv_handle_t handle;
__u16 pathid;
struct sk_buff *rx_buff;
......@@ -110,37 +100,57 @@ typedef struct iucv_connection_t {
fsm_timer timer;
int retry;
fsm_instance *fsm;
net_device *netdev;
connection_profile prof;
struct net_device *netdev;
struct connection_profile prof;
char userid[9];
} iucv_connection;
};
#define CONN_FLAGS_BUFSIZE_CHANGED 1
/**
* 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
* connection state machine.
*/
typedef struct iucv_event_t {
iucv_connection *conn;
struct iucv_event {
struct iucv_connection *conn;
void *data;
} iucv_event;
};
/**
* Private part of the network device structure
*/
typedef struct netiucv_priv_t {
struct netiucv_priv {
struct net_device_stats stats;
unsigned long tbusy;
fsm_instance *fsm;
iucv_connection *conn;
struct platform_device pldev;
} netiucv_priv;
struct iucv_connection *conn;
struct device dev;
};
/**
* Link level header for a packet.
......@@ -161,16 +171,16 @@ typedef struct ll_header_t {
* Compatibility macros for busy handling
* 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);
}
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);
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)
......@@ -387,8 +397,8 @@ static const char *conn_state_names[] = {
static void
netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -399,8 +409,8 @@ netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
static void
netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -410,8 +420,8 @@ netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
static void
netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -421,8 +431,8 @@ netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
static void
netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -432,8 +442,8 @@ netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
static void
netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -443,8 +453,8 @@ netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
static void
netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -454,8 +464,8 @@ netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
static void
netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
{
iucv_connection *conn = (iucv_connection *)pgm_data;
iucv_event ev;
struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
struct iucv_event ev;
ev.conn = conn;
ev.data = (void *)eib;
......@@ -494,10 +504,10 @@ fsm_action_nop(fsm_instance *fi, int event, void *arg)
*/
//static __inline__ 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;
netiucv_priv *privptr = (netiucv_priv *)dev->priv;
struct net_device *dev = conn->netdev;
struct netiucv_priv *privptr = (struct netiucv_priv *)dev->priv;
__u16 offset = 0;
skb_put(pskb, NETIUCV_HDRLEN);
......@@ -518,7 +528,8 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb)
header->next -= NETIUCV_HDRLEN;
if (skb_tailroom(pskb) < header->next) {
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));
return;
}
......@@ -549,17 +560,16 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb)
static void
conn_action_rx(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
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;
int rc;
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
pr_debug("%s() called\n", __FUNCTION__);
if (!conn->netdev) {
/* FRITZ: How to tell iucv LL to drop the msg? */
printk(KERN_WARNING
......@@ -585,10 +595,10 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
static void
conn_action_txdone(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
netiucv_priv *privptr = NULL;
struct netiucv_priv *privptr = NULL;
/* Shut up, gcc! skb is always below 2G. */
struct sk_buff *skb = (struct sk_buff *)(unsigned long)eib->ipmsgtag;
__u32 txbytes = 0;
......@@ -597,12 +607,11 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
unsigned long saveflags;
ll_header header;
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
pr_debug("%s() called\n", __FUNCTION__);
fsm_deltimer(&conn->timer);
if (conn && conn->netdev && conn->netdev->priv)
privptr = (netiucv_priv *)conn->netdev->priv;
privptr = (struct netiucv_priv *)conn->netdev->priv;
if (skb) {
if (privptr) {
privptr->stats.tx_packets++;
......@@ -663,18 +672,17 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
static void
conn_action_connaccept(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv;
struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
int rc;
__u16 msglimit;
__u8 udata[16];
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
pr_debug("%s() called\n", __FUNCTION__);
rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,
conn->handle, conn, NULL, &msglimit);
if (rc != 0) {
......@@ -692,29 +700,27 @@ conn_action_connaccept(fsm_instance *fi, int event, void *arg)
static void
conn_action_connreject(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
// iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
// struct iucv_connection *conn = ev->conn;
iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
__u8 udata[16];
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
pr_debug("%s() called\n", __FUNCTION__);
iucv_sever(eib->ippathid, udata);
}
static void
conn_action_connack(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv;
struct net_device *netdev = conn->netdev;
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);
conn->pathid = eib->ippathid;
netdev->tx_queue_len = eib->ipmsglim;
......@@ -724,16 +730,15 @@ conn_action_connack(fsm_instance *fi, int event, void *arg)
static void
conn_action_connsever(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
// iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data;
net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv;
struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
int state = fsm_getstate(fi);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
pr_debug("%s() called\n", __FUNCTION__);
switch (state) {
case CONN_STATE_IDLE:
case CONN_STATE_TX:
......@@ -751,14 +756,13 @@ conn_action_connsever(fsm_instance *fi, int event, void *arg)
static void
conn_action_start(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
int rc;
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
pr_debug("%s() called\n", __FUNCTION__);
if (conn->handle == 0) {
conn->handle =
iucv_register_program(iucvMagic, conn->userid, mask,
......@@ -769,15 +773,14 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
conn->handle = 0;
return;
}
#ifdef DEBUG
printk(KERN_DEBUG "%s('%s'): registered successfully\n",
pr_debug("%s('%s'): registered successfully\n",
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);
#endif
rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
conn->userid, iucv_host, 0, NULL, NULL, conn->handle,
conn);
......@@ -843,14 +846,13 @@ netiucv_purge_skb_queue(struct sk_buff_head *q)
static void
conn_action_stop(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
net_device *netdev = conn->netdev;
netiucv_priv *privptr = (netiucv_priv *)netdev->priv;
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
struct net_device *netdev = conn->netdev;
struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
pr_debug("%s() called\n", __FUNCTION__);
fsm_newstate(fi, CONN_STATE_STOPPED);
netiucv_purge_skb_queue(&conn->collect_queue);
if (conn->handle)
......@@ -862,9 +864,9 @@ conn_action_stop(fsm_instance *fi, int event, void *arg)
static void
conn_action_inval(fsm_instance *fi, int event, void *arg)
{
iucv_event *ev = (iucv_event *)arg;
iucv_connection *conn = ev->conn;
net_device *netdev = conn->netdev;
struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn;
struct net_device *netdev = conn->netdev;
printk(KERN_WARNING
"%s: Cannot connect without username\n",
......@@ -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 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
dev_action_start(fsm_instance *fi, int event, void *arg)
{
net_device *dev = (net_device *)arg;
netiucv_priv *privptr = dev->priv;
iucv_event ev;
struct net_device *dev = (struct net_device *)arg;
struct netiucv_priv *privptr = dev->priv;
struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STARTWAIT);
fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
......@@ -935,18 +936,17 @@ dev_action_start(fsm_instance *fi, int event, void *arg)
*
* @param fi An instance of an interface statemachine.
* @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
dev_action_stop(fsm_instance *fi, int event, void *arg)
{
net_device *dev = (net_device *)arg;
netiucv_priv *privptr = dev->priv;
iucv_event ev;
struct net_device *dev = (struct net_device *)arg;
struct netiucv_priv *privptr = dev->priv;
struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STOPWAIT);
......@@ -959,16 +959,15 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
*
* @param fi An instance of an interface statemachine.
* @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
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)) {
case DEV_STATE_STARTWAIT:
fsm_newstate(fi, DEV_STATE_RUNNING);
......@@ -990,18 +989,17 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
*
* @param fi An instance of an interface statemachine.
* @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
dev_action_conndown(fsm_instance *fi, int event, void *arg)
{
net_device *dev = (net_device *)arg;
netiucv_priv *privptr = dev->priv;
iucv_event ev;
struct net_device *dev = (struct net_device *)arg;
struct netiucv_priv *privptr = dev->priv;
struct iucv_event ev;
pr_debug("%s() called\n", __FUNCTION__);
#ifdef DEBUG
printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
#endif
switch (fsm_getstate(fi)) {
case DEV_STATE_RUNNING:
fsm_newstate(fi, DEV_STATE_STARTWAIT);
......@@ -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.)
*/
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;
ll_header header;
int rc = 0;
......@@ -1141,10 +1139,10 @@ netiucv_transmit_skb(iucv_connection *conn, struct sk_buff *skb) {
* @return 0 on success, -ERRNO on failure. (Never fails.)
*/
static int
netiucv_open(net_device *dev) {
netiucv_open(struct net_device *dev) {
MOD_INC_USE_COUNT;
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;
}
......@@ -1157,9 +1155,9 @@ netiucv_open(net_device *dev) {
* @return 0 on success, -ERRNO on failure. (Never fails.)
*/
static int
netiucv_close(net_device *dev) {
netiucv_close(struct net_device *dev) {
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;
return 0;
}
......@@ -1175,10 +1173,10 @@ netiucv_close(net_device *dev) {
* Note: If we return !0, then the packet is free'd by
* 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;
netiucv_priv *privptr = (netiucv_priv *)dev->priv;
struct netiucv_priv *privptr = (struct netiucv_priv *)dev->priv;
/**
* Some sanity checks ...
......@@ -1230,9 +1228,9 @@ static int netiucv_tx(struct sk_buff *skb, net_device *dev)
* @return Pointer to stats struct of this interface.
*/
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)
* (valid range is 576 .. NETIUCV_MTU_MAX).
*/
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))
return -EINVAL;
......@@ -1258,66 +1256,20 @@ netiucv_change_mtu (net_device * dev, int new_mtu)
*****************************************************************************/
#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
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",
priv->conn->max_buffsize);
return sprintf(buf, "%d\n", priv->conn->max_buffsize);
}
static ssize_t
buffer_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);
struct netiucv_priv *priv = dev->driver_data;
struct net_device *ndev =
container_of((void *)priv, struct net_device, priv);
char *e;
int bs1;
char tmp[CTRL_BUFSIZE];
......@@ -1354,10 +1306,9 @@ static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
static ssize_t
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",
fsm_getstate_str(priv->fsm));
return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
}
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
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",
fsm_getstate_str(priv->conn->fsm));
return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
}
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
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);
}
......@@ -1384,7 +1334,7 @@ maxmulti_show (struct device *dev, char *buf)
static ssize_t
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;
return count;
......@@ -1395,7 +1345,7 @@ static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
static ssize_t
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);
}
......@@ -1403,7 +1353,7 @@ maxcq_show (struct device *dev, char *buf)
static ssize_t
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;
return count;
......@@ -1414,7 +1364,7 @@ static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
static ssize_t
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);
}
......@@ -1422,7 +1372,7 @@ sdoio_show (struct device *dev, char *buf)
static ssize_t
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;
return count;
......@@ -1433,7 +1383,7 @@ static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
static ssize_t
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);
}
......@@ -1441,7 +1391,7 @@ mdoio_show (struct device *dev, char *buf)
static ssize_t
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;
return count;
......@@ -1452,7 +1402,7 @@ static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
static ssize_t
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);
}
......@@ -1460,7 +1410,7 @@ txlen_show (struct device *dev, char *buf)
static ssize_t
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;
return count;
......@@ -1471,7 +1421,7 @@ static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
static ssize_t
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);
}
......@@ -1479,7 +1429,7 @@ txtime_show (struct device *dev, char *buf)
static ssize_t
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;
return count;
......@@ -1492,8 +1442,7 @@ netiucv_add_files(struct device *dev)
{
int ret = 0;
if ((ret = device_create_file(dev, &dev_attr_user)) ||
(ret = device_create_file(dev, &dev_attr_buffer)) ||
if ((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_connection_fsm_state)) ||
(ret = device_create_file(dev, &dev_attr_max_tx_buffer_used)) ||
......@@ -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_device_fsm_state);
device_remove_file(dev, &dev_attr_buffer);
device_remove_file(dev, &dev_attr_user);
}
return ret;
}
......@@ -1518,53 +1466,53 @@ netiucv_add_files(struct device *dev)
static int
netiucv_register_device(struct net_device *ndev, int ifno)
{
netiucv_priv *priv = ndev->priv;
struct platform_device *pldev = &priv->pldev;
struct netiucv_priv *priv = ndev->priv;
struct device *dev = &priv->dev;
int ret;
char *str = "netiucv";
snprintf(pldev->dev.name, DEVICE_NAME_SIZE,
"%s%x", str, ifno);
pldev->name = str;
pldev->id = ifno;
snprintf(dev->name, DEVICE_NAME_SIZE, "%s", priv->conn->userid);
snprintf(dev->bus_id, BUS_ID_SIZE, "%s%x", str, ifno);
dev->bus = &iucv_bus;
dev->parent = &iucv_root;
ret = platform_device_register(pldev);
ret = device_register(dev);
if (ret)
return ret;
ret = netiucv_add_files(&pldev->dev);
ret = netiucv_add_files(dev);
if (ret)
platform_device_unregister(pldev);
device_unregister(dev);
else
pldev->dev.driver_data = priv;
dev->driver_data = priv;
return ret;
}
#ifdef MODULE
static void
netiucv_unregister_device(struct net_device *ndev)
{
netiucv_priv *priv = (netiucv_priv*)ndev->priv;
struct platform_device *pldev = &priv->pldev;
struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
struct device *dev = &priv->dev;
platform_device_unregister(pldev);
device_unregister(dev);
}
#endif
/**
* Allocate and initialize a new connection structure.
* Add it to the list of connections;
*/
static iucv_connection *
netiucv_new_connection(net_device *dev, char *username)
static struct iucv_connection *
netiucv_new_connection(struct net_device *dev, char *username)
{
iucv_connection **clist = &connections;
iucv_connection *conn =
(iucv_connection *)kmalloc(sizeof(iucv_connection), GFP_KERNEL);
struct iucv_connection **clist = &connections;
struct iucv_connection *conn =
(struct iucv_connection *)
kmalloc(sizeof(struct iucv_connection), GFP_KERNEL);
if (conn) {
memset(conn, 0, sizeof(iucv_connection));
memset(conn, 0, sizeof(struct iucv_connection));
skb_queue_head_init(&conn->collect_queue);
conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
conn->netdev = dev;
......@@ -1609,9 +1557,9 @@ netiucv_new_connection(net_device *dev, char *username)
* list of connections.
*/
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)
return;
......@@ -1635,26 +1583,26 @@ netiucv_remove_connection(iucv_connection *conn)
/**
* Allocate and initialize everything of a net device.
*/
static net_device *
static struct net_device *
netiucv_init_netdevice(int ifno, char *username)
{
netiucv_priv *privptr;
struct netiucv_priv *privptr;
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)
return NULL;
memset(dev, 0, sizeof(net_device));
memset(dev, 0, sizeof(struct net_device));
sprintf(dev->name, "iucv%d", ifno);
priv_size = sizeof(netiucv_priv);
priv_size = sizeof(struct netiucv_priv);
dev->priv = kmalloc(priv_size, GFP_KERNEL);
if (dev->priv == NULL) {
kfree(dev);
return NULL;
}
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,
dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
......@@ -1691,14 +1639,14 @@ netiucv_init_netdevice(int ifno, char *username)
* Allocate and initialize everything of a net device.
*/
static void
netiucv_free_netdevice(net_device *dev)
netiucv_free_netdevice(struct net_device *dev)
{
netiucv_priv *privptr;
struct netiucv_priv *privptr;
if (!dev)
return;
privptr = (netiucv_priv *)dev->priv;
privptr = (struct netiucv_priv *)dev->priv;
if (privptr) {
if (privptr->conn)
netiucv_remove_connection(privptr->conn);
......@@ -1709,10 +1657,67 @@ netiucv_free_netdevice(net_device *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
netiucv_banner(void)
{
char vbuf[] = "$Revision: 1.12 $";
char vbuf[] = "$Revision: 1.16 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
......@@ -1724,101 +1729,65 @@ netiucv_banner(void)
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
netiucv_exit(void)
{
while (connections) {
net_device *dev = connections->netdev;
struct net_device *dev = connections->netdev;
unregister_netdev(dev);
netiucv_unregister_device(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");
return;
}
module_exit(netiucv_exit);
#endif
static int __init
netiucv_init(void)
{
char *p = iucv;
int ifno = 0;
int i = 0;
char username[10];
int ret;
while (p) {
if (isalnum(*p)) {
username[i++] = *p++;
username[i] = '\0';
if (i > 8) {
printk(KERN_WARNING
"netiucv: Invalid user name '%s'\n",
username);
while (*p && (*p != ':') && (*p != ','))
p++;
/* Move the bus stuff to iucv.c? - CH */
ret = bus_register(&iucv_bus);
if (ret != 0) {
printk(KERN_ERR "NETIUCV: failed to register bus.\n");
return ret;
}
} 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++;
}
ret = driver_register(&netiucv_driver);
if (ret != 0) {
printk(KERN_ERR "NETIUCV: failed to register driver.\n");
bus_unregister(&iucv_bus);
return ret;
}
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();
return 0;
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_exit(netiucv_exit);
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