aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/lcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/lcs.c')
-rw-r--r--drivers/s390/net/lcs.c116
1 files changed, 98 insertions, 18 deletions
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index a70de9b4bf29..9b19ea13b4d8 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -37,6 +37,7 @@
37#include <linux/igmp.h> 37#include <linux/igmp.h>
38#include <linux/delay.h> 38#include <linux/delay.h>
39#include <linux/kthread.h> 39#include <linux/kthread.h>
40#include <linux/slab.h>
40#include <net/arp.h> 41#include <net/arp.h>
41#include <net/ip.h> 42#include <net/ip.h>
42 43
@@ -47,7 +48,6 @@
47#include <asm/ccwgroup.h> 48#include <asm/ccwgroup.h>
48 49
49#include "lcs.h" 50#include "lcs.h"
50#include "cu3088.h"
51 51
52 52
53#if !defined(CONFIG_NET_ETHERNET) && \ 53#if !defined(CONFIG_NET_ETHERNET) && \
@@ -60,7 +60,11 @@
60 */ 60 */
61 61
62static char version[] __initdata = "LCS driver"; 62static char version[] __initdata = "LCS driver";
63static char debug_buffer[255]; 63
64/**
65 * the root device for lcs group devices
66 */
67static struct device *lcs_root_dev;
64 68
65/** 69/**
66 * Some prototypes. 70 * Some prototypes.
@@ -76,6 +80,7 @@ static int lcs_recovery(void *ptr);
76/** 80/**
77 * Debug Facility Stuff 81 * Debug Facility Stuff
78 */ 82 */
83static char debug_buffer[255];
79static debug_info_t *lcs_dbf_setup; 84static debug_info_t *lcs_dbf_setup;
80static debug_info_t *lcs_dbf_trace; 85static debug_info_t *lcs_dbf_trace;
81 86
@@ -889,7 +894,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
889 rc = lcs_ready_buffer(&card->write, buffer); 894 rc = lcs_ready_buffer(&card->write, buffer);
890 if (rc) 895 if (rc)
891 return rc; 896 return rc;
892 init_timer(&timer); 897 init_timer_on_stack(&timer);
893 timer.function = lcs_lancmd_timeout; 898 timer.function = lcs_lancmd_timeout;
894 timer.data = (unsigned long) reply; 899 timer.data = (unsigned long) reply;
895 timer.expires = jiffies + HZ*card->lancmd_timeout; 900 timer.expires = jiffies + HZ*card->lancmd_timeout;
@@ -1968,6 +1973,15 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
1968 1973
1969static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); 1974static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
1970 1975
1976const char *lcs_type[] = {
1977 "not a channel",
1978 "2216 parallel",
1979 "2216 channel",
1980 "OSA LCS card",
1981 "unknown channel type",
1982 "unsupported channel type",
1983};
1984
1971static ssize_t 1985static ssize_t
1972lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) 1986lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
1973{ 1987{
@@ -1977,7 +1991,7 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
1977 if (!cgdev) 1991 if (!cgdev)
1978 return -ENODEV; 1992 return -ENODEV;
1979 1993
1980 return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]); 1994 return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]);
1981} 1995}
1982 1996
1983static DEVICE_ATTR(type, 0444, lcs_type_show, NULL); 1997static DEVICE_ATTR(type, 0444, lcs_type_show, NULL);
@@ -2130,8 +2144,12 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
2130 card->write.ccwdev = ccwgdev->cdev[1]; 2144 card->write.ccwdev = ccwgdev->cdev[1];
2131 2145
2132 recover_state = card->state; 2146 recover_state = card->state;
2133 ccw_device_set_online(card->read.ccwdev); 2147 rc = ccw_device_set_online(card->read.ccwdev);
2134 ccw_device_set_online(card->write.ccwdev); 2148 if (rc)
2149 goto out_err;
2150 rc = ccw_device_set_online(card->write.ccwdev);
2151 if (rc)
2152 goto out_werr;
2135 2153
2136 LCS_DBF_TEXT(3, setup, "lcsnewdv"); 2154 LCS_DBF_TEXT(3, setup, "lcsnewdv");
2137 2155
@@ -2210,8 +2228,10 @@ netdev_out:
2210 return 0; 2228 return 0;
2211out: 2229out:
2212 2230
2213 ccw_device_set_offline(card->read.ccwdev);
2214 ccw_device_set_offline(card->write.ccwdev); 2231 ccw_device_set_offline(card->write.ccwdev);
2232out_werr:
2233 ccw_device_set_offline(card->read.ccwdev);
2234out_err:
2215 return -ENODEV; 2235 return -ENODEV;
2216} 2236}
2217 2237
@@ -2364,6 +2384,22 @@ static int lcs_restore(struct ccwgroup_device *gdev)
2364 return lcs_pm_resume(card); 2384 return lcs_pm_resume(card);
2365} 2385}
2366 2386
2387static struct ccw_device_id lcs_ids[] = {
2388 {CCW_DEVICE(0x3088, 0x08), .driver_info = lcs_channel_type_parallel},
2389 {CCW_DEVICE(0x3088, 0x1f), .driver_info = lcs_channel_type_2216},
2390 {CCW_DEVICE(0x3088, 0x60), .driver_info = lcs_channel_type_osa2},
2391 {},
2392};
2393MODULE_DEVICE_TABLE(ccw, lcs_ids);
2394
2395static struct ccw_driver lcs_ccw_driver = {
2396 .owner = THIS_MODULE,
2397 .name = "lcs",
2398 .ids = lcs_ids,
2399 .probe = ccwgroup_probe_ccwdev,
2400 .remove = ccwgroup_remove_ccwdev,
2401};
2402
2367/** 2403/**
2368 * LCS ccwgroup driver registration 2404 * LCS ccwgroup driver registration
2369 */ 2405 */
@@ -2383,6 +2419,33 @@ static struct ccwgroup_driver lcs_group_driver = {
2383 .restore = lcs_restore, 2419 .restore = lcs_restore,
2384}; 2420};
2385 2421
2422static ssize_t
2423lcs_driver_group_store(struct device_driver *ddrv, const char *buf,
2424 size_t count)
2425{
2426 int err;
2427 err = ccwgroup_create_from_string(lcs_root_dev,
2428 lcs_group_driver.driver_id,
2429 &lcs_ccw_driver, 2, buf);
2430 return err ? err : count;
2431}
2432
2433static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store);
2434
2435static struct attribute *lcs_group_attrs[] = {
2436 &driver_attr_group.attr,
2437 NULL,
2438};
2439
2440static struct attribute_group lcs_group_attr_group = {
2441 .attrs = lcs_group_attrs,
2442};
2443
2444static const struct attribute_group *lcs_group_attr_groups[] = {
2445 &lcs_group_attr_group,
2446 NULL,
2447};
2448
2386/** 2449/**
2387 * LCS Module/Kernel initialization function 2450 * LCS Module/Kernel initialization function
2388 */ 2451 */
@@ -2394,17 +2457,30 @@ __init lcs_init_module(void)
2394 pr_info("Loading %s\n", version); 2457 pr_info("Loading %s\n", version);
2395 rc = lcs_register_debug_facility(); 2458 rc = lcs_register_debug_facility();
2396 LCS_DBF_TEXT(0, setup, "lcsinit"); 2459 LCS_DBF_TEXT(0, setup, "lcsinit");
2397 if (rc) { 2460 if (rc)
2398 pr_err("Initialization failed\n"); 2461 goto out_err;
2399 return rc; 2462 lcs_root_dev = root_device_register("lcs");
2400 } 2463 rc = IS_ERR(lcs_root_dev) ? PTR_ERR(lcs_root_dev) : 0;
2401 2464 if (rc)
2402 rc = register_cu3088_discipline(&lcs_group_driver); 2465 goto register_err;
2403 if (rc) { 2466 rc = ccw_driver_register(&lcs_ccw_driver);
2404 pr_err("Initialization failed\n"); 2467 if (rc)
2405 return rc; 2468 goto ccw_err;
2406 } 2469 lcs_group_driver.driver.groups = lcs_group_attr_groups;
2470 rc = ccwgroup_driver_register(&lcs_group_driver);
2471 if (rc)
2472 goto ccwgroup_err;
2407 return 0; 2473 return 0;
2474
2475ccwgroup_err:
2476 ccw_driver_unregister(&lcs_ccw_driver);
2477ccw_err:
2478 root_device_unregister(lcs_root_dev);
2479register_err:
2480 lcs_unregister_debug_facility();
2481out_err:
2482 pr_err("Initializing the lcs device driver failed\n");
2483 return rc;
2408} 2484}
2409 2485
2410 2486
@@ -2416,7 +2492,11 @@ __exit lcs_cleanup_module(void)
2416{ 2492{
2417 pr_info("Terminating lcs module.\n"); 2493 pr_info("Terminating lcs module.\n");
2418 LCS_DBF_TEXT(0, trace, "cleanup"); 2494 LCS_DBF_TEXT(0, trace, "cleanup");
2419 unregister_cu3088_discipline(&lcs_group_driver); 2495 driver_remove_file(&lcs_group_driver.driver,
2496 &driver_attr_group);
2497 ccwgroup_driver_unregister(&lcs_group_driver);
2498 ccw_driver_unregister(&lcs_ccw_driver);
2499 root_device_unregister(lcs_root_dev);
2420 lcs_unregister_debug_facility(); 2500 lcs_unregister_debug_facility();
2421} 2501}
2422 2502