Commit 0286402a authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: iucv driver.

Update iucv driver for new driver model

iucv device configuration is now done through sysfs instead of /proc

Author: Cornelia Huck <cohuck@de.ibm.com>
parent d022be21
/* /*
* $Id: iucv.c,v 1.32 2002/02/12 21:52:20 felfert Exp $ * $Id: iucv.c,v 1.9 2002/11/06 13:37:25 cohuck Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,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 lowlevel driver $Revision: 1.32 $ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.9 $
* *
*/ */
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include "iucv.h" #include "iucv.h"
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
...@@ -275,9 +274,7 @@ static iucv_param * iucv_param_pool; ...@@ -275,9 +274,7 @@ static iucv_param * iucv_param_pool;
MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)"); MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver"); MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12))
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#endif
/* /*
* Debugging stuff * Debugging stuff
...@@ -336,7 +333,7 @@ do { \ ...@@ -336,7 +333,7 @@ do { \
static void static void
iucv_banner(void) iucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.32 $"; char vbuf[] = "$Revision: 1.9 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
......
/* /*
* $Id: netiucv.c,v 1.17 2002/02/12 21:52:20 felfert Exp $ * $Id: netiucv.c,v 1.12 2002/11/26 16:00:54 mschwide Exp $
* *
* IUCV network driver * IUCV network driver
* *
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
* *
* Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com)
*
* Documentation used: * Documentation used:
* the source of the original IUCV driver by: * the source of the original IUCV driver by:
* Stefan Hegewald <hegewald@de.ibm.com> * Stefan Hegewald <hegewald@de.ibm.com>
...@@ -28,7 +30,7 @@ ...@@ -28,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.17 $ * RELEASE-TAG: IUCV network driver $Revision: 1.12 $
* *
*/ */
...@@ -45,7 +47,7 @@ ...@@ -45,7 +47,7 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/proc_fs.h> #include <linux/device.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
...@@ -137,11 +139,7 @@ typedef struct netiucv_priv_t { ...@@ -137,11 +139,7 @@ typedef struct netiucv_priv_t {
unsigned long tbusy; unsigned long tbusy;
fsm_instance *fsm; fsm_instance *fsm;
iucv_connection *conn; iucv_connection *conn;
struct proc_dir_entry *proc_dentry; struct platform_device pldev;
struct proc_dir_entry *proc_stat_entry;
struct proc_dir_entry *proc_buffer_entry;
struct proc_dir_entry *proc_user_entry;
int proc_registered;
} netiucv_priv; } netiucv_priv;
/** /**
...@@ -540,7 +538,7 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb) ...@@ -540,7 +538,7 @@ netiucv_unpack_skb(iucv_connection *conn, struct sk_buff *pskb)
skb->protocol = pskb->protocol; skb->protocol = pskb->protocol;
pskb->ip_summed = CHECKSUM_UNNECESSARY; pskb->ip_summed = CHECKSUM_UNNECESSARY;
netif_rx(skb); netif_rx(skb);
#warning FIXME: [kj] Net drivers should set dev->last_rx immediately after netif_rx dev->last_rx = jiffies;
privptr->stats.rx_packets++; privptr->stats.rx_packets++;
privptr->stats.rx_bytes += skb->len; privptr->stats.rx_bytes += skb->len;
skb_pull(pskb, header->next); skb_pull(pskb, header->next);
...@@ -1255,71 +1253,75 @@ netiucv_change_mtu (net_device * dev, int new_mtu) ...@@ -1255,71 +1253,75 @@ netiucv_change_mtu (net_device * dev, int new_mtu)
return 0; return 0;
} }
/** /**
* procfs related structures and routines * attributes in sysfs
*****************************************************************************/ *****************************************************************************/
#define CTRL_BUFSIZE 40
static net_device * static ssize_t
find_netdev_by_ino(struct proc_dir_entry *pde) user_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
iucv_connection *conn = connections; netiucv_priv *priv = dev->driver_data;
net_device *dev = NULL;
netiucv_priv *privptr;
while (conn) { return off ? 0 : snprintf(buf, count, "%s\n",
if (conn->netdev != dev) { netiucv_printname(priv->conn->userid));
dev = conn->netdev; }
privptr = (netiucv_priv *)dev->priv;
if ((privptr->proc_buffer_entry == pde) || static ssize_t
(privptr->proc_user_entry == pde) || user_write (struct device *dev, const char *buf, size_t count, loff_t off)
(privptr->proc_stat_entry == pde) ) {
return dev; netiucv_priv *priv = dev->driver_data;
} struct net_device *ndev = container_of((void *)priv, struct net_device, priv);
conn = conn->next; 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;
} }
return NULL;
}
#define CTRL_BUFSIZE 40 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 int
netiucv_buffer_open(struct inode *inode, struct file *file)
{
file->private_data = kmalloc(CTRL_BUFSIZE, GFP_KERNEL);
if (file->private_data == NULL)
return -ENOMEM;
MOD_INC_USE_COUNT;
return 0;
} }
static int static DEVICE_ATTR(user, 0644, user_show, user_write);
netiucv_buffer_close(struct inode *inode, struct file *file)
static ssize_t
buffer_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
kfree(file->private_data); netiucv_priv *priv = dev->driver_data;
MOD_DEC_USE_COUNT;
return 0; return off ? 0 : snprintf(buf, count, "%d\n",
priv->conn->max_buffsize);
} }
static ssize_t static ssize_t
netiucv_buffer_write(struct file *file, const char *buf, size_t count, buffer_write (struct device *dev, const char *buf, size_t count, loff_t off)
loff_t *off)
{ {
struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); netiucv_priv *priv = dev->driver_data;
net_device *dev; struct net_device *ndev = container_of((void *)priv, struct net_device, priv);
netiucv_priv *privptr;
char *e; char *e;
int bs1; int bs1;
char tmp[CTRL_BUFSIZE]; char tmp[CTRL_BUFSIZE];
if (!(dev = find_netdev_by_ino(pde)))
return -ENODEV;
if (off != &file->f_pos)
return -ESPIPE;
privptr = (netiucv_priv *)dev->priv;
if (count >= 39) if (count >= 39)
return -EINVAL; return -EINVAL;
...@@ -1331,336 +1333,231 @@ netiucv_buffer_write(struct file *file, const char *buf, size_t count, ...@@ -1331,336 +1333,231 @@ netiucv_buffer_write(struct file *file, const char *buf, size_t count,
if ((bs1 > NETIUCV_BUFSIZE_MAX) || if ((bs1 > NETIUCV_BUFSIZE_MAX) ||
(e && (!isspace(*e)))) (e && (!isspace(*e))))
return -EINVAL; return -EINVAL;
if ((dev->flags & IFF_RUNNING) && if ((ndev->flags & IFF_RUNNING) &&
(bs1 < (dev->mtu + NETIUCV_HDRLEN + 2))) (bs1 < (ndev->mtu + NETIUCV_HDRLEN + 2)))
return -EINVAL; return -EINVAL;
if (bs1 < (576 + NETIUCV_HDRLEN + NETIUCV_HDRLEN)) if (bs1 < (576 + NETIUCV_HDRLEN + NETIUCV_HDRLEN))
return -EINVAL; return -EINVAL;
privptr->conn->max_buffsize = bs1; priv->conn->max_buffsize = bs1;
if (!(dev->flags & IFF_RUNNING)) if (!(ndev->flags & IFF_RUNNING))
dev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN; ndev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN;
privptr->conn->flags |= CONN_FLAGS_BUFSIZE_CHANGED; priv->conn->flags |= CONN_FLAGS_BUFSIZE_CHANGED;
return count; return count;
} }
static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
static ssize_t static ssize_t
netiucv_buffer_read(struct file *file, char *buf, size_t count, loff_t *off) dev_fsm_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); netiucv_priv *priv = dev->driver_data;
char *sbuf = (char *)file->private_data;
net_device *dev; return off ? 0 : snprintf(buf, count, "%s\n",
netiucv_priv *privptr; fsm_getstate_str(priv->fsm));
ssize_t ret = 0;
char *p = sbuf;
int l;
if (!(dev = find_netdev_by_ino(pde)))
return -ENODEV;
if (off != &file->f_pos)
return -ESPIPE;
privptr = (netiucv_priv *)dev->priv;
if (file->f_pos == 0)
sprintf(sbuf, "%d\n", privptr->conn->max_buffsize);
l = strlen(sbuf);
p = sbuf;
if (file->f_pos < l) {
p += file->f_pos;
l = strlen(p);
ret = (count > l) ? l : count;
if (copy_to_user(buf, p, ret))
return -EFAULT;
}
file->f_pos += ret;
return ret;
} }
static int static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
netiucv_user_open(struct inode *inode, struct file *file)
static ssize_t
conn_fsm_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
file->private_data = kmalloc(CTRL_BUFSIZE, GFP_KERNEL); netiucv_priv *priv = dev->driver_data;
if (file->private_data == NULL)
return -ENOMEM; return off ? 0 : snprintf(buf, count, "%s\n",
MOD_INC_USE_COUNT; fsm_getstate_str(priv->conn->fsm));
return 0;
} }
static int static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
netiucv_user_close(struct inode *inode, struct file *file)
static ssize_t
maxmulti_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
kfree(file->private_data); netiucv_priv *priv = dev->driver_data;
MOD_DEC_USE_COUNT;
return 0; return off ? 0 : snprintf(buf, count, "%ld\n",
priv->conn->prof.maxmulti);
} }
static ssize_t static ssize_t
netiucv_user_write(struct file *file, const char *buf, size_t count, maxmulti_write (struct device *dev, const char *buf, size_t count, loff_t off)
loff_t *off)
{ {
struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); netiucv_priv *priv = dev->driver_data;
net_device *dev;
netiucv_priv *privptr; priv->conn->prof.maxmulti = 0;
int i;
char *p;
char tmp[CTRL_BUFSIZE];
char user[9];
if (!(dev = find_netdev_by_ino(pde)))
return -ENODEV;
if (off != &file->f_pos)
return -ESPIPE;
privptr = (netiucv_priv *)dev->priv;
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, privptr->conn->userid, 8) != 0) {
/* username changed */
if (dev->flags & IFF_RUNNING)
return -EBUSY;
}
memcpy(privptr->conn->userid, user, 9);
return count; return count;
} }
static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
static ssize_t static ssize_t
netiucv_user_read(struct file *file, char *buf, size_t count, loff_t *off) maxcq_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); netiucv_priv *priv = dev->driver_data;
char *sbuf = (char *)file->private_data;
net_device *dev; return off ? 0 : snprintf(buf, count, "%ld\n",
netiucv_priv *privptr; priv->conn->prof.maxcqueue);
ssize_t ret = 0; }
char *p = sbuf;
int l;
if (!(dev = find_netdev_by_ino(pde)))
return -ENODEV;
if (off != &file->f_pos)
return -ESPIPE;
privptr = (netiucv_priv *)dev->priv; static ssize_t
maxcq_write (struct device *dev, const char *buf, size_t count, loff_t off)
{
netiucv_priv *priv = dev->driver_data;
priv->conn->prof.maxcqueue = 0;
return count;
}
static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
if (file->f_pos == 0) static ssize_t
sprintf(sbuf, "%s\n", sdoio_show (struct device *dev, char *buf, size_t count, loff_t off)
netiucv_printname(privptr->conn->userid)); {
netiucv_priv *priv = dev->driver_data;
return off ? 0 : snprintf(buf, count, "%ld\n",
priv->conn->prof.doios_single);
}
l = strlen(sbuf); static ssize_t
p = sbuf; sdoio_write (struct device *dev, const char *buf, size_t count, loff_t off)
if (file->f_pos < l) { {
p += file->f_pos; netiucv_priv *priv = dev->driver_data;
l = strlen(p);
ret = (count > l) ? l : count; priv->conn->prof.doios_single = 0;
if (copy_to_user(buf, p, ret)) return count;
return -EFAULT;
}
file->f_pos += ret;
return ret;
} }
#define STATS_BUFSIZE 2048 static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
static int static ssize_t
netiucv_stat_open(struct inode *inode, struct file *file) mdoio_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
file->private_data = kmalloc(STATS_BUFSIZE, GFP_KERNEL); netiucv_priv *priv = dev->driver_data;
if (file->private_data == NULL)
return -ENOMEM; return off ? 0 : snprintf(buf, count, "%ld\n",
MOD_INC_USE_COUNT; priv->conn->prof.doios_multi);
return 0;
} }
static int static ssize_t
netiucv_stat_close(struct inode *inode, struct file *file) mdoio_write (struct device *dev, const char *buf, size_t count, loff_t off)
{ {
kfree(file->private_data); netiucv_priv *priv = dev->driver_data;
MOD_DEC_USE_COUNT;
return 0; priv->conn->prof.doios_multi = 0;
return count;
} }
static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
static ssize_t static ssize_t
netiucv_stat_write(struct file *file, const char *buf, size_t count, loff_t *off) txlen_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); netiucv_priv *priv = dev->driver_data;
net_device *dev;
netiucv_priv *privptr; return off ? 0 : snprintf(buf, count, "%ld\n",
priv->conn->prof.txlen);
}
if (!(dev = find_netdev_by_ino(pde))) static ssize_t
return -ENODEV; txlen_write (struct device *dev, const char *buf, size_t count, loff_t off)
privptr = (netiucv_priv *)dev->priv; {
privptr->conn->prof.maxmulti = 0; netiucv_priv *priv = dev->driver_data;
privptr->conn->prof.maxcqueue = 0;
privptr->conn->prof.doios_single = 0; priv->conn->prof.txlen = 0;
privptr->conn->prof.doios_multi = 0;
privptr->conn->prof.txlen = 0;
privptr->conn->prof.tx_time = 0;
return count; return count;
} }
static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
static ssize_t static ssize_t
netiucv_stat_read(struct file *file, char *buf, size_t count, loff_t *off) txtime_show (struct device *dev, char *buf, size_t count, loff_t off)
{ {
struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); netiucv_priv *priv = dev->driver_data;
char *sbuf = (char *)file->private_data;
net_device *dev; return off ? 0 : snprintf(buf, count, "%ld\n",
netiucv_priv *privptr; priv->conn->prof.tx_time);
ssize_t ret = 0; }
char *p = sbuf;
int l;
if (!(dev = find_netdev_by_ino(pde))) static ssize_t
return -ENODEV; txtime_write (struct device *dev, const char *buf, size_t count, loff_t off)
if (off != &file->f_pos) {
return -ESPIPE; netiucv_priv *priv = dev->driver_data;
priv->conn->prof.tx_time = 0;
return count;
}
privptr = (netiucv_priv *)dev->priv; static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
if (file->f_pos == 0) { static inline int
p += sprintf(p, "Device FSM state: %s\n", netiucv_add_files(struct device *dev)
fsm_getstate_str(privptr->fsm)); {
p += sprintf(p, "Connection FSM state: %s\n", int ret = 0;
fsm_getstate_str(privptr->conn->fsm));
p += sprintf(p, "Max. TX buffer used: %ld\n", if ((ret = device_create_file(dev, &dev_attr_user)) ||
privptr->conn->prof.maxmulti); (ret = device_create_file(dev, &dev_attr_buffer)) ||
p += sprintf(p, "Max. chained SKBs: %ld\n", (ret = device_create_file(dev, &dev_attr_device_fsm_state)) ||
privptr->conn->prof.maxcqueue); (ret = device_create_file(dev, &dev_attr_connection_fsm_state)) ||
p += sprintf(p, "TX single write ops: %ld\n", (ret = device_create_file(dev, &dev_attr_max_tx_buffer_used)) ||
privptr->conn->prof.doios_single); (ret = device_create_file(dev, &dev_attr_max_chained_skbs)) ||
p += sprintf(p, "TX multi write ops: %ld\n", (ret = device_create_file(dev, &dev_attr_tx_single_write_ops)) ||
privptr->conn->prof.doios_multi); (ret = device_create_file(dev, &dev_attr_tx_multi_write_ops)) ||
p += sprintf(p, "Netto bytes written: %ld\n", (ret = device_create_file(dev, &dev_attr_netto_bytes)) ||
privptr->conn->prof.txlen); (ret = device_create_file(dev, &dev_attr_max_tx_io_time))) {
p += sprintf(p, "Max. TX IO-time: %ld\n", device_remove_file(dev, &dev_attr_netto_bytes);
privptr->conn->prof.tx_time); device_remove_file(dev, &dev_attr_tx_multi_write_ops);
} device_remove_file(dev, &dev_attr_tx_single_write_ops);
l = strlen(sbuf); device_remove_file(dev, &dev_attr_max_chained_skbs);
p = sbuf; device_remove_file(dev, &dev_attr_max_tx_buffer_used);
if (file->f_pos < l) { device_remove_file(dev, &dev_attr_connection_fsm_state);
p += file->f_pos; device_remove_file(dev, &dev_attr_device_fsm_state);
l = strlen(p); device_remove_file(dev, &dev_attr_buffer);
ret = (count > l) ? l : count; device_remove_file(dev, &dev_attr_user);
if (copy_to_user(buf, p, ret))
return -EFAULT;
} }
file->f_pos += ret;
return ret; return ret;
} }
static struct file_operations netiucv_stat_fops = { static int
.read = netiucv_stat_read, netiucv_register_device(struct net_device *ndev, int ifno)
.write = netiucv_stat_write, {
.open = netiucv_stat_open, netiucv_priv *priv = ndev->priv;
.release = netiucv_stat_close, struct platform_device *pldev = &priv->pldev;
}; int ret;
char *str = "netiucv";
static struct file_operations netiucv_buffer_fops = { snprintf(pldev->dev.name, DEVICE_NAME_SIZE,
.read = netiucv_buffer_read, "%s%x", str, ifno);
.write = netiucv_buffer_write, pldev->name = str;
.open = netiucv_buffer_open, pldev->id = ifno;
.release = netiucv_buffer_close,
};
static struct file_operations netiucv_user_fops = { ret = platform_device_register(pldev);
.read = netiucv_user_read,
.write = netiucv_user_write,
.open = netiucv_user_open,
.release = netiucv_user_close,
};
static struct proc_dir_entry *netiucv_dir = NULL; if (ret)
static struct proc_dir_entry *netiucv_template = NULL; return ret;
/** ret = netiucv_add_files(&pldev->dev);
* Create the driver's main directory /proc/net/iucv
*/ if (ret)
static void platform_device_unregister(pldev);
netiucv_proc_create_main(void) else
{ pldev->dev.driver_data = priv;
/** return ret;
* If not registered, register main proc dir-entry now
*/
if (!netiucv_dir)
netiucv_dir = proc_mkdir("iucv", proc_net);
} }
#ifdef MODULE #ifdef MODULE
/**
* Destroy /proc/net/iucv
*/
static void static void
netiucv_proc_destroy_main(void) netiucv_unregister_device(struct net_device *ndev)
{ {
remove_proc_entry("iucv", proc_net); netiucv_priv *priv = (netiucv_priv*)ndev->priv;
} struct platform_device *pldev = &priv->pldev;
#endif MODULE
platform_device_unregister(pldev);
/**
* Create a device specific subdirectory in /proc/net/iucv/ with the
* same name like the device. In that directory, create 3 entries
* "statistics", "buffersize" and "username".
*
* @param dev The device for which the subdirectory should be created.
*
*/
static void
netiucv_proc_create_sub(net_device *dev) {
netiucv_priv *privptr = dev->priv;
privptr->proc_dentry = proc_mkdir(dev->name, netiucv_dir);
privptr->proc_stat_entry =
create_proc_entry("statistics",
S_IFREG | S_IRUSR | S_IWUSR,
privptr->proc_dentry);
privptr->proc_stat_entry->proc_fops = &netiucv_stat_fops;
privptr->proc_buffer_entry =
create_proc_entry("buffersize",
S_IFREG | S_IRUSR | S_IWUSR,
privptr->proc_dentry);
privptr->proc_buffer_entry->proc_fops = &netiucv_buffer_fops;
privptr->proc_user_entry =
create_proc_entry("username",
S_IFREG | S_IRUSR | S_IWUSR,
privptr->proc_dentry);
privptr->proc_user_entry->proc_fops = &netiucv_user_fops;
privptr->proc_registered = 1;
} }
#endif
/**
* Destroy a device specific subdirectory.
*
* @param privptr Pointer to device private data.
*/
static void
netiucv_proc_destroy_sub(netiucv_priv *privptr) {
if (!privptr->proc_registered)
return;
remove_proc_entry("statistics", privptr->proc_dentry);
remove_proc_entry("buffersize", privptr->proc_dentry);
remove_proc_entry("username", privptr->proc_dentry);
remove_proc_entry(privptr->proc_dentry->name, netiucv_dir);
privptr->proc_registered = 0;
}
/** /**
* Allocate and initialize a new connection structure. * Allocate and initialize a new connection structure.
...@@ -1813,7 +1710,6 @@ netiucv_free_netdevice(net_device *dev) ...@@ -1813,7 +1710,6 @@ netiucv_free_netdevice(net_device *dev)
netiucv_remove_connection(privptr->conn); netiucv_remove_connection(privptr->conn);
if (privptr->fsm) if (privptr->fsm)
kfree_fsm(privptr->fsm); kfree_fsm(privptr->fsm);
netiucv_proc_destroy_sub(privptr);
kfree(privptr); kfree(privptr);
} }
kfree(dev); kfree(dev);
...@@ -1822,7 +1718,7 @@ netiucv_free_netdevice(net_device *dev) ...@@ -1822,7 +1718,7 @@ netiucv_free_netdevice(net_device *dev)
static void static void
netiucv_banner(void) netiucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.17 $"; char vbuf[] = "$Revision: 1.12 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
...@@ -1858,9 +1754,9 @@ netiucv_exit(void) ...@@ -1858,9 +1754,9 @@ netiucv_exit(void)
while (connections) { while (connections) {
net_device *dev = connections->netdev; net_device *dev = connections->netdev;
unregister_netdev(dev); unregister_netdev(dev);
netiucv_unregister_device(dev);
netiucv_free_netdevice(dev); netiucv_free_netdevice(dev);
} }
netiucv_proc_destroy_main();
printk(KERN_INFO "NETIUCV driver unloaded\n"); printk(KERN_INFO "NETIUCV driver unloaded\n");
return; return;
...@@ -1877,7 +1773,6 @@ netiucv_init(void) ...@@ -1877,7 +1773,6 @@ netiucv_init(void)
int i = 0; int i = 0;
char username[10]; char username[10];
netiucv_proc_create_main();
while (p) { while (p) {
if (isalnum(*p)) { if (isalnum(*p)) {
username[i++] = *p++; username[i++] = *p++;
...@@ -1915,7 +1810,7 @@ netiucv_init(void) ...@@ -1915,7 +1810,7 @@ netiucv_init(void)
netiucv_free_netdevice(dev); netiucv_free_netdevice(dev);
} else { } else {
printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username)); printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username));
netiucv_proc_create_sub(dev); netiucv_register_device(dev, ifno);
ifno++; ifno++;
} }
} }
......
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