int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
 {
-       if (flag != 0 && flag != 1) {
-               pr_err("Illegal value %d\n", flag);
-               return -EINVAL;
-       }
-
-       if (flag) {
-               pr_err("dpo_emulated not supported\n");
-               return -EINVAL;
-       }
-
+       printk_once(KERN_WARNING
+               "ignoring deprecated emulate_dpo attribute\n");
        return 0;
 }
 EXPORT_SYMBOL(se_dev_set_emulate_dpo);
 
 int se_dev_set_emulate_fua_read(struct se_device *dev, int flag)
 {
-       if (flag != 0 && flag != 1) {
-               pr_err("Illegal value %d\n", flag);
-               return -EINVAL;
-       }
-
-       if (flag) {
-               pr_err("ua read emulated not supported\n");
-               return -EINVAL;
-       }
-
+       printk_once(KERN_WARNING
+               "ignoring deprecated emulate_fua_read attribute\n");
        return 0;
 }
 EXPORT_SYMBOL(se_dev_set_emulate_fua_read);
 
        dev->dev_attrib.da_dev = dev;
        dev->dev_attrib.emulate_model_alias = DA_EMULATE_MODEL_ALIAS;
-       dev->dev_attrib.emulate_dpo = DA_EMULATE_DPO;
-       dev->dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE;
-       dev->dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ;
+       dev->dev_attrib.emulate_dpo = 1;
+       dev->dev_attrib.emulate_fua_write = 1;
+       dev->dev_attrib.emulate_fua_read = 1;
        dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE;
        dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL;
        dev->dev_attrib.emulate_tas = DA_EMULATE_TAS;
 
                 * for SCSI WRITEs with Forced Unit Access (FUA) set.
                 * Allow this to happen independent of WCE=0 setting.
                 */
-               if (ret > 0 &&
-                   dev->dev_attrib.emulate_fua_write > 0 &&
-                   (cmd->se_cmd_flags & SCF_FUA)) {
+               if (ret > 0 && (cmd->se_cmd_flags & SCF_FUA)) {
                        loff_t start = cmd->t_task_lba *
                                dev->dev_attrib.block_size;
                        loff_t end;
 
 void   transport_send_task_abort(struct se_cmd *);
 sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
 void   target_qf_do_work(struct work_struct *work);
+bool   target_check_wce(struct se_device *dev);
+bool   target_check_fua(struct se_device *dev);
 
 /* target_core_stat.c */
 void   target_stat_setup_dev_default_groups(struct se_device *);
 
 sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
 {
        if (cdb[1] & 0x10) {
-               if (!dev->dev_attrib.emulate_dpo) {
+               /* see explanation in spc_emulate_modesense */
+               if (!target_check_fua(dev)) {
                        pr_err("Got CDB: 0x%02x with DPO bit set, but device"
                               " does not advertise support for DPO\n", cdb[0]);
                        return -EINVAL;
                }
        }
        if (cdb[1] & 0x8) {
-               if (!dev->dev_attrib.emulate_fua_write || !se_dev_check_wce(dev)) {
+               if (!target_check_fua(dev)) {
                        pr_err("Got CDB: 0x%02x with FUA bit set, but device"
                               " does not advertise support for FUA write\n",
                               cdb[0]);
 
        buf[5] = 0x07;
 
        /* If WriteCache emulation is enabled, set V_SUP */
-       if (se_dev_check_wce(dev))
+       if (target_check_wce(dev))
                buf[6] = 0x01;
        /* If an LBA map is present set R_SUP */
        spin_lock(&cmd->se_dev->t10_alua.lba_map_lock);
        if (pc == 1)
                goto out;
 
-       if (se_dev_check_wce(dev))
+       if (target_check_wce(dev))
                p[2] = 0x04; /* Write Cache Enable */
        p[12] = 0x20; /* Disabled Read Ahead */
 
             (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
                spc_modesense_write_protect(&buf[length], type);
 
-       if ((se_dev_check_wce(dev)) &&
-           (dev->dev_attrib.emulate_fua_write > 0))
+       /*
+        * SBC only allows us to enable FUA and DPO together.  Fortunately
+        * DPO is explicitly specified as a hint, so a noop is a perfectly
+        * valid implementation.
+        */
+       if (target_check_fua(dev))
                spc_modesense_dpofua(&buf[length], type);
 
        ++length;
 
        return 0;
 }
 EXPORT_SYMBOL(transport_generic_handle_tmr);
+
+bool
+target_check_wce(struct se_device *dev)
+{
+       bool wce = false;
+
+       if (dev->transport->get_write_cache)
+               wce = dev->transport->get_write_cache(dev);
+       else if (dev->dev_attrib.emulate_write_cache > 0)
+               wce = true;
+
+       return wce;
+}
+
+bool
+target_check_fua(struct se_device *dev)
+{
+       return target_check_wce(dev) && dev->dev_attrib.emulate_fua_write > 0;
+}
 
 #define DA_MAX_WRITE_SAME_LEN                  0
 /* Use a model alias based on the configfs backend device name */
 #define DA_EMULATE_MODEL_ALIAS                 0
-/* Emulation for Direct Page Out */
-#define DA_EMULATE_DPO                         0
-/* Emulation for Forced Unit Access WRITEs */
-#define DA_EMULATE_FUA_WRITE                   1
-/* Emulation for Forced Unit Access READs */
-#define DA_EMULATE_FUA_READ                    0
 /* Emulation for WriteCache and SYNCHRONIZE_CACHE */
 #define DA_EMULATE_WRITE_CACHE                 0
 /* Emulation for UNIT ATTENTION Interlock Control */