1*f30664e2SSebastian Ott /* 2*f30664e2SSebastian Ott * Device driver for s390 storage class memory. 3*f30664e2SSebastian Ott * 4*f30664e2SSebastian Ott * Copyright IBM Corp. 2012 5*f30664e2SSebastian Ott * Author(s): Sebastian Ott <sebott@linux.vnet.ibm.com> 6*f30664e2SSebastian Ott */ 7*f30664e2SSebastian Ott 8*f30664e2SSebastian Ott #define KMSG_COMPONENT "scm_block" 9*f30664e2SSebastian Ott #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 10*f30664e2SSebastian Ott 11*f30664e2SSebastian Ott #include <linux/module.h> 12*f30664e2SSebastian Ott #include <linux/spinlock.h> 13*f30664e2SSebastian Ott #include <linux/slab.h> 14*f30664e2SSebastian Ott #include <asm/eadm.h> 15*f30664e2SSebastian Ott #include "scm_blk.h" 16*f30664e2SSebastian Ott 17*f30664e2SSebastian Ott static void notify(struct scm_device *scmdev) 18*f30664e2SSebastian Ott { 19*f30664e2SSebastian Ott pr_info("%lu: The capabilities of the SCM increment changed\n", 20*f30664e2SSebastian Ott (unsigned long) scmdev->address); 21*f30664e2SSebastian Ott SCM_LOG(2, "State changed"); 22*f30664e2SSebastian Ott SCM_LOG_STATE(2, scmdev); 23*f30664e2SSebastian Ott } 24*f30664e2SSebastian Ott 25*f30664e2SSebastian Ott static int scm_probe(struct scm_device *scmdev) 26*f30664e2SSebastian Ott { 27*f30664e2SSebastian Ott struct scm_blk_dev *bdev; 28*f30664e2SSebastian Ott int ret; 29*f30664e2SSebastian Ott 30*f30664e2SSebastian Ott SCM_LOG(2, "probe"); 31*f30664e2SSebastian Ott SCM_LOG_STATE(2, scmdev); 32*f30664e2SSebastian Ott 33*f30664e2SSebastian Ott if (scmdev->attrs.oper_state != OP_STATE_GOOD) 34*f30664e2SSebastian Ott return -EINVAL; 35*f30664e2SSebastian Ott 36*f30664e2SSebastian Ott bdev = kzalloc(sizeof(*bdev), GFP_KERNEL); 37*f30664e2SSebastian Ott if (!bdev) 38*f30664e2SSebastian Ott return -ENOMEM; 39*f30664e2SSebastian Ott 40*f30664e2SSebastian Ott spin_lock_irq(&scmdev->lock); 41*f30664e2SSebastian Ott dev_set_drvdata(&scmdev->dev, bdev); 42*f30664e2SSebastian Ott spin_unlock_irq(&scmdev->lock); 43*f30664e2SSebastian Ott 44*f30664e2SSebastian Ott ret = scm_blk_dev_setup(bdev, scmdev); 45*f30664e2SSebastian Ott if (ret) { 46*f30664e2SSebastian Ott spin_lock_irq(&scmdev->lock); 47*f30664e2SSebastian Ott dev_set_drvdata(&scmdev->dev, NULL); 48*f30664e2SSebastian Ott spin_unlock_irq(&scmdev->lock); 49*f30664e2SSebastian Ott kfree(bdev); 50*f30664e2SSebastian Ott goto out; 51*f30664e2SSebastian Ott } 52*f30664e2SSebastian Ott 53*f30664e2SSebastian Ott out: 54*f30664e2SSebastian Ott return ret; 55*f30664e2SSebastian Ott } 56*f30664e2SSebastian Ott 57*f30664e2SSebastian Ott static int scm_remove(struct scm_device *scmdev) 58*f30664e2SSebastian Ott { 59*f30664e2SSebastian Ott struct scm_blk_dev *bdev; 60*f30664e2SSebastian Ott 61*f30664e2SSebastian Ott spin_lock_irq(&scmdev->lock); 62*f30664e2SSebastian Ott bdev = dev_get_drvdata(&scmdev->dev); 63*f30664e2SSebastian Ott dev_set_drvdata(&scmdev->dev, NULL); 64*f30664e2SSebastian Ott spin_unlock_irq(&scmdev->lock); 65*f30664e2SSebastian Ott scm_blk_dev_cleanup(bdev); 66*f30664e2SSebastian Ott kfree(bdev); 67*f30664e2SSebastian Ott 68*f30664e2SSebastian Ott return 0; 69*f30664e2SSebastian Ott } 70*f30664e2SSebastian Ott 71*f30664e2SSebastian Ott static struct scm_driver scm_drv = { 72*f30664e2SSebastian Ott .drv = { 73*f30664e2SSebastian Ott .name = "scm_block", 74*f30664e2SSebastian Ott .owner = THIS_MODULE, 75*f30664e2SSebastian Ott }, 76*f30664e2SSebastian Ott .notify = notify, 77*f30664e2SSebastian Ott .probe = scm_probe, 78*f30664e2SSebastian Ott .remove = scm_remove, 79*f30664e2SSebastian Ott .handler = scm_blk_irq, 80*f30664e2SSebastian Ott }; 81*f30664e2SSebastian Ott 82*f30664e2SSebastian Ott int __init scm_drv_init(void) 83*f30664e2SSebastian Ott { 84*f30664e2SSebastian Ott return scm_driver_register(&scm_drv); 85*f30664e2SSebastian Ott } 86*f30664e2SSebastian Ott 87*f30664e2SSebastian Ott void scm_drv_cleanup(void) 88*f30664e2SSebastian Ott { 89*f30664e2SSebastian Ott scm_driver_unregister(&scm_drv); 90*f30664e2SSebastian Ott } 91