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