Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / target / tcm_remote / tcm_remote.c
blobcb8db2558056f67e5c2031c643136256dbfe2d7f
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include <linux/module.h>
4 #include <linux/moduleparam.h>
5 #include <linux/init.h>
6 #include <linux/slab.h>
7 #include <linux/types.h>
8 #include <linux/configfs.h>
9 #include <scsi/scsi.h>
10 #include <scsi/scsi_tcq.h>
11 #include <scsi/scsi_host.h>
12 #include <scsi/scsi_device.h>
13 #include <scsi/scsi_cmnd.h>
15 #include <target/target_core_base.h>
16 #include <target/target_core_fabric.h>
18 #include "tcm_remote.h"
20 static inline struct tcm_remote_tpg *remote_tpg(struct se_portal_group *se_tpg)
22 return container_of(se_tpg, struct tcm_remote_tpg, remote_se_tpg);
25 static char *tcm_remote_get_endpoint_wwn(struct se_portal_group *se_tpg)
28 * Return the passed NAA identifier for the Target Port
30 return &remote_tpg(se_tpg)->remote_hba->remote_wwn_address[0];
33 static u16 tcm_remote_get_tag(struct se_portal_group *se_tpg)
36 * This Tag is used when forming SCSI Name identifier in EVPD=1 0x83
37 * to represent the SCSI Target Port.
39 return remote_tpg(se_tpg)->remote_tpgt;
42 static int tcm_remote_dummy_cmd_fn(struct se_cmd *se_cmd)
44 return 0;
47 static void tcm_remote_dummy_cmd_void_fn(struct se_cmd *se_cmd)
52 static char *tcm_remote_dump_proto_id(struct tcm_remote_hba *remote_hba)
54 switch (remote_hba->remote_proto_id) {
55 case SCSI_PROTOCOL_SAS:
56 return "SAS";
57 case SCSI_PROTOCOL_SRP:
58 return "SRP";
59 case SCSI_PROTOCOL_FCP:
60 return "FCP";
61 case SCSI_PROTOCOL_ISCSI:
62 return "iSCSI";
63 default:
64 break;
67 return "Unknown";
70 static int tcm_remote_port_link(
71 struct se_portal_group *se_tpg,
72 struct se_lun *lun)
74 pr_debug("TCM_Remote_ConfigFS: Port Link LUN %lld Successful\n",
75 lun->unpacked_lun);
76 return 0;
79 static void tcm_remote_port_unlink(
80 struct se_portal_group *se_tpg,
81 struct se_lun *lun)
83 pr_debug("TCM_Remote_ConfigFS: Port Unlink LUN %lld Successful\n",
84 lun->unpacked_lun);
87 static struct se_portal_group *tcm_remote_make_tpg(
88 struct se_wwn *wwn,
89 const char *name)
91 struct tcm_remote_hba *remote_hba = container_of(wwn,
92 struct tcm_remote_hba, remote_hba_wwn);
93 struct tcm_remote_tpg *remote_tpg;
94 unsigned long tpgt;
95 int ret;
97 if (strstr(name, "tpgt_") != name) {
98 pr_err("Unable to locate \"tpgt_#\" directory group\n");
99 return ERR_PTR(-EINVAL);
101 if (kstrtoul(name + 5, 10, &tpgt))
102 return ERR_PTR(-EINVAL);
104 if (tpgt >= TL_TPGS_PER_HBA) {
105 pr_err("Passed tpgt: %lu exceeds TL_TPGS_PER_HBA: %u\n",
106 tpgt, TL_TPGS_PER_HBA);
107 return ERR_PTR(-EINVAL);
109 remote_tpg = &remote_hba->remote_hba_tpgs[tpgt];
110 remote_tpg->remote_hba = remote_hba;
111 remote_tpg->remote_tpgt = tpgt;
113 * Register the remote_tpg as a emulated TCM Target Endpoint
115 ret = core_tpg_register(wwn, &remote_tpg->remote_se_tpg,
116 remote_hba->remote_proto_id);
117 if (ret < 0)
118 return ERR_PTR(-ENOMEM);
120 pr_debug("TCM_Remote_ConfigFS: Allocated Emulated %s Target Port %s,t,0x%04lx\n",
121 tcm_remote_dump_proto_id(remote_hba),
122 config_item_name(&wwn->wwn_group.cg_item), tpgt);
123 return &remote_tpg->remote_se_tpg;
126 static void tcm_remote_drop_tpg(struct se_portal_group *se_tpg)
128 struct se_wwn *wwn = se_tpg->se_tpg_wwn;
129 struct tcm_remote_tpg *remote_tpg = container_of(se_tpg,
130 struct tcm_remote_tpg, remote_se_tpg);
131 struct tcm_remote_hba *remote_hba;
132 unsigned short tpgt;
134 remote_hba = remote_tpg->remote_hba;
135 tpgt = remote_tpg->remote_tpgt;
138 * Deregister the remote_tpg as a emulated TCM Target Endpoint
140 core_tpg_deregister(se_tpg);
142 remote_tpg->remote_hba = NULL;
143 remote_tpg->remote_tpgt = 0;
145 pr_debug("TCM_Remote_ConfigFS: Deallocated Emulated %s Target Port %s,t,0x%04x\n",
146 tcm_remote_dump_proto_id(remote_hba),
147 config_item_name(&wwn->wwn_group.cg_item), tpgt);
150 static struct se_wwn *tcm_remote_make_wwn(
151 struct target_fabric_configfs *tf,
152 struct config_group *group,
153 const char *name)
155 struct tcm_remote_hba *remote_hba;
156 char *ptr;
157 int ret, off = 0;
159 remote_hba = kzalloc(sizeof(*remote_hba), GFP_KERNEL);
160 if (!remote_hba)
161 return ERR_PTR(-ENOMEM);
164 * Determine the emulated Protocol Identifier and Target Port Name
165 * based on the incoming configfs directory name.
167 ptr = strstr(name, "naa.");
168 if (ptr) {
169 remote_hba->remote_proto_id = SCSI_PROTOCOL_SAS;
170 goto check_len;
172 ptr = strstr(name, "fc.");
173 if (ptr) {
174 remote_hba->remote_proto_id = SCSI_PROTOCOL_FCP;
175 off = 3; /* Skip over "fc." */
176 goto check_len;
178 ptr = strstr(name, "0x");
179 if (ptr) {
180 remote_hba->remote_proto_id = SCSI_PROTOCOL_SRP;
181 off = 2; /* Skip over "0x" */
182 goto check_len;
184 ptr = strstr(name, "iqn.");
185 if (!ptr) {
186 pr_err("Unable to locate prefix for emulated Target Port: %s\n",
187 name);
188 ret = -EINVAL;
189 goto out;
191 remote_hba->remote_proto_id = SCSI_PROTOCOL_ISCSI;
193 check_len:
194 if (strlen(name) >= TL_WWN_ADDR_LEN) {
195 pr_err("Emulated NAA %s Address: %s, exceeds max: %d\n",
196 name, tcm_remote_dump_proto_id(remote_hba), TL_WWN_ADDR_LEN);
197 ret = -EINVAL;
198 goto out;
200 snprintf(&remote_hba->remote_wwn_address[0], TL_WWN_ADDR_LEN, "%s", &name[off]);
202 pr_debug("TCM_Remote_ConfigFS: Allocated emulated Target %s Address: %s\n",
203 tcm_remote_dump_proto_id(remote_hba), name);
204 return &remote_hba->remote_hba_wwn;
205 out:
206 kfree(remote_hba);
207 return ERR_PTR(ret);
210 static void tcm_remote_drop_wwn(struct se_wwn *wwn)
212 struct tcm_remote_hba *remote_hba = container_of(wwn,
213 struct tcm_remote_hba, remote_hba_wwn);
215 pr_debug("TCM_Remote_ConfigFS: Deallocating emulated Target %s Address: %s\n",
216 tcm_remote_dump_proto_id(remote_hba),
217 remote_hba->remote_wwn_address);
218 kfree(remote_hba);
221 static ssize_t tcm_remote_wwn_version_show(struct config_item *item, char *page)
223 return sprintf(page, "TCM Remote Fabric module %s\n", TCM_REMOTE_VERSION);
226 CONFIGFS_ATTR_RO(tcm_remote_wwn_, version);
228 static struct configfs_attribute *tcm_remote_wwn_attrs[] = {
229 &tcm_remote_wwn_attr_version,
230 NULL,
233 static const struct target_core_fabric_ops remote_ops = {
234 .module = THIS_MODULE,
235 .fabric_name = "remote",
236 .tpg_get_wwn = tcm_remote_get_endpoint_wwn,
237 .tpg_get_tag = tcm_remote_get_tag,
238 .check_stop_free = tcm_remote_dummy_cmd_fn,
239 .release_cmd = tcm_remote_dummy_cmd_void_fn,
240 .write_pending = tcm_remote_dummy_cmd_fn,
241 .queue_data_in = tcm_remote_dummy_cmd_fn,
242 .queue_status = tcm_remote_dummy_cmd_fn,
243 .queue_tm_rsp = tcm_remote_dummy_cmd_void_fn,
244 .aborted_task = tcm_remote_dummy_cmd_void_fn,
245 .fabric_make_wwn = tcm_remote_make_wwn,
246 .fabric_drop_wwn = tcm_remote_drop_wwn,
247 .fabric_make_tpg = tcm_remote_make_tpg,
248 .fabric_drop_tpg = tcm_remote_drop_tpg,
249 .fabric_post_link = tcm_remote_port_link,
250 .fabric_pre_unlink = tcm_remote_port_unlink,
251 .tfc_wwn_attrs = tcm_remote_wwn_attrs,
254 static int __init tcm_remote_fabric_init(void)
256 return target_register_template(&remote_ops);
259 static void __exit tcm_remote_fabric_exit(void)
261 target_unregister_template(&remote_ops);
264 MODULE_DESCRIPTION("TCM virtual remote target");
265 MODULE_AUTHOR("Dmitry Bogdanov <d.bogdanov@yadro.com>");
266 MODULE_LICENSE("GPL");
267 module_init(tcm_remote_fabric_init);
268 module_exit(tcm_remote_fabric_exit);