s390: remove cu3088 layer for lcs and ctcm
authorUrsula Braun <ursula.braun@de.ibm.com>
Thu, 12 Nov 2009 21:46:29 +0000 (21:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 14 Nov 2009 04:47:00 +0000 (20:47 -0800)
The cu3088-driver used as common base for lcs- and ctcm-devices
makes it difficult to assign the appropriate driver to an lcs-device
or a ctcm-device. This patch eliminates the cu3088-driver and thus
the root device "cu3088". Path /sys/devices/cu3088 is replaced with
the pathes /sys/devices/lcs and /sys/devices/ctcm.

Patch is based on a proposal from Cornelia Huck.

Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
13 files changed:
drivers/s390/net/Makefile
drivers/s390/net/claw.c
drivers/s390/net/claw.h
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_fsms.h
drivers/s390/net/ctcm_main.c
drivers/s390/net/ctcm_main.h
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/ctcm_sysfs.c
drivers/s390/net/cu3088.c [deleted file]
drivers/s390/net/cu3088.h [deleted file]
drivers/s390/net/lcs.c
drivers/s390/net/lcs.h

index 96eddb3b1d08a06e6fae0545ba0b601973a783d6..6cab5a62f99e602194de9459e839cbd2a6ae4dd9 100644 (file)
@@ -3,11 +3,11 @@
 #
 
 ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
-obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o
+obj-$(CONFIG_CTCM) += ctcm.o fsm.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
-obj-$(CONFIG_LCS) += lcs.o cu3088.o
-obj-$(CONFIG_CLAW) += claw.o cu3088.o
+obj-$(CONFIG_LCS) += lcs.o
+obj-$(CONFIG_CLAW) += claw.o
 qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
 obj-$(CONFIG_QETH) += qeth.o
 qeth_l2-y += qeth_l2_main.o
index c63babefb69840be3ce38244b363aaec18c99479..cf283e3d2763c48f075ad86825ea7e271b845c1f 100644 (file)
@@ -90,7 +90,6 @@
 #include <linux/timer.h>
 #include <linux/types.h>
 
-#include "cu3088.h"
 #include "claw.h"
 
 /*
@@ -258,6 +257,9 @@ static int claw_pm_prepare(struct ccwgroup_device *gdev)
        return -EPERM;
 }
 
+/* the root device for claw group devices */
+static struct device *claw_root_dev;
+
 /* ccwgroup table  */
 
 static struct ccwgroup_driver claw_group_driver = {
@@ -272,6 +274,47 @@ static struct ccwgroup_driver claw_group_driver = {
        .prepare     = claw_pm_prepare,
 };
 
+static struct ccw_device_id claw_ids[] = {
+       {CCW_DEVICE(0x3088, 0x61), .driver_info = claw_channel_type_claw},
+       {},
+};
+MODULE_DEVICE_TABLE(ccw, claw_ids);
+
+static struct ccw_driver claw_ccw_driver = {
+       .owner  = THIS_MODULE,
+       .name   = "claw",
+       .ids    = claw_ids,
+       .probe  = ccwgroup_probe_ccwdev,
+       .remove = ccwgroup_remove_ccwdev,
+};
+
+static ssize_t
+claw_driver_group_store(struct device_driver *ddrv, const char *buf,
+                       size_t count)
+{
+       int err;
+       err = ccwgroup_create_from_string(claw_root_dev,
+                                         claw_group_driver.driver_id,
+                                         &claw_ccw_driver, 3, buf);
+       return err ? err : count;
+}
+
+static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store);
+
+static struct attribute *claw_group_attrs[] = {
+       &driver_attr_group.attr,
+       NULL,
+};
+
+static struct attribute_group claw_group_attr_group = {
+       .attrs = claw_group_attrs,
+};
+
+static struct attribute_group *claw_group_attr_groups[] = {
+       &claw_group_attr_group,
+       NULL,
+};
+
 /*
 *       Key functions
 */
@@ -3326,7 +3369,11 @@ claw_remove_files(struct device *dev)
 static void __exit
 claw_cleanup(void)
 {
-       unregister_cu3088_discipline(&claw_group_driver);
+       driver_remove_file(&claw_group_driver.driver,
+                          &driver_attr_group);
+       ccwgroup_driver_unregister(&claw_group_driver);
+       ccw_driver_unregister(&claw_ccw_driver);
+       root_device_unregister(claw_root_dev);
        claw_unregister_debug_facility();
        pr_info("Driver unloaded\n");
 
@@ -3348,16 +3395,31 @@ claw_init(void)
        if (ret) {
                pr_err("Registering with the S/390 debug feature"
                        " failed with error code %d\n", ret);
-               return ret;
+               goto out_err;
        }
        CLAW_DBF_TEXT(2, setup, "init_mod");
-       ret = register_cu3088_discipline(&claw_group_driver);
-       if (ret) {
-               CLAW_DBF_TEXT(2, setup, "init_bad");
-               claw_unregister_debug_facility();
-               pr_err("Registering with the cu3088 device driver failed "
-                          "with error code %d\n", ret);
-       }
+       claw_root_dev = root_device_register("qeth");
+       ret = IS_ERR(claw_root_dev) ? PTR_ERR(claw_root_dev) : 0;
+       if (ret)
+               goto register_err;
+       ret = ccw_driver_register(&claw_ccw_driver);
+       if (ret)
+               goto ccw_err;
+       claw_group_driver.driver.groups = claw_group_attr_groups;
+       ret = ccwgroup_driver_register(&claw_group_driver);
+       if (ret)
+               goto ccwgroup_err;
+       return 0;
+
+ccwgroup_err:
+       ccw_driver_unregister(&claw_ccw_driver);
+ccw_err:
+       root_device_unregister(claw_root_dev);
+register_err:
+       CLAW_DBF_TEXT(2, setup, "init_bad");
+       claw_unregister_debug_facility();
+out_err:
+       pr_err("Initializing the claw device driver failed\n");
        return ret;
 }
 
index 005072c420d30deeb304874054cb6142a7411fe5..46d59a13db12d1aabdaf87d497dbe2f3d1c02d55 100644 (file)
@@ -129,6 +129,18 @@ static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level)
                } \
        } while (0)
 
+/**
+ * Enum for classifying detected devices.
+ */
+enum claw_channel_types {
+       /* Device is not a channel  */
+       claw_channel_type_none,
+
+       /* Device is a CLAW channel device */
+       claw_channel_type_claw
+};
+
+
 /*******************************************************
 *  Define Control Blocks                               *
 *                                                      *
index 4ded9ac2c5efc5298ecd8159e7f368d96001d0ad..70eb7f1384146e4138e5853534a87966cf79fb5a 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/idals.h>
 
 #include "fsm.h"
-#include "cu3088.h"
 
 #include "ctcm_dbug.h"
 #include "ctcm_main.h"
index 2326aba9807af3dfbff1e917b7bb07acee4fdd1e..046d077fabbb3e02ee7470a5a2f5ef245ac0b9a8 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/idals.h>
 
 #include "fsm.h"
-#include "cu3088.h"
 #include "ctcm_main.h"
 
 /*
index ecac3b2e32d4dd845519efe88e886ec4e14537c8..558dc323a9475a2cae973e309800ff9b92775660 100644 (file)
 
 #include <asm/idals.h>
 
-#include "cu3088.h"
 #include "ctcm_fsms.h"
 #include "ctcm_main.h"
 
 /* Some common global variables */
 
+/**
+ * The root device for ctcm group devices
+ */
+static struct device *ctcm_root_dev;
+
 /*
  * Linked list of all detected channels.
  */
@@ -246,7 +250,7 @@ static void channel_remove(struct channel *ch)
  *
  * returns Pointer to a channel or NULL if no matching channel available.
  */
-static struct channel *channel_get(enum channel_types type,
+static struct channel *channel_get(enum ctcm_channel_types type,
                                        char *id, int direction)
 {
        struct channel *ch = channels;
@@ -1342,7 +1346,7 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev)
  *
  * returns 0 on success, !0 on error.
  */
-static int add_channel(struct ccw_device *cdev, enum channel_types type,
+static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
                                struct ctcm_priv *priv)
 {
        struct channel **c = &channels;
@@ -1501,13 +1505,13 @@ free_return:    /* note that all channel pointers are 0 or valid */
 /*
  * Return type of a detected device.
  */
-static enum channel_types get_channel_type(struct ccw_device_id *id)
+static enum ctcm_channel_types get_channel_type(struct ccw_device_id *id)
 {
-       enum channel_types type;
-       type = (enum channel_types)id->driver_info;
+       enum ctcm_channel_types type;
+       type = (enum ctcm_channel_types)id->driver_info;
 
-       if (type == channel_type_ficon)
-               type = channel_type_escon;
+       if (type == ctcm_channel_type_ficon)
+               type = ctcm_channel_type_escon;
 
        return type;
 }
@@ -1525,7 +1529,7 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
        char read_id[CTCM_ID_SIZE];
        char write_id[CTCM_ID_SIZE];
        int direction;
-       enum channel_types type;
+       enum ctcm_channel_types type;
        struct ctcm_priv *priv;
        struct net_device *dev;
        struct ccw_device *cdev0;
@@ -1749,6 +1753,22 @@ err_out:
        return rc;
 }
 
+static struct ccw_device_id ctcm_ids[] = {
+       {CCW_DEVICE(0x3088, 0x08), .driver_info = ctcm_channel_type_parallel},
+       {CCW_DEVICE(0x3088, 0x1e), .driver_info = ctcm_channel_type_ficon},
+       {CCW_DEVICE(0x3088, 0x1f), .driver_info = ctcm_channel_type_escon},
+       {},
+};
+MODULE_DEVICE_TABLE(ccw, ctcm_ids);
+
+static struct ccw_driver ctcm_ccw_driver = {
+       .owner  = THIS_MODULE,
+       .name   = "ctcm",
+       .ids    = ctcm_ids,
+       .probe  = ccwgroup_probe_ccwdev,
+       .remove = ccwgroup_remove_ccwdev,
+};
+
 static struct ccwgroup_driver ctcm_group_driver = {
        .owner       = THIS_MODULE,
        .name        = CTC_DRIVER_NAME,
@@ -1763,6 +1783,33 @@ static struct ccwgroup_driver ctcm_group_driver = {
        .restore     = ctcm_pm_resume,
 };
 
+static ssize_t
+ctcm_driver_group_store(struct device_driver *ddrv, const char *buf,
+                       size_t count)
+{
+       int err;
+
+       err = ccwgroup_create_from_string(ctcm_root_dev,
+                                         ctcm_group_driver.driver_id,
+                                         &ctcm_ccw_driver, 2, buf);
+       return err ? err : count;
+}
+
+static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store);
+
+static struct attribute *ctcm_group_attrs[] = {
+       &driver_attr_group.attr,
+       NULL,
+};
+
+static struct attribute_group ctcm_group_attr_group = {
+       .attrs = ctcm_group_attrs,
+};
+
+static struct attribute_group *ctcm_group_attr_groups[] = {
+       &ctcm_group_attr_group,
+       NULL,
+};
 
 /*
  * Module related routines
@@ -1776,7 +1823,10 @@ static struct ccwgroup_driver ctcm_group_driver = {
  */
 static void __exit ctcm_exit(void)
 {
-       unregister_cu3088_discipline(&ctcm_group_driver);
+       driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group);
+       ccwgroup_driver_unregister(&ctcm_group_driver);
+       ccw_driver_unregister(&ctcm_ccw_driver);
+       root_device_unregister(ctcm_root_dev);
        ctcm_unregister_dbf_views();
        pr_info("CTCM driver unloaded\n");
 }
@@ -1802,17 +1852,31 @@ static int __init ctcm_init(void)
        channels = NULL;
 
        ret = ctcm_register_dbf_views();
-       if (ret) {
-               return ret;
-       }
-       ret = register_cu3088_discipline(&ctcm_group_driver);
-       if (ret) {
-               ctcm_unregister_dbf_views();
-               pr_err("%s / register_cu3088_discipline failed, ret = %d\n",
-                       __func__, ret);
-               return ret;
-       }
+       if (ret)
+               goto out_err;
+       ctcm_root_dev = root_device_register("ctcm");
+       ret = IS_ERR(ctcm_root_dev) ? PTR_ERR(ctcm_root_dev) : 0;
+       if (ret)
+               goto register_err;
+       ret = ccw_driver_register(&ctcm_ccw_driver);
+       if (ret)
+               goto ccw_err;
+       ctcm_group_driver.driver.groups = ctcm_group_attr_groups;
+       ret = ccwgroup_driver_register(&ctcm_group_driver);
+       if (ret)
+               goto ccwgroup_err;
        print_banner();
+       return 0;
+
+ccwgroup_err:
+       ccw_driver_unregister(&ctcm_ccw_driver);
+ccw_err:
+       root_device_unregister(ctcm_root_dev);
+register_err:
+       ctcm_unregister_dbf_views();
+out_err:
+       pr_err("%s / Initializing the ctcm device driver failed, ret = %d\n",
+               __func__, ret);
        return ret;
 }
 
index d925e732b7d8f69fbf46785e2d4ee24cb3db8f34..d34fa14f44e767c7ddf866b2d325406c48607ce2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/netdevice.h>
 
 #include "fsm.h"
-#include "cu3088.h"
 #include "ctcm_dbug.h"
 #include "ctcm_mpc.h"
 
                        ctcmpc_dumpit(buf, len); \
        } while (0)
 
+/**
+ * Enum for classifying detected devices
+ */
+enum ctcm_channel_types {
+       /* Device is not a channel  */
+       ctcm_channel_type_none,
+
+       /* Device is a CTC/A */
+       ctcm_channel_type_parallel,
+
+       /* Device is a FICON channel */
+       ctcm_channel_type_ficon,
+
+       /* Device is a ESCON channel */
+       ctcm_channel_type_escon
+};
+
 /*
  * CCW commands, used in this driver.
  */
@@ -121,7 +137,7 @@ struct channel {
         * Type of this channel.
         * CTC/A or Escon for valid channels.
         */
-       enum channel_types type;
+       enum ctcm_channel_types type;
        /*
         * Misc. flags. See CHANNEL_FLAGS_... below
         */
index 781e18be7e8fb1cb26dcabc09df6750edac6bd2f..5978b390153f82210a67650852643518c9fd0dae 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/moduleparam.h>
 #include <asm/idals.h>
 
-#include "cu3088.h"
 #include "ctcm_mpc.h"
 #include "ctcm_main.h"
 #include "ctcm_fsms.h"
index 8452bb052d68aa80f64c6fd10971fc3d4ea31969..738ad26c74a737c1f6c9b5a8ceb6d853f7e86719 100644 (file)
@@ -158,6 +158,15 @@ static ssize_t ctcm_proto_store(struct device *dev,
        return count;
 }
 
+const char *ctcm_type[] = {
+       "not a channel",
+       "CTC/A",
+       "FICON channel",
+       "ESCON channel",
+       "unknown channel type",
+       "unsupported channel type",
+};
+
 static ssize_t ctcm_type_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -168,7 +177,7 @@ static ssize_t ctcm_type_show(struct device *dev,
                return -ENODEV;
 
        return sprintf(buf, "%s\n",
-                       cu3088_type[cgdev->cdev[0]->id.driver_info]);
+                       ctcm_type[cgdev->cdev[0]->id.driver_info]);
 }
 
 static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
deleted file mode 100644 (file)
index 4838345..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * CTC / LCS ccw_device driver
- *
- * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Arnd Bergmann <arndb@de.ibm.com>
- *            Cornelia Huck <cornelia.huck@de.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <asm/ccwdev.h>
-#include <asm/ccwgroup.h>
-
-#include "cu3088.h"
-
-const char *cu3088_type[] = {
-       "not a channel",
-       "CTC/A",
-       "ESCON channel",
-       "FICON channel",
-       "OSA LCS card",
-       "CLAW channel device",
-       "unknown channel type",
-       "unsupported channel type",
-};
-
-/* static definitions */
-
-static struct ccw_device_id cu3088_ids[] = {
-       { CCW_DEVICE(0x3088, 0x08), .driver_info = channel_type_parallel },
-       { CCW_DEVICE(0x3088, 0x1f), .driver_info = channel_type_escon },
-       { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon },
-       { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 },
-       { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw },
-       { /* end of list */ }
-};
-
-static struct ccw_driver cu3088_driver;
-
-static struct device *cu3088_root_dev;
-
-static ssize_t
-group_write(struct device_driver *drv, const char *buf, size_t count)
-{
-       int ret;
-       struct ccwgroup_driver *cdrv;
-
-       cdrv = to_ccwgroupdrv(drv);
-       if (!cdrv)
-               return -EINVAL;
-       ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id,
-                                         &cu3088_driver, 2, buf);
-
-       return (ret == 0) ? count : ret;
-}
-
-static DRIVER_ATTR(group, 0200, NULL, group_write);
-
-/* Register-unregister for ctc&lcs */
-int
-register_cu3088_discipline(struct ccwgroup_driver *dcp)
-{
-       int rc;
-
-       if (!dcp)
-               return -EINVAL;
-
-       /* Register discipline.*/
-       rc = ccwgroup_driver_register(dcp);
-       if (rc)
-               return rc;
-
-       rc = driver_create_file(&dcp->driver, &driver_attr_group);
-       if (rc)
-               ccwgroup_driver_unregister(dcp);
-
-       return rc;
-
-}
-
-void
-unregister_cu3088_discipline(struct ccwgroup_driver *dcp)
-{
-       if (!dcp)
-               return;
-
-       driver_remove_file(&dcp->driver, &driver_attr_group);
-       ccwgroup_driver_unregister(dcp);
-}
-
-static struct ccw_driver cu3088_driver = {
-       .owner       = THIS_MODULE,
-       .ids         = cu3088_ids,
-       .name        = "cu3088",
-       .probe       = ccwgroup_probe_ccwdev,
-       .remove      = ccwgroup_remove_ccwdev,
-};
-
-/* module setup */
-static int __init
-cu3088_init (void)
-{
-       int rc;
-
-       cu3088_root_dev = root_device_register("cu3088");
-       if (IS_ERR(cu3088_root_dev))
-               return PTR_ERR(cu3088_root_dev);
-       rc = ccw_driver_register(&cu3088_driver);
-       if (rc)
-               root_device_unregister(cu3088_root_dev);
-
-       return rc;
-}
-
-static void __exit
-cu3088_exit (void)
-{
-       ccw_driver_unregister(&cu3088_driver);
-       root_device_unregister(cu3088_root_dev);
-}
-
-MODULE_DEVICE_TABLE(ccw,cu3088_ids);
-MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
-MODULE_LICENSE("GPL");
-
-module_init(cu3088_init);
-module_exit(cu3088_exit);
-
-EXPORT_SYMBOL_GPL(cu3088_type);
-EXPORT_SYMBOL_GPL(register_cu3088_discipline);
-EXPORT_SYMBOL_GPL(unregister_cu3088_discipline);
diff --git a/drivers/s390/net/cu3088.h b/drivers/s390/net/cu3088.h
deleted file mode 100644 (file)
index d8558a7..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _CU3088_H
-#define _CU3088_H
-
-/**
- * Enum for classifying detected devices.
- */
-enum channel_types {
-        /* Device is not a channel  */
-       channel_type_none,
-
-        /* Device is a CTC/A */
-       channel_type_parallel,
-
-       /* Device is a ESCON channel */
-       channel_type_escon,
-
-       /* Device is a FICON channel */
-       channel_type_ficon,
-
-       /* Device is a OSA2 card */
-       channel_type_osa2,
-
-       /* Device is a CLAW channel device */
-       channel_type_claw,
-
-       /* Device is a channel, but we don't know
-        * anything about it */
-       channel_type_unknown,
-
-       /* Device is an unsupported model */
-       channel_type_unsupported,
-
-       /* number of type entries */
-       num_channel_types
-};
-
-extern const char *cu3088_type[num_channel_types];
-extern int register_cu3088_discipline(struct ccwgroup_driver *);
-extern void unregister_cu3088_discipline(struct ccwgroup_driver *);
-
-#endif
index 5e46415d3e13a9f15955d0ca9a0ba8034fa61d10..1d43d23f5ea3657dbde0cea876228d13fa768ba0 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/ccwgroup.h>
 
 #include "lcs.h"
-#include "cu3088.h"
 
 
 #if !defined(CONFIG_NET_ETHERNET) && \
  */
 
 static char version[] __initdata = "LCS driver";
-static char debug_buffer[255];
+
+/**
+  * the root device for lcs group devices
+  */
+static struct device *lcs_root_dev;
 
 /**
  * Some prototypes.
@@ -76,6 +79,7 @@ static int lcs_recovery(void *ptr);
 /**
  * Debug Facility Stuff
  */
+static char debug_buffer[255];
 static debug_info_t *lcs_dbf_setup;
 static debug_info_t *lcs_dbf_trace;
 
@@ -1968,6 +1972,15 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
 
 static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
 
+const char *lcs_type[] = {
+       "not a channel",
+       "2216 parallel",
+       "2216 channel",
+       "OSA LCS card",
+       "unknown channel type",
+       "unsupported channel type",
+};
+
 static ssize_t
 lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1977,7 +1990,7 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
        if (!cgdev)
                return -ENODEV;
 
-       return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
+       return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]);
 }
 
 static DEVICE_ATTR(type, 0444, lcs_type_show, NULL);
@@ -2370,6 +2383,22 @@ static int lcs_restore(struct ccwgroup_device *gdev)
        return lcs_pm_resume(card);
 }
 
+static struct ccw_device_id lcs_ids[] = {
+       {CCW_DEVICE(0x3088, 0x08), .driver_info = lcs_channel_type_parallel},
+       {CCW_DEVICE(0x3088, 0x1f), .driver_info = lcs_channel_type_2216},
+       {CCW_DEVICE(0x3088, 0x60), .driver_info = lcs_channel_type_osa2},
+       {},
+};
+MODULE_DEVICE_TABLE(ccw, lcs_ids);
+
+static struct ccw_driver lcs_ccw_driver = {
+       .owner  = THIS_MODULE,
+       .name   = "lcs",
+       .ids    = lcs_ids,
+       .probe  = ccwgroup_probe_ccwdev,
+       .remove = ccwgroup_remove_ccwdev,
+};
+
 /**
  * LCS ccwgroup driver registration
  */
@@ -2389,6 +2418,33 @@ static struct ccwgroup_driver lcs_group_driver = {
        .restore     = lcs_restore,
 };
 
+static ssize_t
+lcs_driver_group_store(struct device_driver *ddrv, const char *buf,
+                      size_t count)
+{
+       int err;
+       err = ccwgroup_create_from_string(lcs_root_dev,
+                                         lcs_group_driver.driver_id,
+                                         &lcs_ccw_driver, 2, buf);
+       return err ? err : count;
+}
+
+static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store);
+
+static struct attribute *lcs_group_attrs[] = {
+       &driver_attr_group.attr,
+       NULL,
+};
+
+static struct attribute_group lcs_group_attr_group = {
+       .attrs = lcs_group_attrs,
+};
+
+static struct attribute_group *lcs_group_attr_groups[] = {
+       &lcs_group_attr_group,
+       NULL,
+};
+
 /**
  *  LCS Module/Kernel initialization function
  */
@@ -2400,17 +2456,30 @@ __init lcs_init_module(void)
        pr_info("Loading %s\n", version);
        rc = lcs_register_debug_facility();
        LCS_DBF_TEXT(0, setup, "lcsinit");
-       if (rc) {
-               pr_err("Initialization failed\n");
-               return rc;
-       }
-
-       rc = register_cu3088_discipline(&lcs_group_driver);
-       if (rc) {
-               pr_err("Initialization failed\n");
-               return rc;
-       }
+       if (rc)
+               goto out_err;
+       lcs_root_dev = root_device_register("lcs");
+       rc = IS_ERR(lcs_root_dev) ? PTR_ERR(lcs_root_dev) : 0;
+       if (rc)
+               goto register_err;
+       rc = ccw_driver_register(&lcs_ccw_driver);
+       if (rc)
+               goto ccw_err;
+       lcs_group_driver.driver.groups = lcs_group_attr_groups;
+       rc = ccwgroup_driver_register(&lcs_group_driver);
+       if (rc)
+               goto ccwgroup_err;
        return 0;
+
+ccwgroup_err:
+       ccw_driver_unregister(&lcs_ccw_driver);
+ccw_err:
+       root_device_unregister(lcs_root_dev);
+register_err:
+       lcs_unregister_debug_facility();
+out_err:
+       pr_err("Initializing the lcs device driver failed\n");
+       return rc;
 }
 
 
@@ -2422,7 +2491,11 @@ __exit lcs_cleanup_module(void)
 {
        pr_info("Terminating lcs module.\n");
        LCS_DBF_TEXT(0, trace, "cleanup");
-       unregister_cu3088_discipline(&lcs_group_driver);
+       driver_remove_file(&lcs_group_driver.driver,
+                          &driver_attr_group);
+       ccwgroup_driver_unregister(&lcs_group_driver);
+       ccw_driver_unregister(&lcs_ccw_driver);
+       root_device_unregister(lcs_root_dev);
        lcs_unregister_debug_facility();
 }
 
index 6d668642af270e27b6b376ce99c2b3276cbc63a8..8c03392ac833f2a284c7f422f296b52fc610e285 100644 (file)
@@ -36,6 +36,24 @@ static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level)
 #define CARD_FROM_DEV(cdev) \
        (struct lcs_card *) dev_get_drvdata( \
                &((struct ccwgroup_device *)dev_get_drvdata(&cdev->dev))->dev);
+
+/**
+ * Enum for classifying detected devices.
+ */
+enum lcs_channel_types {
+       /* Device is not a channel  */
+       lcs_channel_type_none,
+
+       /* Device is a 2216 channel */
+       lcs_channel_type_parallel,
+
+       /* Device is a 2216 channel */
+       lcs_channel_type_2216,
+
+       /* Device is a OSA2 card */
+       lcs_channel_type_osa2
+};
+
 /**
  * CCW commands used in this driver
  */