blk-sec-common.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Samsung specific module in block layer
  4. *
  5. * Copyright (C) 2021 Manjong Lee <[email protected]>
  6. * Copyright (C) 2021 Junho Kim <[email protected]>
  7. * Copyright (C) 2021 Changheun Lee <[email protected]>
  8. * Copyright (C) 2021 Seunghwan Hyun <[email protected]>
  9. * Copyright (C) 2021 Tran Xuan Nam <[email protected]>
  10. */
  11. #include <linux/sysfs.h>
  12. #include <linux/module.h>
  13. #include <linux/blk_types.h>
  14. #include <linux/blkdev.h>
  15. #include <linux/part_stat.h>
  16. #include <linux/sec_class.h>
  17. #include "blk-sec.h"
  18. struct disk_info {
  19. /* fields related with target device itself */
  20. struct gendisk *gd;
  21. struct request_queue *queue;
  22. };
  23. struct device *blk_sec_dev;
  24. EXPORT_SYMBOL(blk_sec_dev);
  25. struct workqueue_struct *blk_sec_common_wq;
  26. EXPORT_SYMBOL(blk_sec_common_wq);
  27. static struct disk_info internal_disk;
  28. static unsigned int internal_min_size_mb = 10 * 1024; /* 10GB */
  29. #define SECTORS2MB(x) ((x) / 2 / 1024)
  30. #define SCSI_DISK0_MAJOR 8
  31. #define MMC_BLOCK_MAJOR 179
  32. #define MAJOR8_DEV_NUM 16 /* maximum number of minor devices in scsi disk0 */
  33. #define SCSI_MINORS 16 /* first minor number of scsi disk0 */
  34. #define MMC_TARGET_DEV 16 /* number of mmc devices set of target (maximum 256) */
  35. #define MMC_MINORS 8 /* first minor number of mmc disk */
  36. static bool is_internal_bdev(struct block_device *dev)
  37. {
  38. int size_mb;
  39. if (bdev_is_partition(dev))
  40. return false;
  41. if (dev->bd_disk->flags & GENHD_FL_REMOVABLE)
  42. return false;
  43. size_mb = SECTORS2MB(get_capacity(dev->bd_disk));
  44. if (size_mb >= internal_min_size_mb)
  45. return true;
  46. return false;
  47. }
  48. static struct gendisk *find_internal_disk(void)
  49. {
  50. struct block_device *bdev;
  51. struct gendisk *gd = NULL;
  52. int idx;
  53. dev_t devno = MKDEV(0, 0);
  54. for (idx = 0; idx < MAJOR8_DEV_NUM; idx++) {
  55. devno = MKDEV(SCSI_DISK0_MAJOR, SCSI_MINORS * idx);
  56. bdev = blkdev_get_by_dev(devno, FMODE_READ, NULL);
  57. if (IS_ERR(bdev))
  58. continue;
  59. if (bdev->bd_disk && is_internal_bdev(bdev))
  60. gd = bdev->bd_disk;
  61. blkdev_put(bdev, FMODE_READ);
  62. if (gd)
  63. return gd;
  64. }
  65. for (idx = 0; idx < MMC_TARGET_DEV; idx++) {
  66. devno = MKDEV(MMC_BLOCK_MAJOR, MMC_MINORS * idx);
  67. bdev = blkdev_get_by_dev(devno, FMODE_READ, NULL);
  68. if (IS_ERR(bdev))
  69. continue;
  70. if (bdev->bd_disk && is_internal_bdev(bdev))
  71. gd = bdev->bd_disk;
  72. blkdev_put(bdev, FMODE_READ);
  73. if (gd)
  74. return gd;
  75. }
  76. return NULL;
  77. }
  78. static inline int init_internal_disk_info(void)
  79. {
  80. if (!internal_disk.gd) {
  81. internal_disk.gd = find_internal_disk();
  82. if (unlikely(!internal_disk.gd)) {
  83. pr_err("%s: can't find internal disk\n", __func__);
  84. return -ENODEV;
  85. }
  86. internal_disk.queue = internal_disk.gd->queue;
  87. }
  88. return 0;
  89. }
  90. static inline void clear_internal_disk_info(void)
  91. {
  92. internal_disk.gd = NULL;
  93. internal_disk.queue = NULL;
  94. }
  95. struct gendisk *blk_sec_internal_disk(void)
  96. {
  97. if (unlikely(!internal_disk.gd))
  98. init_internal_disk_info();
  99. return internal_disk.gd;
  100. }
  101. EXPORT_SYMBOL(blk_sec_internal_disk);
  102. static int blk_sec_uevent(struct device *dev, struct kobj_uevent_env *env)
  103. {
  104. return add_uevent_var(env, "DEVNAME=%s", dev->kobj.name);
  105. }
  106. static struct device_type blk_sec_type = {
  107. .uevent = blk_sec_uevent,
  108. };
  109. static int __init blk_sec_common_init(void)
  110. {
  111. int retval;
  112. #if IS_ENABLED(CONFIG_DRV_SAMSUNG)
  113. blk_sec_dev = sec_device_create(NULL, "blk_sec");
  114. if (unlikely(IS_ERR(blk_sec_dev))) {
  115. pr_err("%s: Failed to create blk-sec device\n", __func__);
  116. return PTR_ERR(blk_sec_dev);
  117. }
  118. blk_sec_dev->type = &blk_sec_type;
  119. #endif
  120. blk_sec_common_wq = create_freezable_workqueue("blk_sec_common");
  121. retval = init_internal_disk_info();
  122. if (retval) {
  123. clear_internal_disk_info();
  124. pr_err("%s: Can't find internal disk info!", __func__);
  125. }
  126. return 0;
  127. }
  128. static void __exit blk_sec_common_exit(void)
  129. {
  130. clear_internal_disk_info();
  131. }
  132. module_init(blk_sec_common_init);
  133. module_exit(blk_sec_common_exit);
  134. MODULE_LICENSE("GPL v2");
  135. MODULE_AUTHOR("Changheun Lee <[email protected]>");
  136. MODULE_DESCRIPTION("Samsung specific module in block layer");
  137. MODULE_VERSION("1.0");