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