179 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*******************************************************************************3 * Filename: target_core_hba.c4 *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 29static LIST_HEAD(backend_list);30static DEFINE_MUTEX(backend_mutex);31 32static u32 hba_id_counter;33 34static DEFINE_SPINLOCK(hba_lock);35static LIST_HEAD(hba_list);36 37 38int 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);53 return -EEXIST;54 }55 }56 target_setup_backend_cits(tb);57 list_add_tail(&tb->list, &backend_list);58 mutex_unlock(&backend_mutex);59 60 pr_debug("TCM: Registered subsystem plugin: %s struct module: %p\n",61 ops->name, ops->owner);62 return 0;63}64EXPORT_SYMBOL(transport_backend_register);65 66void 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(&tb->list);74 mutex_unlock(&backend_mutex);75 /*76 * Wait for any outstanding backend driver ->rcu_head77 * callbacks to complete post TBO->free_device() ->78 * call_rcu(), before allowing backend driver module79 * unload of target_backend_ops->owner to proceed.80 */81 rcu_barrier();82 kfree(tb);83 return;84 }85 }86 mutex_unlock(&backend_mutex);87}88EXPORT_SYMBOL(target_backend_unregister);89 90static 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(&backend_mutex);100 return NULL;101found:102 if (tb->ops->owner && !try_module_get(tb->ops->owner))103 tb = NULL;104 mutex_unlock(&backend_mutex);105 return tb;106}107 108struct se_hba *109core_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) {116 pr_err("Unable to allocate struct se_hba\n");117 return ERR_PTR(-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(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(&hba_lock);137 hba->hba_id = hba_id_counter++;138 list_add_tail(&hba->hba_node, &hba_list);139 spin_unlock(&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 146out_module_put:147 module_put(hba->backend->ops->owner);148 hba->backend = NULL;149out_free_hba:150 kfree(hba);151 return ERR_PTR(ret);152}153 154int155core_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(&hba_lock);162 list_del(&hba->hba_node);163 spin_unlock(&hba_lock);164 165 pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target"166 " Core\n", hba->hba_id);167 168 module_put(hba->backend->ops->owner);169 170 hba->backend = NULL;171 kfree(hba);172 return 0;173}174 175bool target_sense_desc_format(struct se_device *dev)176{177 return (dev) ? dev->transport->get_blocks(dev) > U32_MAX : false;178}179