]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_spc.c
target: fix DPO and FUA bit checks
[karo-tx-linux.git] / drivers / target / target_core_spc.c
index 6c8bd6bc175ca48fb9d33063dc3f3b8185d19876..988c158cf65d149e787de81caf02ff829a8c3167 100644 (file)
@@ -103,10 +103,12 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
                buf[5] |= 0x8;
        /*
         * Set Protection (PROTECT) bit when DIF has been enabled on the
-        * device, and the transport supports VERIFY + PASS.
+        * device, and the fabric supports VERIFY + PASS.  Also report
+        * PROTECT=1 if sess_prot_type has been configured to allow T10-PI
+        * to unprotected devices.
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type)
+               if (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)
                        buf[5] |= 0x1;
        }
 
@@ -467,9 +469,11 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
         * only for TYPE3 protection.
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT)
+               if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT ||
+                   cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT)
                        buf[4] = 0x5;
-               else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT)
+               else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT ||
+                       cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT)
                        buf[4] = 0x4;
        }
 
@@ -477,7 +481,7 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
        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);
@@ -861,7 +865,7 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p)
         * TAG field.
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type)
+               if (dev->dev_attrib.pi_prot_type || sess->sess_prot_type)
                        p[5] |= 0x80;
        }
 
@@ -884,7 +888,7 @@ static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p)
        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 */
 
@@ -996,8 +1000,12 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
             (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;
@@ -1099,7 +1107,7 @@ static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd)
        unsigned char *buf;
        unsigned char tbuf[SE_MODE_PAGE_BUF];
        int length;
-       int ret = 0;
+       sense_reason_t ret = 0;
        int i;
 
        if (!cmd->data_length) {