]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_pr.c
[media] ad9389b: no monitor if EDID is wrong
[karo-tx-linux.git] / drivers / target / target_core_pr.c
index 26c1f2d8920f36fc71fccb233f7de47636717ce4..bd78faf67c6b366657d572b8e8d1461af77abfec 100644 (file)
@@ -606,13 +606,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
                return NULL;
        }
 
-       pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_ATOMIC);
-       if (!pr_reg->pr_aptpl_buf) {
-               pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n");
-               kmem_cache_free(t10_pr_reg_cache, pr_reg);
-               return NULL;
-       }
-
        INIT_LIST_HEAD(&pr_reg->pr_reg_list);
        INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list);
        INIT_LIST_HEAD(&pr_reg->pr_reg_aptpl_list);
@@ -803,7 +796,6 @@ int core_scsi3_alloc_aptpl_registration(
                pr_err("Unable to allocate struct t10_pr_registration\n");
                return -ENOMEM;
        }
-       pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
 
        INIT_LIST_HEAD(&pr_reg->pr_reg_list);
        INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list);
@@ -1272,7 +1264,6 @@ static void __core_scsi3_free_registration(
        if (!preempt_and_abort_list) {
                pr_reg->pr_reg_deve = NULL;
                pr_reg->pr_reg_nacl = NULL;
-               kfree(pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, pr_reg);
                return;
        }
@@ -1341,7 +1332,6 @@ void core_scsi3_free_all_registrations(
        list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->aptpl_reg_list,
                                pr_reg_aptpl_list) {
                list_del(&pr_reg->pr_reg_aptpl_list);
-               kfree(pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, pr_reg);
        }
        spin_unlock(&pr_tmpl->aptpl_reg_lock);
@@ -1814,7 +1804,6 @@ out:
                        kmem_cache_free(t10_pr_reg_cache, pr_reg_tmp);
                }
 
-               kfree(dest_pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
 
                if (dest_local_nexus)
@@ -1840,8 +1829,6 @@ static int core_scsi3_update_aptpl_buf(
        int reg_count = 0;
        int ret = 0;
 
-       memset(buf, 0, pr_aptpl_buf_len);
-
        spin_lock(&dev->dev_reservation_lock);
        spin_lock(&dev->t10_pr.registration_lock);
        /*
@@ -1927,9 +1914,6 @@ out:
        return ret;
 }
 
-/*
- * Called with struct se_device->aptpl_file_mutex held
- */
 static int __core_scsi3_write_aptpl_to_file(
        struct se_device *dev,
        unsigned char *buf)
@@ -1968,49 +1952,64 @@ static int __core_scsi3_write_aptpl_to_file(
        return ret ? -EIO : 0;
 }
 
-static int
-core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf,
-               u32 in_pr_aptpl_buf_len)
+/*
+ * Clear the APTPL metadata if APTPL has been disabled, otherwise
+ * write out the updated metadata to struct file for this SCSI device.
+ */
+static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
 {
-       unsigned char null_buf[64], *buf;
-       int ret;
+       unsigned char *buf;
+       int rc;
 
-       /*
-        * Can be called with a NULL pointer from PROUT service action CLEAR
-        */
-       if (!in_buf) {
-               snprintf(null_buf, 64, "No Registrations or Reservations\n");
-               buf = null_buf;
-       } else {
-               ret = core_scsi3_update_aptpl_buf(dev, in_buf, in_pr_aptpl_buf_len);
-               if (ret != 0)
-                       return ret;
-               buf = in_buf;
+       if (!aptpl) {
+               char *null_buf = "No Registrations or Reservations\n";
+
+               rc = __core_scsi3_write_aptpl_to_file(dev, null_buf);
+               dev->t10_pr.pr_aptpl_active = 0;
+               pr_debug("SPC-3 PR: Set APTPL Bit Deactivated\n");
+
+               if (rc)
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+               return 0;
        }
 
-       /*
-        * __core_scsi3_write_aptpl_to_file() will call strlen()
-        * on the passed buf to determine pr_aptpl_buf_len.
-        */
-       return __core_scsi3_write_aptpl_to_file(dev, buf);
+       buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
+       if (!buf)
+               return TCM_OUT_OF_RESOURCES;
+
+       rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN);
+       if (rc < 0) {
+               kfree(buf);
+               return TCM_OUT_OF_RESOURCES;
+       }
+
+       rc = __core_scsi3_write_aptpl_to_file(dev, buf);
+       if (rc != 0) {
+               pr_err("SPC-3 PR: Could not update APTPL\n");
+               kfree(buf);
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       }
+       dev->t10_pr.pr_aptpl_active = 1;
+       kfree(buf);
+       pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
+       return 0;
 }
 
 static sense_reason_t
 core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
-               int aptpl, int all_tg_pt, int spec_i_pt, enum register_type register_type)
+               bool aptpl, bool all_tg_pt, bool spec_i_pt, enum register_type register_type)
 {
        struct se_session *se_sess = cmd->se_sess;
        struct se_device *dev = cmd->se_dev;
        struct se_dev_entry *se_deve;
        struct se_lun *se_lun = cmd->se_lun;
        struct se_portal_group *se_tpg;
-       struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e;
+       struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
-       /* Used for APTPL metadata w/ UNREGISTER */
-       unsigned char *pr_aptpl_buf = NULL;
        unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
        sense_reason_t ret = TCM_NO_SENSE;
-       int pr_holder = 0, type;
+       int pr_holder = 0;
 
        if (!se_sess || !se_lun) {
                pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
@@ -2028,8 +2027,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
        /*
         * Follow logic from spc4r17 Section 5.7.7, Register Behaviors Table 47
         */
-       pr_reg_e = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess);
-       if (!pr_reg_e) {
+       pr_reg = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess);
+       if (!pr_reg) {
                if (res_key) {
                        pr_warn("SPC-3 PR: Reservation Key non-zero"
                                " for SA REGISTER, returning CONFLICT\n");
@@ -2069,56 +2068,27 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                        if (ret != 0)
                                return ret;
                }
-               /*
-                * Nothing left to do for the APTPL=0 case.
-                */
-               if (!aptpl) {
-                       pr_tmpl->pr_aptpl_active = 0;
-                       core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
-                       pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for"
-                                       " REGISTER\n");
-                       return 0;
-               }
-               /*
-                * Locate the newly allocated local I_T Nexus *pr_reg, and
-                * update the APTPL metadata information using its
-                * preallocated *pr_reg->pr_aptpl_buf.
-                */
-               pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev,
-                               se_sess->se_node_acl, se_sess);
 
-               if (core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                       pr_tmpl->pr_aptpl_active = 1;
-                       pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n");
-               }
-
-               goto out_put_pr_reg;
+               return core_scsi3_update_and_write_aptpl(dev, aptpl);
        }
 
-       /*
-        * Locate the existing *pr_reg via struct se_node_acl pointers
-        */
-       pr_reg = pr_reg_e;
-       type = pr_reg->pr_res_type;
-
-       if (register_type == REGISTER) {
-               if (res_key != pr_reg->pr_res_key) {
-                       pr_err("SPC-3 PR REGISTER: Received"
-                               " res_key: 0x%016Lx does not match"
-                               " existing SA REGISTER res_key:"
-                               " 0x%016Lx\n", res_key,
-                               pr_reg->pr_res_key);
-                       ret = TCM_RESERVATION_CONFLICT;
-                       goto out_put_pr_reg;
-               }
+       /* ok, existing registration */
+
+       if ((register_type == REGISTER) && (res_key != pr_reg->pr_res_key)) {
+               pr_err("SPC-3 PR REGISTER: Received"
+                      " res_key: 0x%016Lx does not match"
+                      " existing SA REGISTER res_key:"
+                      " 0x%016Lx\n", res_key,
+                      pr_reg->pr_res_key);
+               ret = TCM_RESERVATION_CONFLICT;
+               goto out;
        }
 
        if (spec_i_pt) {
                pr_err("SPC-3 PR REGISTER: SPEC_I_PT"
                        " set on a registered nexus\n");
                ret = TCM_INVALID_PARAMETER_LIST;
-               goto out_put_pr_reg;
+               goto out;
        }
 
        /*
@@ -2130,34 +2100,36 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                        " registration exists, but ALL_TG_PT=1 bit not"
                        " present in received PROUT\n");
                ret = TCM_INVALID_CDB_FIELD;
-               goto out_put_pr_reg;
+               goto out;
        }
 
        /*
-        * Allocate APTPL metadata buffer used for UNREGISTER ops
+        * sa_res_key=1 Change Reservation Key for registered I_T Nexus.
         */
-       if (aptpl) {
-               pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
-               if (!pr_aptpl_buf) {
-                       pr_err("Unable to allocate"
-                               " pr_aptpl_buf\n");
-                       ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-                       goto out_put_pr_reg;
-               }
-       }
+       if (sa_res_key) {
+               /*
+                * Increment PRgeneration counter for struct se_device"
+                * upon a successful REGISTER, see spc4r17 section 6.3.2
+                * READ_KEYS service action.
+                */
+               pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev);
+               pr_reg->pr_res_key = sa_res_key;
+               pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
+                        " Key for %s to: 0x%016Lx PRgeneration:"
+                        " 0x%08x\n", cmd->se_tfo->get_fabric_name(),
+                        (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "",
+                        pr_reg->pr_reg_nacl->initiatorname,
+                        pr_reg->pr_res_key, pr_reg->pr_res_generation);
 
-       /*
-        * sa_res_key=0 Unregister Reservation Key for registered I_T
-        * Nexus sa_res_key=1 Change Reservation Key for registered I_T
-        * Nexus.
-        */
-       if (!sa_res_key) {
+       } else {
+               /*
+                * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus.
+                */
                pr_holder = core_scsi3_check_implict_release(
                                cmd->se_dev, pr_reg);
                if (pr_holder < 0) {
-                       kfree(pr_aptpl_buf);
                        ret = TCM_RESERVATION_CONFLICT;
-                       goto out_put_pr_reg;
+                       goto out;
                }
 
                spin_lock(&pr_tmpl->registration_lock);
@@ -2202,8 +2174,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                 * RESERVATIONS RELEASED.
                 */
                if (pr_holder &&
-                  (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
-                   type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
+                   (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
+                    pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
                        list_for_each_entry(pr_reg_p,
                                        &pr_tmpl->registration_list,
                                        pr_reg_list) {
@@ -2215,58 +2187,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                                        ASCQ_2AH_RESERVATIONS_RELEASED);
                        }
                }
-               spin_unlock(&pr_tmpl->registration_lock);
-
-               if (!aptpl) {
-                       pr_tmpl->pr_aptpl_active = 0;
-                       core_scsi3_update_and_write_aptpl(dev, NULL, 0);
-                       pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
-                                       " for UNREGISTER\n");
-                       return 0;
-               }
-
-               if (!core_scsi3_update_and_write_aptpl(dev, pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                       pr_tmpl->pr_aptpl_active = 1;
-                       pr_debug("SPC-3 PR: Set APTPL Bit Activated"
-                                       " for UNREGISTER\n");
-               }
-
-               goto out_free_aptpl_buf;
-       }
-
-       /*
-        * Increment PRgeneration counter for struct se_device"
-        * upon a successful REGISTER, see spc4r17 section 6.3.2
-        * READ_KEYS service action.
-        */
-       pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev);
-       pr_reg->pr_res_key = sa_res_key;
-       pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
-               " Key for %s to: 0x%016Lx PRgeneration:"
-               " 0x%08x\n", cmd->se_tfo->get_fabric_name(),
-               (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "",
-               pr_reg->pr_reg_nacl->initiatorname,
-               pr_reg->pr_res_key, pr_reg->pr_res_generation);
 
-       if (!aptpl) {
-               pr_tmpl->pr_aptpl_active = 0;
-               core_scsi3_update_and_write_aptpl(dev, NULL, 0);
-               pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
-                               " for REGISTER\n");
-               ret = 0;
-               goto out_put_pr_reg;
+               spin_unlock(&pr_tmpl->registration_lock);
        }
 
-       if (!core_scsi3_update_and_write_aptpl(dev, pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-               pr_tmpl->pr_aptpl_active = 1;
-               pr_debug("SPC-3 PR: Set APTPL Bit Activated"
-                       " for REGISTER\n");
-       }
+       ret = core_scsi3_update_and_write_aptpl(dev, aptpl);
 
-out_free_aptpl_buf:
-       kfree(pr_aptpl_buf);
-       ret = 0;
-out_put_pr_reg:
+out:
        core_scsi3_put_pr_reg(pr_reg);
        return ret;
 }
@@ -2440,13 +2367,8 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
                        i_buf);
        spin_unlock(&dev->dev_reservation_lock);
 
-       if (pr_tmpl->pr_aptpl_active) {
-               if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                       pr_debug("SPC-3 PR: Updated APTPL metadata"
-                                       " for RESERVE\n");
-               }
-       }
+       if (pr_tmpl->pr_aptpl_active)
+               core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
 
        ret = 0;
 out_put_pr_reg:
@@ -2660,12 +2582,9 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
        spin_unlock(&pr_tmpl->registration_lock);
 
 write_aptpl:
-       if (pr_tmpl->pr_aptpl_active) {
-               if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                       pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                       pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n");
-               }
-       }
+       if (pr_tmpl->pr_aptpl_active)
+               core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
+
 out_put_pr_reg:
        core_scsi3_put_pr_reg(pr_reg);
        return ret;
@@ -2749,11 +2668,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
        pr_debug("SPC-3 PR [%s] Service Action: CLEAR complete\n",
                cmd->se_tfo->get_fabric_name());
 
-       if (pr_tmpl->pr_aptpl_active) {
-               core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
-               pr_debug("SPC-3 PR: Updated APTPL metadata"
-                               " for CLEAR\n");
-       }
+       core_scsi3_update_and_write_aptpl(cmd->se_dev, false);
 
        core_scsi3_pr_generation(dev);
        return 0;
@@ -2825,7 +2740,6 @@ static void core_scsi3_release_preempt_and_abort(
 
                pr_reg->pr_reg_deve = NULL;
                pr_reg->pr_reg_nacl = NULL;
-               kfree(pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, pr_reg);
        }
 }
@@ -2987,14 +2901,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                }
                spin_unlock(&dev->dev_reservation_lock);
 
-               if (pr_tmpl->pr_aptpl_active) {
-                       if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                                       pr_reg_n->pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                               pr_debug("SPC-3 PR: Updated APTPL"
-                                       " metadata for  PREEMPT%s\n", (preempt_type == PREEMPT_AND_ABORT) ?
-                                       "_AND_ABORT" : "");
-                       }
-               }
+               if (pr_tmpl->pr_aptpl_active)
+                       core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
 
                core_scsi3_put_pr_reg(pr_reg_n);
                core_scsi3_pr_generation(cmd->se_dev);
@@ -3122,13 +3030,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                                                pr_reg_n);
        }
 
-       if (pr_tmpl->pr_aptpl_active) {
-               if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               pr_reg_n->pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                       pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
-                               "%s\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "");
-               }
-       }
+       if (pr_tmpl->pr_aptpl_active)
+               core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
 
        core_scsi3_put_pr_reg(pr_reg_n);
        core_scsi3_pr_generation(cmd->se_dev);
@@ -3555,23 +3458,7 @@ after_iport_check:
        } else
                core_scsi3_put_pr_reg(pr_reg);
 
-       /*
-        * Clear the APTPL metadata if APTPL has been disabled, otherwise
-        * write out the updated metadata to struct file for this SCSI device.
-        */
-       if (!aptpl) {
-               pr_tmpl->pr_aptpl_active = 0;
-               core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
-               pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for"
-                               " REGISTER_AND_MOVE\n");
-       } else {
-               pr_tmpl->pr_aptpl_active = 1;
-               if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               dest_pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) {
-                       pr_debug("SPC-3 PR: Set APTPL Bit Activated for"
-                                       " REGISTER_AND_MOVE\n");
-               }
-       }
+       core_scsi3_update_and_write_aptpl(cmd->se_dev, aptpl);
 
        transport_kunmap_data_sg(cmd);