2007-04-27 18:01:56 +04:00
/*
* drivers / s390 / char / sclp_config . c
*
* Copyright IBM Corp . 2007
* Author ( s ) : Heiko Carstens < heiko . carstens @ de . ibm . com >
*/
2008-12-25 15:39:48 +03:00
# define KMSG_COMPONENT "sclp_config"
# define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
2007-04-27 18:01:56 +04:00
# include <linux/init.h>
# include <linux/errno.h>
# include <linux/cpu.h>
# include <linux/sysdev.h>
# include <linux/workqueue.h>
2008-04-30 15:38:37 +04:00
# include <asm/smp.h>
2007-04-27 18:01:56 +04:00
2008-12-25 15:39:48 +03:00
# include "sclp.h"
2007-04-27 18:01:56 +04:00
struct conf_mgm_data {
u8 reserved ;
u8 ev_qualifier ;
} __attribute__ ( ( packed ) ) ;
2008-04-30 15:38:37 +04:00
# define EV_QUAL_CPU_CHANGE 1
2007-04-27 18:01:56 +04:00
# define EV_QUAL_CAP_CHANGE 3
static struct work_struct sclp_cpu_capability_work ;
2008-04-30 15:38:37 +04:00
static struct work_struct sclp_cpu_change_work ;
2007-04-27 18:01:56 +04:00
static void sclp_cpu_capability_notify ( struct work_struct * work )
{
int cpu ;
struct sys_device * sysdev ;
2008-12-25 15:39:48 +03:00
pr_warning ( " cpu capability changed. \n " ) ;
2008-01-25 23:08:02 +03:00
get_online_cpus ( ) ;
2007-04-27 18:01:56 +04:00
for_each_online_cpu ( cpu ) {
sysdev = get_cpu_sysdev ( cpu ) ;
kobject_uevent ( & sysdev - > kobj , KOBJ_CHANGE ) ;
}
2008-01-25 23:08:02 +03:00
put_online_cpus ( ) ;
2007-04-27 18:01:56 +04:00
}
2008-07-14 11:57:28 +04:00
static void __ref sclp_cpu_change_notify ( struct work_struct * work )
{
2008-08-01 18:39:23 +04:00
smp_rescan_cpus ( ) ;
2008-04-30 15:38:37 +04:00
}
2007-04-27 18:01:56 +04:00
static void sclp_conf_receiver_fn ( struct evbuf_header * evbuf )
{
struct conf_mgm_data * cdata ;
cdata = ( struct conf_mgm_data * ) ( evbuf + 1 ) ;
2008-04-30 15:38:37 +04:00
switch ( cdata - > ev_qualifier ) {
case EV_QUAL_CPU_CHANGE :
schedule_work ( & sclp_cpu_change_work ) ;
break ;
case EV_QUAL_CAP_CHANGE :
2007-04-27 18:01:56 +04:00
schedule_work ( & sclp_cpu_capability_work ) ;
2008-04-30 15:38:37 +04:00
break ;
}
2007-04-27 18:01:56 +04:00
}
static struct sclp_register sclp_conf_register =
{
. receive_mask = EVTYP_CONFMGMDATA_MASK ,
. receiver_fn = sclp_conf_receiver_fn ,
} ;
static int __init sclp_conf_init ( void )
{
int rc ;
INIT_WORK ( & sclp_cpu_capability_work , sclp_cpu_capability_notify ) ;
2008-04-30 15:38:37 +04:00
INIT_WORK ( & sclp_cpu_change_work , sclp_cpu_change_notify ) ;
2007-04-27 18:01:56 +04:00
rc = sclp_register ( & sclp_conf_register ) ;
2008-07-14 11:59:28 +04:00
if ( rc )
2007-04-27 18:01:56 +04:00
return rc ;
2008-02-19 17:29:32 +03:00
if ( ! ( sclp_conf_register . sclp_send_mask & EVTYP_CONFMGMDATA_MASK ) ) {
2008-12-25 15:39:48 +03:00
pr_warning ( " no configuration management. \n " ) ;
2007-04-27 18:01:56 +04:00
sclp_unregister ( & sclp_conf_register ) ;
rc = - ENOSYS ;
}
return rc ;
}
__initcall ( sclp_conf_init ) ;