diff options
Diffstat (limited to 'drivers/s390/net/lcs.c')
-rw-r--r-- | drivers/s390/net/lcs.c | 116 |
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 | ||
62 | static char version[] __initdata = "LCS driver"; | 62 | static char version[] __initdata = "LCS driver"; |
63 | static char debug_buffer[255]; | 63 | |
64 | /** | ||
65 | * the root device for lcs group devices | ||
66 | */ | ||
67 | static 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 | */ |
83 | static char debug_buffer[255]; | ||
79 | static debug_info_t *lcs_dbf_setup; | 84 | static debug_info_t *lcs_dbf_setup; |
80 | static debug_info_t *lcs_dbf_trace; | 85 | static 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 | ||
1969 | static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); | 1974 | static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); |
1970 | 1975 | ||
1976 | const 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 | |||
1971 | static ssize_t | 1985 | static ssize_t |
1972 | lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) | 1986 | lcs_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 | ||
1983 | static DEVICE_ATTR(type, 0444, lcs_type_show, NULL); | 1997 | static 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; |
2211 | out: | 2229 | out: |
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); |
2232 | out_werr: | ||
2233 | ccw_device_set_offline(card->read.ccwdev); | ||
2234 | out_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 | ||
2387 | static 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 | }; | ||
2393 | MODULE_DEVICE_TABLE(ccw, lcs_ids); | ||
2394 | |||
2395 | static 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 | ||
2422 | static ssize_t | ||
2423 | lcs_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 | |||
2433 | static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); | ||
2434 | |||
2435 | static struct attribute *lcs_group_attrs[] = { | ||
2436 | &driver_attr_group.attr, | ||
2437 | NULL, | ||
2438 | }; | ||
2439 | |||
2440 | static struct attribute_group lcs_group_attr_group = { | ||
2441 | .attrs = lcs_group_attrs, | ||
2442 | }; | ||
2443 | |||
2444 | static 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 | |||
2475 | ccwgroup_err: | ||
2476 | ccw_driver_unregister(&lcs_ccw_driver); | ||
2477 | ccw_err: | ||
2478 | root_device_unregister(lcs_root_dev); | ||
2479 | register_err: | ||
2480 | lcs_unregister_debug_facility(); | ||
2481 | out_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 | ||