diff options
Diffstat (limited to 'drivers/s390/net/lcs.c')
| -rw-r--r-- | drivers/s390/net/lcs.c | 115 | 
1 files changed, 97 insertions, 18 deletions
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index a70de9b4bf2..f6cc46dc050 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();  }  |