2012-08-28 16:50:38 +02:00
/*
* Device driver for s390 storage class memory .
*
* Copyright IBM Corp . 2012
* Author ( s ) : Sebastian Ott < sebott @ linux . vnet . ibm . com >
*/
# define KMSG_COMPONENT "scm_block"
# define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
# include <linux/module.h>
# include <linux/slab.h>
# include <asm/eadm.h>
# include "scm_blk.h"
2013-02-28 12:07:38 +01:00
static void scm_notify ( struct scm_device * scmdev , enum scm_event event )
2012-08-28 16:50:38 +02:00
{
2013-02-28 12:07:55 +01:00
struct scm_blk_dev * bdev = dev_get_drvdata ( & scmdev - > dev ) ;
2013-02-28 12:07:38 +01:00
switch ( event ) {
case SCM_CHANGE :
2013-03-18 16:01:30 +01:00
pr_info ( " %lx: The capabilities of the SCM increment changed \n " ,
2013-02-28 12:07:38 +01:00
( unsigned long ) scmdev - > address ) ;
SCM_LOG ( 2 , " State changed " ) ;
SCM_LOG_STATE ( 2 , scmdev ) ;
break ;
2013-02-28 12:07:55 +01:00
case SCM_AVAIL :
SCM_LOG ( 2 , " Increment available " ) ;
SCM_LOG_STATE ( 2 , scmdev ) ;
scm_blk_set_available ( bdev ) ;
break ;
2013-02-28 12:07:38 +01:00
}
2012-08-28 16:50:38 +02:00
}
static int scm_probe ( struct scm_device * scmdev )
{
struct scm_blk_dev * bdev ;
int ret ;
SCM_LOG ( 2 , " probe " ) ;
SCM_LOG_STATE ( 2 , scmdev ) ;
if ( scmdev - > attrs . oper_state ! = OP_STATE_GOOD )
return - EINVAL ;
bdev = kzalloc ( sizeof ( * bdev ) , GFP_KERNEL ) ;
if ( ! bdev )
return - ENOMEM ;
dev_set_drvdata ( & scmdev - > dev , bdev ) ;
ret = scm_blk_dev_setup ( bdev , scmdev ) ;
if ( ret ) {
dev_set_drvdata ( & scmdev - > dev , NULL ) ;
kfree ( bdev ) ;
goto out ;
}
out :
return ret ;
}
static int scm_remove ( struct scm_device * scmdev )
{
2012-09-04 19:36:41 +02:00
struct scm_blk_dev * bdev = dev_get_drvdata ( & scmdev - > dev ) ;
2012-08-28 16:50:38 +02:00
scm_blk_dev_cleanup ( bdev ) ;
2012-09-04 19:37:51 +02:00
dev_set_drvdata ( & scmdev - > dev , NULL ) ;
2012-08-28 16:50:38 +02:00
kfree ( bdev ) ;
return 0 ;
}
static struct scm_driver scm_drv = {
. drv = {
. name = " scm_block " ,
. owner = THIS_MODULE ,
} ,
2013-02-28 12:07:38 +01:00
. notify = scm_notify ,
2012-08-28 16:50:38 +02:00
. probe = scm_probe ,
. remove = scm_remove ,
. handler = scm_blk_irq ,
} ;
int __init scm_drv_init ( void )
{
return scm_driver_register ( & scm_drv ) ;
}
void scm_drv_cleanup ( void )
{
scm_driver_unregister ( & scm_drv ) ;
}