s390: set online race in the lcs driver
Subsystems (3)
PATCH 3/10 s390: set online race in the lcs driver
[patch 3/10] s390: set online race in the lcs driver.
From: Michael Holzheu <[email protected]>
There is a race between lcs_stopcard() and lcs_open_device() which can lead to the error 'lcs: Error in starting channel, rc=-16'. lcs_open_device() is invoked when 'ifconfig up' is called due to a hotplug event, which is caused by register_netdev(). In parallel lcs_stopcard() is executed. Both functions are sending lcs commands. The second invocation fails with -EBUSY (-16) as return value. Move invocation of register_netdev() after invocation of lcs_stopcard to avoid the race.
Signed-off-by Frank Pavlic <[email protected]>
diffstat:
drivers/s390/net/lcs.c | 31 ++++++++++++++++--------------- 1 files changed, 16 insertions(+), 15 deletions(-)
drivers/s390/net/lcs.c +16 -15
@@ -11,7 +11,7 @@* Frank Pavlic ([email protected]) and * Martin Schwidefsky <[email protected]> * -* $Revision: 1.97 $ $Date: 2005/03/31 09:42:02 $ +* $Revision: 1.98 $ $Date: 2005/04/18 13:41:29 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@/** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.97 $" +#define VERSION_LCS_C "$Revision: 1.98 $"static char version[]__initdata ="LCS driver (" VERSION_LCS_C "/" VERSION_LCS_H ")" ;static char debug_buffer[255 ];
@@ -1098,14 +1098,6 @@ lcs_check_multicast_support(struct lcs_cPRINT_ERR ("Query IPAssist failed. Assuming unsupported!\n" );return -EOPNOTSUPP ; } -/* Print out supported assists: IPv6 */ -PRINT_INFO ("LCS device %s %s IPv6 support\n" , card->dev->name, - (card->ip_assists_supported &LCS_IPASS_IPV6_SUPPORT ) ? -"with" :"without" ); -/* Print out supported assist: Multicast */ -PRINT_INFO ("LCS device %s %s Multicast support\n" , card->dev->name, - (card->ip_assists_supported &LCS_IPASS_MULTICAST_SUPPORT ) ? -"with" :"without" );if (card->ip_assists_supported &LCS_IPASS_MULTICAST_SUPPORT )return 0 ;return -EOPNOTSUPP ;
@@ -2198,30 +2190,39 @@ lcs_new_device(struct ccwgroup_device *cif (!dev) goto out; card->dev = dev; -netdev_out: card->dev->priv = card; card->dev->open = lcs_open_device; card->dev->stop = lcs_stop_device; card->dev->hard_start_xmit = lcs_start_xmit; card->dev->get_stats = lcs_getstats;SET_MODULE_OWNER (dev); -if (lcs_register_netdev (ccwgdev) !=0 ) - goto out;memcpy (card->dev->dev_addr, card->mac,LCS_MAC_LENGTH );#ifdef CONFIG_IP_MULTICAST if (!lcs_check_multicast_support (card)) card->dev->set_multicast_list = lcs_set_multicast_list;#endif -netif_stop_queue (card->dev); +netdev_out:lcs_set_allowed_threads (card,0xffffffff );if (recover_state ==DEV_STATE_RECOVER ) {lcs_set_multicast_list (card->dev); card->dev->flags |=IFF_UP ;netif_wake_queue (card->dev); card->state =DEV_STATE_UP ; - }else + }else {lcs_stopcard (card); + } +if (lcs_register_netdev (ccwgdev) !=0 ) + goto out; + +/* Print out supported assists: IPv6 */ +PRINT_INFO ("LCS device %s %s IPv6 support\n" , card->dev->name, + (card->ip_assists_supported &LCS_IPASS_IPV6_SUPPORT ) ? +"with" :"without" ); +/* Print out supported assist: Multicast */ +PRINT_INFO ("LCS device %s %s Multicast support\n" , card->dev->name, + (card->ip_assists_supported &LCS_IPASS_MULTICAST_SUPPORT ) ? +"with" :"without" );return 0 ; out: