summaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/lcs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 16:55:01 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 16:55:01 +0100
commitd7fc02c7bae7b1cf69269992cf880a43a350cdaa (patch)
treea43d56fa72913a1cc98a0bbebe054d08581b3a7c /drivers/s390/net/lcs.c
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6 (diff)
parentMerge branch 'master' of /home/davem/src/GIT/linux-2.6/ (diff)
downloadlinux-d7fc02c7bae7b1cf69269992cf880a43a350cdaa.tar.xz
linux-d7fc02c7bae7b1cf69269992cf880a43a350cdaa.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1815 commits) mac80211: fix reorder buffer release iwmc3200wifi: Enable wimax core through module parameter iwmc3200wifi: Add wifi-wimax coexistence mode as a module parameter iwmc3200wifi: Coex table command does not expect a response iwmc3200wifi: Update wiwi priority table iwlwifi: driver version track kernel version iwlwifi: indicate uCode type when fail dump error/event log iwl3945: remove duplicated event logging code b43: fix two warnings ipw2100: fix rebooting hang with driver loaded cfg80211: indent regulatory messages with spaces iwmc3200wifi: fix NULL pointer dereference in pmkid update mac80211: Fix TX status reporting for injected data frames ath9k: enable 2GHz band only if the device supports it airo: Fix integer overflow warning rt2x00: Fix padding bug on L2PAD devices. WE: Fix set events not propagated b43legacy: avoid PPC fault during resume b43: avoid PPC fault during resume tcp: fix a timewait refcnt race ... Fix up conflicts due to sysctl cleanups (dead sysctl_check code and CTL_UNNUMBERED removed) in kernel/sysctl_check.c net/ipv4/sysctl_net_ipv4.c net/ipv6/addrconf.c net/sctp/sysctl.c
Diffstat (limited to 'drivers/s390/net/lcs.c')
-rw-r--r--drivers/s390/net/lcs.c115
1 files changed, 97 insertions, 18 deletions
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index a70de9b4bf29..f6cc46dc0501 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -47,7 +47,6 @@
#include <asm/ccwgroup.h>
#include "lcs.h"
-#include "cu3088.h"
#if !defined(CONFIG_NET_ETHERNET) && \
@@ -60,7 +59,11 @@
*/
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();
}