scm_drv.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. #define pr_fmt(fmt) "scm_block: " fmt
  9. #include <linux/module.h>
  10. #include <linux/slab.h>
  11. #include <asm/eadm.h>
  12. #include "scm_blk.h"
  13. static void scm_notify(struct scm_device *scmdev, enum scm_event event)
  14. {
  15. struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
  16. switch (event) {
  17. case SCM_CHANGE:
  18. pr_info("%lx: The capabilities of the SCM increment changed\n",
  19. (unsigned long) scmdev->address);
  20. SCM_LOG(2, "State changed");
  21. SCM_LOG_STATE(2, scmdev);
  22. break;
  23. case SCM_AVAIL:
  24. SCM_LOG(2, "Increment available");
  25. SCM_LOG_STATE(2, scmdev);
  26. scm_blk_set_available(bdev);
  27. break;
  28. }
  29. }
  30. static int scm_probe(struct scm_device *scmdev)
  31. {
  32. struct scm_blk_dev *bdev;
  33. int ret;
  34. SCM_LOG(2, "probe");
  35. SCM_LOG_STATE(2, scmdev);
  36. if (scmdev->attrs.oper_state != OP_STATE_GOOD)
  37. return -EINVAL;
  38. bdev = kzalloc_obj(*bdev);
  39. if (!bdev)
  40. return -ENOMEM;
  41. dev_set_drvdata(&scmdev->dev, bdev);
  42. ret = scm_blk_dev_setup(bdev, scmdev);
  43. if (ret) {
  44. dev_set_drvdata(&scmdev->dev, NULL);
  45. kfree(bdev);
  46. goto out;
  47. }
  48. out:
  49. return ret;
  50. }
  51. static void scm_remove(struct scm_device *scmdev)
  52. {
  53. struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
  54. scm_blk_dev_cleanup(bdev);
  55. dev_set_drvdata(&scmdev->dev, NULL);
  56. kfree(bdev);
  57. }
  58. static struct scm_driver scm_drv = {
  59. .drv = {
  60. .name = "scm_block",
  61. .owner = THIS_MODULE,
  62. },
  63. .notify = scm_notify,
  64. .probe = scm_probe,
  65. .remove = scm_remove,
  66. .handler = scm_blk_irq,
  67. };
  68. int __init scm_drv_init(void)
  69. {
  70. return scm_driver_register(&scm_drv);
  71. }
  72. void scm_drv_cleanup(void)
  73. {
  74. scm_driver_unregister(&scm_drv);
  75. }