- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / drivers / s390 / net / lcs.c
index a70de9b..f6cc46d 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;
 
@@ -889,7 +893,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
        rc = lcs_ready_buffer(&card->write, buffer);
        if (rc)
                return rc;
-       init_timer(&timer);
+       init_timer_on_stack(&timer);
        timer.function = lcs_lancmd_timeout;
        timer.data = (unsigned long) reply;
        timer.expires = jiffies + HZ*card->lancmd_timeout;
@@ -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);
@@ -2130,8 +2143,12 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
        card->write.ccwdev = ccwgdev->cdev[1];
 
        recover_state = card->state;
-       ccw_device_set_online(card->read.ccwdev);
-       ccw_device_set_online(card->write.ccwdev);
+       rc = ccw_device_set_online(card->read.ccwdev);
+       if (rc)
+               goto out_err;
+       rc = ccw_device_set_online(card->write.ccwdev);
+       if (rc)
+               goto out_werr;
 
        LCS_DBF_TEXT(3, setup, "lcsnewdv");
 
@@ -2210,8 +2227,10 @@ netdev_out:
        return 0;
 out:
 
-       ccw_device_set_offline(card->read.ccwdev);
        ccw_device_set_offline(card->write.ccwdev);
+out_werr:
+       ccw_device_set_offline(card->read.ccwdev);
+out_err:
        return -ENODEV;
 }
 
@@ -2364,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
  */
@@ -2383,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 const struct attribute_group *lcs_group_attr_groups[] = {
+       &lcs_group_attr_group,
+       NULL,
+};
+
 /**
  *  LCS Module/Kernel initialization function
  */
@@ -2394,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;
 }
 
 
@@ -2416,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();
 }