summaryrefslogtreecommitdiff
path: root/drivers/target/target_core_tpg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/target_core_tpg.c')
-rw-r--r--drivers/target/target_core_tpg.c73
1 files changed, 66 insertions, 7 deletions
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index 736847c933e5..c0e429e5ef31 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -31,6 +31,7 @@
#include "target_core_ua.h"
extern struct se_device *g_lun0_dev;
+static DEFINE_XARRAY_ALLOC(tpg_xa);
/* __core_tpg_get_initiator_node_acl():
*
@@ -328,7 +329,7 @@ static void target_shutdown_sessions(struct se_node_acl *acl)
restart:
spin_lock_irqsave(&acl->nacl_sess_lock, flags);
list_for_each_entry(sess, &acl->acl_sess_list, sess_acl_list) {
- if (atomic_read(&sess->stopped))
+ if (sess->cmd_cnt && atomic_read(&sess->cmd_cnt->stopped))
continue;
list_del_init(&sess->sess_acl_list);
@@ -439,6 +440,68 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref)
complete(&lun->lun_shutdown_comp);
}
+static int target_tpg_register_rtpi(struct se_portal_group *se_tpg)
+{
+ u32 val;
+ int ret;
+
+ if (se_tpg->rtpi_manual) {
+ ret = xa_insert(&tpg_xa, se_tpg->tpg_rtpi, se_tpg, GFP_KERNEL);
+ if (ret) {
+ pr_info("%s_TPG[%hu] - Can not set RTPI %#x, it is already busy",
+ se_tpg->se_tpg_tfo->fabric_name,
+ se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg),
+ se_tpg->tpg_rtpi);
+ return -EINVAL;
+ }
+ } else {
+ ret = xa_alloc(&tpg_xa, &val, se_tpg,
+ XA_LIMIT(1, USHRT_MAX), GFP_KERNEL);
+ if (!ret)
+ se_tpg->tpg_rtpi = val;
+ }
+
+ return ret;
+}
+
+static void target_tpg_deregister_rtpi(struct se_portal_group *se_tpg)
+{
+ if (se_tpg->tpg_rtpi && se_tpg->enabled)
+ xa_erase(&tpg_xa, se_tpg->tpg_rtpi);
+}
+
+int target_tpg_enable(struct se_portal_group *se_tpg)
+{
+ int ret;
+
+ ret = target_tpg_register_rtpi(se_tpg);
+ if (ret)
+ return ret;
+
+ ret = se_tpg->se_tpg_tfo->fabric_enable_tpg(se_tpg, true);
+ if (ret) {
+ target_tpg_deregister_rtpi(se_tpg);
+ return ret;
+ }
+
+ se_tpg->enabled = true;
+
+ return 0;
+}
+
+int target_tpg_disable(struct se_portal_group *se_tpg)
+{
+ int ret;
+
+ target_tpg_deregister_rtpi(se_tpg);
+
+ ret = se_tpg->se_tpg_tfo->fabric_enable_tpg(se_tpg, false);
+ if (!ret)
+ se_tpg->enabled = false;
+
+ return ret;
+}
+
/* Does not change se_wwn->priv. */
int core_tpg_register(
struct se_wwn *se_wwn,
@@ -535,6 +598,8 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head);
}
+ target_tpg_deregister_rtpi(se_tpg);
+
return 0;
}
EXPORT_SYMBOL(core_tpg_deregister);
@@ -578,10 +643,6 @@ int core_tpg_add_lun(
if (ret < 0)
goto out;
- ret = core_alloc_rtpi(lun, dev);
- if (ret)
- goto out_kill_ref;
-
if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) &&
!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp);
@@ -605,8 +666,6 @@ int core_tpg_add_lun(
return 0;
-out_kill_ref:
- percpu_ref_exit(&lun->lun_ref);
out:
return ret;
}