}
 #endif
 
-static inline bool f2fs_discard_en(struct f2fs_sb_info *sbi)
+static inline bool f2fs_hw_should_discard(struct f2fs_sb_info *sbi)
 {
-       struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev);
+       return f2fs_sb_has_blkzoned(sbi->sb);
+}
 
-       return blk_queue_discard(q) || f2fs_sb_has_blkzoned(sbi->sb);
+static inline bool f2fs_hw_support_discard(struct f2fs_sb_info *sbi)
+{
+       return blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev));
+}
+
+static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi)
+{
+       return (test_opt(sbi, DISCARD) && f2fs_hw_support_discard(sbi)) ||
+                                       f2fs_hw_should_discard(sbi);
 }
 
 static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
 
        struct list_head *head = &SM_I(sbi)->dcc_info->entry_list;
        int i;
 
-       if (se->valid_blocks == max_blocks || !f2fs_discard_en(sbi))
+       if (se->valid_blocks == max_blocks || !f2fs_hw_support_discard(sbi))
                return false;
 
        if (!force) {
-               if (!test_opt(sbi, DISCARD) || !se->valid_blocks ||
+               if (!f2fs_realtime_discard_enable(sbi) || !se->valid_blocks ||
                        SM_I(sbi)->dcc_info->nr_discards >=
                                SM_I(sbi)->dcc_info->max_discards)
                        return false;
                                dirty_i->nr_dirty[PRE]--;
                }
 
-               if (!test_opt(sbi, DISCARD))
+               if (!f2fs_realtime_discard_enable(sbi))
                        continue;
 
                if (force && start >= cpc->trim_start &&
                        del = 0;
                }
 
-               if (f2fs_discard_en(sbi) &&
-                       !f2fs_test_and_set_bit(offset, se->discard_map))
+               if (!f2fs_test_and_set_bit(offset, se->discard_map))
                        sbi->discard_blks--;
 
                /* don't overwrite by SSR to keep node chain */
                        del = 0;
                }
 
-               if (f2fs_discard_en(sbi) &&
-                       f2fs_test_and_clear_bit(offset, se->discard_map))
+               if (f2fs_test_and_clear_bit(offset, se->discard_map))
                        sbi->discard_blks++;
        }
        if (!f2fs_test_bit(offset, se->ckpt_valid_map))
         * discard option. User configuration looks like using runtime discard
         * or periodic fstrim instead of it.
         */
-       if (test_opt(sbi, DISCARD))
+       if (f2fs_realtime_discard_enable(sbi))
                goto out;
 
        start_block = START_BLOCK(sbi, start_segno);
                        return -ENOMEM;
 #endif
 
-               if (f2fs_discard_en(sbi)) {
-                       sit_i->sentries[start].discard_map
-                               = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE,
-                                                               GFP_KERNEL);
-                       if (!sit_i->sentries[start].discard_map)
-                               return -ENOMEM;
-               }
+               sit_i->sentries[start].discard_map
+                       = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE,
+                                                       GFP_KERNEL);
+               if (!sit_i->sentries[start].discard_map)
+                       return -ENOMEM;
        }
 
        sit_i->tmp_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
                                total_node_blocks += se->valid_blocks;
 
                        /* build discard map only one time */
-                       if (f2fs_discard_en(sbi)) {
-                               if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
-                                       memset(se->discard_map, 0xff,
-                                               SIT_VBLOCK_MAP_SIZE);
-                               } else {
-                                       memcpy(se->discard_map,
-                                               se->cur_valid_map,
-                                               SIT_VBLOCK_MAP_SIZE);
-                                       sbi->discard_blks +=
-                                               sbi->blocks_per_seg -
-                                               se->valid_blocks;
-                               }
+                       if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
+                               memset(se->discard_map, 0xff,
+                                       SIT_VBLOCK_MAP_SIZE);
+                       } else {
+                               memcpy(se->discard_map,
+                                       se->cur_valid_map,
+                                       SIT_VBLOCK_MAP_SIZE);
+                               sbi->discard_blks +=
+                                       sbi->blocks_per_seg -
+                                       se->valid_blocks;
                        }
 
                        if (sbi->segs_per_sec > 1)
                if (IS_NODESEG(se->type))
                        total_node_blocks += se->valid_blocks;
 
-               if (f2fs_discard_en(sbi)) {
-                       if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
-                               memset(se->discard_map, 0xff,
-                                                       SIT_VBLOCK_MAP_SIZE);
-                       } else {
-                               memcpy(se->discard_map, se->cur_valid_map,
-                                                       SIT_VBLOCK_MAP_SIZE);
-                               sbi->discard_blks += old_valid_blocks;
-                               sbi->discard_blks -= se->valid_blocks;
-                       }
+               if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
+                       memset(se->discard_map, 0xff, SIT_VBLOCK_MAP_SIZE);
+               } else {
+                       memcpy(se->discard_map, se->cur_valid_map,
+                                               SIT_VBLOCK_MAP_SIZE);
+                       sbi->discard_blks += old_valid_blocks;
+                       sbi->discard_blks -= se->valid_blocks;
                }
 
                if (sbi->segs_per_sec > 1) {
 
 static int parse_options(struct super_block *sb, char *options)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(sb);
-       struct request_queue *q;
        substring_t args[MAX_OPT_ARGS];
        char *p, *name;
        int arg = 0;
                                return -EINVAL;
                        break;
                case Opt_discard:
-                       q = bdev_get_queue(sb->s_bdev);
-                       if (blk_queue_discard(q)) {
-                               set_opt(sbi, DISCARD);
-                       } else if (!f2fs_sb_has_blkzoned(sb)) {
-                               f2fs_msg(sb, KERN_WARNING,
-                                       "mounting with \"discard\" option, but "
-                                       "the device does not support discard");
-                       }
+                       set_opt(sbi, DISCARD);
                        break;
                case Opt_nodiscard:
                        if (f2fs_sb_has_blkzoned(sb)) {
        /* be sure to wait for any on-going discard commands */
        dropped = f2fs_wait_discard_bios(sbi);
 
-       if (f2fs_discard_en(sbi) && !sbi->discard_blks && !dropped) {
+       if ((f2fs_hw_support_discard(sbi) || f2fs_hw_should_discard(sbi)) &&
+                                       !sbi->discard_blks && !dropped) {
                struct cp_control cpc = {
                        .reason = CP_UMOUNT | CP_TRIMMED,
                };
        set_opt(sbi, NOHEAP);
        sbi->sb->s_flags |= SB_LAZYTIME;
        set_opt(sbi, FLUSH_MERGE);
-       if (blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev)))
-               set_opt(sbi, DISCARD);
+       set_opt(sbi, DISCARD);
        if (f2fs_sb_has_blkzoned(sbi->sb))
                set_opt_mode(sbi, F2FS_MOUNT_LFS);
        else