1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /******************************************************************************* |
3 | * Filename: target_core_hba.c |
4 | * |
5 | * This file contains the TCM HBA Transport related functions. |
6 | * |
7 | * (c) Copyright 2003-2013 Datera, Inc. |
8 | * |
9 | * Nicholas A. Bellinger <nab@kernel.org> |
10 | * |
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> |
18 | #include <linux/in.h> |
19 | #include <linux/module.h> |
20 | #include <net/sock.h> |
21 | #include <net/tcp.h> |
22 | |
23 | #include <target/target_core_base.h> |
24 | #include <target/target_core_backend.h> |
25 | #include <target/target_core_fabric.h> |
26 | |
27 | #include "target_core_internal.h" |
28 | |
29 | static LIST_HEAD(backend_list); |
30 | static DEFINE_MUTEX(backend_mutex); |
31 | |
32 | static u32 hba_id_counter; |
33 | |
34 | static DEFINE_SPINLOCK(hba_lock); |
35 | static LIST_HEAD(hba_list); |
36 | |
37 | |
38 | int transport_backend_register(const struct target_backend_ops *ops) |
39 | { |
40 | struct target_backend *tb, *old; |
41 | |
42 | tb = kzalloc(size: 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(lock: &backend_mutex); |
52 | kfree(objp: tb); |
53 | return -EEXIST; |
54 | } |
55 | } |
56 | target_setup_backend_cits(tb); |
57 | list_add_tail(new: &tb->list, head: &backend_list); |
58 | mutex_unlock(lock: &backend_mutex); |
59 | |
60 | pr_debug("TCM: Registered subsystem plugin: %s struct module: %p\n" , |
61 | ops->name, ops->owner); |
62 | return 0; |
63 | } |
64 | EXPORT_SYMBOL(transport_backend_register); |
65 | |
66 | void target_backend_unregister(const struct target_backend_ops *ops) |
67 | { |
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(entry: &tb->list); |
74 | mutex_unlock(lock: &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(); |
82 | kfree(objp: tb); |
83 | return; |
84 | } |
85 | } |
86 | mutex_unlock(lock: &backend_mutex); |
87 | } |
88 | EXPORT_SYMBOL(target_backend_unregister); |
89 | |
90 | static struct target_backend *core_get_backend(const char *name) |
91 | { |
92 | struct target_backend *tb; |
93 | |
94 | mutex_lock(&backend_mutex); |
95 | list_for_each_entry(tb, &backend_list, list) { |
96 | if (!strcmp(tb->ops->name, name)) |
97 | goto found; |
98 | } |
99 | mutex_unlock(lock: &backend_mutex); |
100 | return NULL; |
101 | found: |
102 | if (tb->ops->owner && !try_module_get(module: tb->ops->owner)) |
103 | tb = NULL; |
104 | mutex_unlock(lock: &backend_mutex); |
105 | return tb; |
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(size: sizeof(*hba), GFP_KERNEL); |
115 | if (!hba) { |
116 | pr_err("Unable to allocate struct se_hba\n" ); |
117 | return ERR_PTR(error: -ENOMEM); |
118 | } |
119 | |
120 | spin_lock_init(&hba->device_lock); |
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 | |
126 | hba->backend = core_get_backend(name: plugin_name); |
127 | if (!hba->backend) { |
128 | ret = -EINVAL; |
129 | goto out_free_hba; |
130 | } |
131 | |
132 | ret = hba->backend->ops->attach_hba(hba, plugin_dep_id); |
133 | if (ret < 0) |
134 | goto out_module_put; |
135 | |
136 | spin_lock(lock: &hba_lock); |
137 | hba->hba_id = hba_id_counter++; |
138 | list_add_tail(new: &hba->hba_node, head: &hba_list); |
139 | spin_unlock(lock: &hba_lock); |
140 | |
141 | pr_debug("CORE_HBA[%d] - Attached HBA to Generic Target" |
142 | " Core\n" , hba->hba_id); |
143 | |
144 | return hba; |
145 | |
146 | out_module_put: |
147 | module_put(module: hba->backend->ops->owner); |
148 | hba->backend = NULL; |
149 | out_free_hba: |
150 | kfree(objp: hba); |
151 | return ERR_PTR(error: ret); |
152 | } |
153 | |
154 | int |
155 | core_delete_hba(struct se_hba *hba) |
156 | { |
157 | WARN_ON(hba->dev_count); |
158 | |
159 | hba->backend->ops->detach_hba(hba); |
160 | |
161 | spin_lock(lock: &hba_lock); |
162 | list_del(entry: &hba->hba_node); |
163 | spin_unlock(lock: &hba_lock); |
164 | |
165 | pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target" |
166 | " Core\n" , hba->hba_id); |
167 | |
168 | module_put(module: hba->backend->ops->owner); |
169 | |
170 | hba->backend = NULL; |
171 | kfree(objp: hba); |
172 | return 0; |
173 | } |
174 | |
175 | bool target_sense_desc_format(struct se_device *dev) |
176 | { |
177 | return (dev) ? dev->transport->get_blocks(dev) > U32_MAX : false; |
178 | } |
179 | |