xref: /linux/drivers/s390/block/scm_drv.c (revision c3e6d407c0c09fb46a391bdd0a28827472825de7)
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 
16f30664e2SSebastian Ott static void notify(struct scm_device *scmdev)
17f30664e2SSebastian Ott {
18f30664e2SSebastian Ott 	pr_info("%lu: The capabilities of the SCM increment changed\n",
19f30664e2SSebastian Ott 		(unsigned long) scmdev->address);
20f30664e2SSebastian Ott 	SCM_LOG(2, "State changed");
21f30664e2SSebastian Ott 	SCM_LOG_STATE(2, scmdev);
22f30664e2SSebastian Ott }
23f30664e2SSebastian Ott 
24f30664e2SSebastian Ott static int scm_probe(struct scm_device *scmdev)
25f30664e2SSebastian Ott {
26f30664e2SSebastian Ott 	struct scm_blk_dev *bdev;
27f30664e2SSebastian Ott 	int ret;
28f30664e2SSebastian Ott 
29f30664e2SSebastian Ott 	SCM_LOG(2, "probe");
30f30664e2SSebastian Ott 	SCM_LOG_STATE(2, scmdev);
31f30664e2SSebastian Ott 
32f30664e2SSebastian Ott 	if (scmdev->attrs.oper_state != OP_STATE_GOOD)
33f30664e2SSebastian Ott 		return -EINVAL;
34f30664e2SSebastian Ott 
35f30664e2SSebastian Ott 	bdev = kzalloc(sizeof(*bdev), GFP_KERNEL);
36f30664e2SSebastian Ott 	if (!bdev)
37f30664e2SSebastian Ott 		return -ENOMEM;
38f30664e2SSebastian Ott 
39f30664e2SSebastian Ott 	dev_set_drvdata(&scmdev->dev, bdev);
40f30664e2SSebastian Ott 	ret = scm_blk_dev_setup(bdev, scmdev);
41f30664e2SSebastian Ott 	if (ret) {
42f30664e2SSebastian Ott 		dev_set_drvdata(&scmdev->dev, NULL);
43f30664e2SSebastian Ott 		kfree(bdev);
44f30664e2SSebastian Ott 		goto out;
45f30664e2SSebastian Ott 	}
46f30664e2SSebastian Ott 
47f30664e2SSebastian Ott out:
48f30664e2SSebastian Ott 	return ret;
49f30664e2SSebastian Ott }
50f30664e2SSebastian Ott 
51f30664e2SSebastian Ott static int scm_remove(struct scm_device *scmdev)
52f30664e2SSebastian Ott {
53*c3e6d407SSebastian Ott 	struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
54f30664e2SSebastian Ott 
55f30664e2SSebastian Ott 	dev_set_drvdata(&scmdev->dev, NULL);
56f30664e2SSebastian Ott 	scm_blk_dev_cleanup(bdev);
57f30664e2SSebastian Ott 	kfree(bdev);
58f30664e2SSebastian Ott 
59f30664e2SSebastian Ott 	return 0;
60f30664e2SSebastian Ott }
61f30664e2SSebastian Ott 
62f30664e2SSebastian Ott static struct scm_driver scm_drv = {
63f30664e2SSebastian Ott 	.drv = {
64f30664e2SSebastian Ott 		.name = "scm_block",
65f30664e2SSebastian Ott 		.owner = THIS_MODULE,
66f30664e2SSebastian Ott 	},
67f30664e2SSebastian Ott 	.notify = notify,
68f30664e2SSebastian Ott 	.probe = scm_probe,
69f30664e2SSebastian Ott 	.remove = scm_remove,
70f30664e2SSebastian Ott 	.handler = scm_blk_irq,
71f30664e2SSebastian Ott };
72f30664e2SSebastian Ott 
73f30664e2SSebastian Ott int __init scm_drv_init(void)
74f30664e2SSebastian Ott {
75f30664e2SSebastian Ott 	return scm_driver_register(&scm_drv);
76f30664e2SSebastian Ott }
77f30664e2SSebastian Ott 
78f30664e2SSebastian Ott void scm_drv_cleanup(void)
79f30664e2SSebastian Ott {
80f30664e2SSebastian Ott 	scm_driver_unregister(&scm_drv);
81f30664e2SSebastian Ott }
82