Commit 63c85307 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: iucv driver.

 - Move iucv bus and root device initialization from netiucv to iucv.
 - Fix race condition in iucv_connect.
 - Add 'user' attribute to netiucv driver.
parent 36e9a080
/* /*
* $Id: iucv.c,v 1.11 2003/04/15 16:45:37 aberg Exp $ * $Id: iucv.c,v 1.14 2003/09/23 16:48:17 mschwide Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -29,11 +29,12 @@ ...@@ -29,11 +29,12 @@
* 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.11 $ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.14 $
* *
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -43,6 +44,7 @@ ...@@ -43,6 +44,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/device.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include "iucv.h" #include "iucv.h"
#include <asm/io.h> #include <asm/io.h>
...@@ -71,6 +73,21 @@ ...@@ -71,6 +73,21 @@
#define IPANSLST 0x08 #define IPANSLST 0x08
#define IPBUFLST 0x40 #define IPBUFLST 0x40
static int
iucv_bus_match (struct device *dev, struct device_driver *drv)
{
return 0;
}
struct bus_type iucv_bus = {
.name = "iucv",
.match = iucv_bus_match,
};
struct device iucv_root = {
.bus_id = "iucv",
};
/* General IUCV interrupt structure */ /* General IUCV interrupt structure */
typedef struct { typedef struct {
__u16 ippathid; __u16 ippathid;
...@@ -283,7 +300,7 @@ MODULE_LICENSE("GPL"); ...@@ -283,7 +300,7 @@ MODULE_LICENSE("GPL");
#ifdef DEBUG #ifdef DEBUG
static int debuglevel = 0; static int debuglevel = 0;
MODULE_PARM(debuglevel, "i"); module_param(debuglevel, int, 0);
MODULE_PARM_DESC(debuglevel, MODULE_PARM_DESC(debuglevel,
"Specifies the debug level (0=off ... 3=all)"); "Specifies the debug level (0=off ... 3=all)");
...@@ -332,7 +349,7 @@ do { \ ...@@ -332,7 +349,7 @@ do { \
static void static void
iucv_banner(void) iucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.11 $"; char vbuf[] = "$Revision: 1.14 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
...@@ -353,9 +370,24 @@ iucv_banner(void) ...@@ -353,9 +370,24 @@ iucv_banner(void)
static int static int
iucv_init(void) iucv_init(void)
{ {
int ret;
if (iucv_external_int_buffer) if (iucv_external_int_buffer)
return 0; return 0;
ret = bus_register(&iucv_bus);
if (ret != 0) {
printk(KERN_ERR "IUCV: failed to register bus.\n");
return ret;
}
ret = device_register(&iucv_root);
if (ret != 0) {
printk(KERN_ERR "IUCV: failed to register iucv root.\n");
bus_unregister(&iucv_bus);
return ret;
}
/* Note: GFP_DMA used used to get memory below 2G */ /* Note: GFP_DMA used used to get memory below 2G */
iucv_external_int_buffer = kmalloc(sizeof(iucv_GeneralInterrupt), iucv_external_int_buffer = kmalloc(sizeof(iucv_GeneralInterrupt),
GFP_KERNEL|GFP_DMA); GFP_KERNEL|GFP_DMA);
...@@ -401,6 +433,8 @@ iucv_exit(void) ...@@ -401,6 +433,8 @@ iucv_exit(void)
kfree(iucv_external_int_buffer); kfree(iucv_external_int_buffer);
if (iucv_param_pool) if (iucv_param_pool)
kfree(iucv_param_pool); kfree(iucv_param_pool);
device_unregister(&iucv_root);
bus_unregister(&iucv_bus);
printk(KERN_INFO "IUCV lowlevel driver unloaded\n"); printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
} }
...@@ -528,9 +562,8 @@ b2f0(__u32 code, void *parm) ...@@ -528,9 +562,8 @@ b2f0(__u32 code, void *parm)
* - ENOMEM - storage allocation for a new pathid table failed * - ENOMEM - storage allocation for a new pathid table failed
*/ */
static int static int
iucv_add_pathid(__u16 pathid, handler *handler) __iucv_add_pathid(__u16 pathid, handler *handler)
{ {
ulong flags;
iucv_debug(1, "entering"); iucv_debug(1, "entering");
...@@ -539,21 +572,30 @@ iucv_add_pathid(__u16 pathid, handler *handler) ...@@ -539,21 +572,30 @@ iucv_add_pathid(__u16 pathid, handler *handler)
if (pathid > (max_connections - 1)) if (pathid > (max_connections - 1))
return -EINVAL; return -EINVAL;
spin_lock_irqsave (&iucv_lock, flags);
if (iucv_pathid_table[pathid]) { if (iucv_pathid_table[pathid]) {
spin_unlock_irqrestore (&iucv_lock, flags);
iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]); iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
printk(KERN_WARNING printk(KERN_WARNING
"%s: Pathid being used, error.\n", __FUNCTION__); "%s: Pathid being used, error.\n", __FUNCTION__);
return -EINVAL; return -EINVAL;
} }
iucv_pathid_table[pathid] = handler; iucv_pathid_table[pathid] = handler;
spin_unlock_irqrestore (&iucv_lock, flags);
iucv_debug(1, "exiting"); iucv_debug(1, "exiting");
return 0; return 0;
} /* end of add_pathid function */ } /* end of add_pathid function */
static int
iucv_add_pathid(__u16 pathid, handler *handler)
{
ulong flags;
int rc;
spin_lock_irqsave (&iucv_lock, flags);
rc = __iucv_add_pathid(pathid, handler);
spin_unlock_irqrestore (&iucv_lock, flags);
return rc;
}
static void static void
iucv_remove_pathid(__u16 pathid) iucv_remove_pathid(__u16 pathid)
{ {
...@@ -1090,15 +1132,18 @@ iucv_connect (__u16 *pathid, __u16 msglim_reqstd, ...@@ -1090,15 +1132,18 @@ iucv_connect (__u16 *pathid, __u16 msglim_reqstd,
EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget)); EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
} }
spin_lock_irqsave (&iucv_lock, flags);
parm->ipflags1 = (__u8)flags1; parm->ipflags1 = (__u8)flags1;
b2f0_result = b2f0(CONNECT, parm); b2f0_result = b2f0(CONNECT, parm);
if (b2f0_result == 0)
add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
spin_unlock_irqrestore (&iucv_lock, flags);
if (b2f0_result) { if (b2f0_result) {
release_param(parm); release_param(parm);
return b2f0_result; return b2f0_result;
} }
add_pathid_result = iucv_add_pathid(parm->ippathid, h);
*pathid = parm->ippathid; *pathid = parm->ippathid;
if (msglim) if (msglim)
...@@ -2171,8 +2216,6 @@ iucv_irq_handler(struct pt_regs *regs, __u16 code) ...@@ -2171,8 +2216,6 @@ iucv_irq_handler(struct pt_regs *regs, __u16 code)
{ {
iucv_irqdata *irqdata; iucv_irqdata *irqdata;
irq_enter();
irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC); irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC);
if (!irqdata) { if (!irqdata) {
printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
...@@ -2188,9 +2231,6 @@ iucv_irq_handler(struct pt_regs *regs, __u16 code) ...@@ -2188,9 +2231,6 @@ iucv_irq_handler(struct pt_regs *regs, __u16 code)
spin_unlock(&iucv_irq_queue_lock); spin_unlock(&iucv_irq_queue_lock);
tasklet_schedule(&iucv_tasklet); tasklet_schedule(&iucv_tasklet);
irq_exit();
return;
} }
/** /**
...@@ -2407,6 +2447,8 @@ module_exit(iucv_exit); ...@@ -2407,6 +2447,8 @@ module_exit(iucv_exit);
* using them or should some of them be made * using them or should some of them be made
* static / removed? pls review. Arnd * static / removed? pls review. Arnd
*/ */
EXPORT_SYMBOL (iucv_bus);
EXPORT_SYMBOL (iucv_root);
EXPORT_SYMBOL (iucv_accept); EXPORT_SYMBOL (iucv_accept);
EXPORT_SYMBOL (iucv_connect); EXPORT_SYMBOL (iucv_connect);
#if 0 #if 0
......
...@@ -202,6 +202,9 @@ typedef struct { ...@@ -202,6 +202,9 @@ typedef struct {
u32 length; u32 length;
} iucv_array_t __attribute__ ((aligned (8))); } iucv_array_t __attribute__ ((aligned (8)));
extern struct bus_type iucv_bus;
extern struct device iucv_root;
/* -prototypes- */ /* -prototypes- */
/* /*
* Name: iucv_register_program * Name: iucv_register_program
......
/* /*
* $Id: netiucv.c,v 1.20 2003/05/27 11:34:24 mschwide Exp $ * $Id: netiucv.c,v 1.26 2003/09/23 16:48:17 mschwide Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -30,11 +30,10 @@ ...@@ -30,11 +30,10 @@
* 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.20 $ * RELEASE-TAG: IUCV network driver $Revision: 1.26 $
* *
*/ */
#include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -115,23 +114,6 @@ static struct iucv_connection *connections; ...@@ -115,23 +114,6 @@ static struct iucv_connection *connections;
/* Keep track of interfaces. */ /* Keep track of interfaces. */
static int ifno; 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.
...@@ -1254,6 +1236,16 @@ netiucv_change_mtu (struct net_device * dev, int new_mtu) ...@@ -1254,6 +1236,16 @@ netiucv_change_mtu (struct net_device * dev, int new_mtu)
*****************************************************************************/ *****************************************************************************/
#define CTRL_BUFSIZE 40 #define CTRL_BUFSIZE 40
static ssize_t
user_show (struct device *dev, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
}
static DEVICE_ATTR(user, 0444, user_show, NULL);
static ssize_t static ssize_t
buffer_show (struct device *dev, char *buf) buffer_show (struct device *dev, char *buf)
{ {
...@@ -1437,6 +1429,7 @@ static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write); ...@@ -1437,6 +1429,7 @@ static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
static struct attribute *netiucv_attrs[] = { static struct attribute *netiucv_attrs[] = {
&dev_attr_buffer.attr, &dev_attr_buffer.attr,
&dev_attr_user.attr,
NULL, NULL,
}; };
...@@ -1490,7 +1483,6 @@ netiucv_register_device(struct net_device *ndev, int ifno) ...@@ -1490,7 +1483,6 @@ netiucv_register_device(struct net_device *ndev, int ifno)
int ret; int ret;
char *str = "netiucv"; char *str = "netiucv";
snprintf(dev->name, DEVICE_NAME_SIZE, "%s", priv->conn->userid);
snprintf(dev->bus_id, BUS_ID_SIZE, "%s%x", str, ifno); snprintf(dev->bus_id, BUS_ID_SIZE, "%s%x", str, ifno);
dev->bus = &iucv_bus; dev->bus = &iucv_bus;
dev->parent = &iucv_root; dev->parent = &iucv_root;
...@@ -1739,7 +1731,7 @@ static struct device_driver netiucv_driver = { ...@@ -1739,7 +1731,7 @@ static struct device_driver netiucv_driver = {
static void static void
netiucv_banner(void) netiucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.20 $"; char vbuf[] = "$Revision: 1.26 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
...@@ -1763,7 +1755,6 @@ netiucv_exit(void) ...@@ -1763,7 +1755,6 @@ netiucv_exit(void)
driver_remove_file(&netiucv_driver, &driver_attr_connection); driver_remove_file(&netiucv_driver, &driver_attr_connection);
driver_unregister(&netiucv_driver); driver_unregister(&netiucv_driver);
bus_unregister(&iucv_bus);
printk(KERN_INFO "NETIUCV driver unloaded\n"); printk(KERN_INFO "NETIUCV driver unloaded\n");
return; return;
...@@ -1774,25 +1765,9 @@ netiucv_init(void) ...@@ -1774,25 +1765,9 @@ netiucv_init(void)
{ {
int ret; int ret;
/* 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;
}
ret = driver_register(&netiucv_driver); ret = driver_register(&netiucv_driver);
if (ret != 0) { if (ret != 0) {
printk(KERN_ERR "NETIUCV: failed to register driver.\n"); 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; return ret;
} }
...@@ -1803,9 +1778,7 @@ netiucv_init(void) ...@@ -1803,9 +1778,7 @@ netiucv_init(void)
netiucv_banner(); netiucv_banner();
else { else {
printk(KERN_ERR "NETIUCV: failed to add driver attribute.\n"); printk(KERN_ERR "NETIUCV: failed to add driver attribute.\n");
device_unregister(&iucv_root);
driver_unregister(&netiucv_driver); driver_unregister(&netiucv_driver);
bus_unregister(&iucv_bus);
} }
return ret; return ret;
} }
......
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