Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
c66ac9db NB |
2 | /******************************************************************************* |
3 | * Filename: target_core_hba.c | |
4 | * | |
e3d6f909 | 5 | * This file contains the TCM HBA Transport related functions. |
c66ac9db | 6 | * |
4c76251e | 7 | * (c) Copyright 2003-2013 Datera, Inc. |
c66ac9db NB |
8 | * |
9 | * Nicholas A. Bellinger <nab@kernel.org> | |
10 | * | |
c66ac9db NB |
11 | ******************************************************************************/ |
12 | ||
13 | #include <linux/net.h> | |
14 | #include <linux/string.h> | |
15 | #include <linux/timer.h> | |
16 | #include <linux/slab.h> | |
17 | #include <linux/spinlock.h> | |
c66ac9db | 18 | #include <linux/in.h> |
827509e3 | 19 | #include <linux/module.h> |
c66ac9db NB |
20 | #include <net/sock.h> |
21 | #include <net/tcp.h> | |
22 | ||
23 | #include <target/target_core_base.h> | |
c4795fb2 CH |
24 | #include <target/target_core_backend.h> |
25 | #include <target/target_core_fabric.h> | |
c66ac9db | 26 | |
e26d99ae | 27 | #include "target_core_internal.h" |
c66ac9db | 28 | |
0a06d430 CH |
29 | static LIST_HEAD(backend_list); |
30 | static DEFINE_MUTEX(backend_mutex); | |
c66ac9db | 31 | |
e3d6f909 AG |
32 | static u32 hba_id_counter; |
33 | ||
34 | static DEFINE_SPINLOCK(hba_lock); | |
35 | static LIST_HEAD(hba_list); | |
36 | ||
c66ac9db | 37 | |
0a06d430 CH |
38 | int transport_backend_register(const struct target_backend_ops *ops) |
39 | { | |
40 | struct target_backend *tb, *old; | |
41 | ||
42 | tb = kzalloc(sizeof(*tb), GFP_KERNEL); | |
43 | if (!tb) | |
44 | return -ENOMEM; | |
45 | tb->ops = ops; | |
46 | ||
47 | mutex_lock(&backend_mutex); | |
48 | list_for_each_entry(old, &backend_list, list) { | |
49 | if (!strcmp(old->ops->name, ops->name)) { | |
50 | pr_err("backend %s already registered.\n", ops->name); | |
51 | mutex_unlock(&backend_mutex); | |
52 | kfree(tb); | |
c66ac9db NB |
53 | return -EEXIST; |
54 | } | |
55 | } | |
0a06d430 CH |
56 | target_setup_backend_cits(tb); |
57 | list_add_tail(&tb->list, &backend_list); | |
58 | mutex_unlock(&backend_mutex); | |
c66ac9db | 59 | |
0a06d430 CH |
60 | pr_debug("TCM: Registered subsystem plugin: %s struct module: %p\n", |
61 | ops->name, ops->owner); | |
c66ac9db NB |
62 | return 0; |
63 | } | |
0a06d430 | 64 | EXPORT_SYMBOL(transport_backend_register); |
c66ac9db | 65 | |
0a06d430 | 66 | void target_backend_unregister(const struct target_backend_ops *ops) |
c66ac9db | 67 | { |
0a06d430 CH |
68 | struct target_backend *tb; |
69 | ||
70 | mutex_lock(&backend_mutex); | |
71 | list_for_each_entry(tb, &backend_list, list) { | |
72 | if (tb->ops == ops) { | |
73 | list_del(&tb->list); | |
94509182 NB |
74 | mutex_unlock(&backend_mutex); |
75 | /* | |
76 | * Wait for any outstanding backend driver ->rcu_head | |
77 | * callbacks to complete post TBO->free_device() -> | |
78 | * call_rcu(), before allowing backend driver module | |
79 | * unload of target_backend_ops->owner to proceed. | |
80 | */ | |
81 | rcu_barrier(); | |
0a06d430 | 82 | kfree(tb); |
94509182 | 83 | return; |
0a06d430 CH |
84 | } |
85 | } | |
86 | mutex_unlock(&backend_mutex); | |
c66ac9db | 87 | } |
0a06d430 | 88 | EXPORT_SYMBOL(target_backend_unregister); |
c66ac9db | 89 | |
0a06d430 | 90 | static struct target_backend *core_get_backend(const char *name) |
c66ac9db | 91 | { |
0a06d430 | 92 | struct target_backend *tb; |
c66ac9db | 93 | |
0a06d430 CH |
94 | mutex_lock(&backend_mutex); |
95 | list_for_each_entry(tb, &backend_list, list) { | |
96 | if (!strcmp(tb->ops->name, name)) | |
c66ac9db NB |
97 | goto found; |
98 | } | |
0a06d430 | 99 | mutex_unlock(&backend_mutex); |
c66ac9db NB |
100 | return NULL; |
101 | found: | |
0a06d430 CH |
102 | if (tb->ops->owner && !try_module_get(tb->ops->owner)) |
103 | tb = NULL; | |
104 | mutex_unlock(&backend_mutex); | |
105 | return tb; | |
c66ac9db NB |
106 | } |
107 | ||
108 | struct se_hba * | |
109 | core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags) | |
110 | { | |
111 | struct se_hba *hba; | |
112 | int ret = 0; | |
113 | ||
114 | hba = kzalloc(sizeof(*hba), GFP_KERNEL); | |
115 | if (!hba) { | |
6708bb27 | 116 | pr_err("Unable to allocate struct se_hba\n"); |
c66ac9db NB |
117 | return ERR_PTR(-ENOMEM); |
118 | } | |
119 | ||
c66ac9db | 120 | spin_lock_init(&hba->device_lock); |
c66ac9db NB |
121 | mutex_init(&hba->hba_access_mutex); |
122 | ||
123 | hba->hba_index = scsi_get_new_index(SCSI_INST_INDEX); | |
124 | hba->hba_flags |= hba_flags; | |
125 | ||
0a06d430 CH |
126 | hba->backend = core_get_backend(plugin_name); |
127 | if (!hba->backend) { | |
c66ac9db NB |
128 | ret = -EINVAL; |
129 | goto out_free_hba; | |
130 | } | |
131 | ||
0a06d430 | 132 | ret = hba->backend->ops->attach_hba(hba, plugin_dep_id); |
c66ac9db NB |
133 | if (ret < 0) |
134 | goto out_module_put; | |
135 | ||
e3d6f909 AG |
136 | spin_lock(&hba_lock); |
137 | hba->hba_id = hba_id_counter++; | |
138 | list_add_tail(&hba->hba_node, &hba_list); | |
139 | spin_unlock(&hba_lock); | |
c66ac9db | 140 | |
6708bb27 | 141 | pr_debug("CORE_HBA[%d] - Attached HBA to Generic Target" |
c66ac9db NB |
142 | " Core\n", hba->hba_id); |
143 | ||
144 | return hba; | |
145 | ||
146 | out_module_put: | |
0a06d430 CH |
147 | module_put(hba->backend->ops->owner); |
148 | hba->backend = NULL; | |
c66ac9db NB |
149 | out_free_hba: |
150 | kfree(hba); | |
151 | return ERR_PTR(ret); | |
152 | } | |
153 | ||
154 | int | |
155 | core_delete_hba(struct se_hba *hba) | |
156 | { | |
0fd97ccf | 157 | WARN_ON(hba->dev_count); |
c66ac9db | 158 | |
0a06d430 | 159 | hba->backend->ops->detach_hba(hba); |
c66ac9db | 160 | |
e3d6f909 AG |
161 | spin_lock(&hba_lock); |
162 | list_del(&hba->hba_node); | |
163 | spin_unlock(&hba_lock); | |
c66ac9db | 164 | |
6708bb27 | 165 | pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target" |
c66ac9db NB |
166 | " Core\n", hba->hba_id); |
167 | ||
0a06d430 | 168 | module_put(hba->backend->ops->owner); |
c66ac9db | 169 | |
0a06d430 | 170 | hba->backend = NULL; |
c66ac9db NB |
171 | kfree(hba); |
172 | return 0; | |
173 | } | |
4e4937e8 SG |
174 | |
175 | bool target_sense_desc_format(struct se_device *dev) | |
176 | { | |
f3bb467f | 177 | return (dev) ? dev->transport->get_blocks(dev) > U32_MAX : false; |
4e4937e8 | 178 | } |