Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.38-rc1 185 lines 5.0 kB view raw
1/******************************************************************************* 2 * Filename: target_core_hba.c 3 * 4 * This file copntains the iSCSI HBA Transport related functions. 5 * 6 * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc. 7 * Copyright (c) 2005, 2006, 2007 SBE, Inc. 8 * Copyright (c) 2007-2010 Rising Tide Systems 9 * Copyright (c) 2008-2010 Linux-iSCSI.org 10 * 11 * Nicholas A. Bellinger <nab@kernel.org> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 26 * 27 ******************************************************************************/ 28 29#include <linux/net.h> 30#include <linux/string.h> 31#include <linux/timer.h> 32#include <linux/slab.h> 33#include <linux/spinlock.h> 34#include <linux/smp_lock.h> 35#include <linux/in.h> 36#include <net/sock.h> 37#include <net/tcp.h> 38 39#include <target/target_core_base.h> 40#include <target/target_core_device.h> 41#include <target/target_core_device.h> 42#include <target/target_core_tpg.h> 43#include <target/target_core_transport.h> 44 45#include "target_core_hba.h" 46 47static LIST_HEAD(subsystem_list); 48static DEFINE_MUTEX(subsystem_mutex); 49 50int transport_subsystem_register(struct se_subsystem_api *sub_api) 51{ 52 struct se_subsystem_api *s; 53 54 INIT_LIST_HEAD(&sub_api->sub_api_list); 55 56 mutex_lock(&subsystem_mutex); 57 list_for_each_entry(s, &subsystem_list, sub_api_list) { 58 if (!(strcmp(s->name, sub_api->name))) { 59 printk(KERN_ERR "%p is already registered with" 60 " duplicate name %s, unable to process" 61 " request\n", s, s->name); 62 mutex_unlock(&subsystem_mutex); 63 return -EEXIST; 64 } 65 } 66 list_add_tail(&sub_api->sub_api_list, &subsystem_list); 67 mutex_unlock(&subsystem_mutex); 68 69 printk(KERN_INFO "TCM: Registered subsystem plugin: %s struct module:" 70 " %p\n", sub_api->name, sub_api->owner); 71 return 0; 72} 73EXPORT_SYMBOL(transport_subsystem_register); 74 75void transport_subsystem_release(struct se_subsystem_api *sub_api) 76{ 77 mutex_lock(&subsystem_mutex); 78 list_del(&sub_api->sub_api_list); 79 mutex_unlock(&subsystem_mutex); 80} 81EXPORT_SYMBOL(transport_subsystem_release); 82 83static struct se_subsystem_api *core_get_backend(const char *sub_name) 84{ 85 struct se_subsystem_api *s; 86 87 mutex_lock(&subsystem_mutex); 88 list_for_each_entry(s, &subsystem_list, sub_api_list) { 89 if (!strcmp(s->name, sub_name)) 90 goto found; 91 } 92 mutex_unlock(&subsystem_mutex); 93 return NULL; 94found: 95 if (s->owner && !try_module_get(s->owner)) 96 s = NULL; 97 mutex_unlock(&subsystem_mutex); 98 return s; 99} 100 101struct se_hba * 102core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags) 103{ 104 struct se_hba *hba; 105 int ret = 0; 106 107 hba = kzalloc(sizeof(*hba), GFP_KERNEL); 108 if (!hba) { 109 printk(KERN_ERR "Unable to allocate struct se_hba\n"); 110 return ERR_PTR(-ENOMEM); 111 } 112 113 INIT_LIST_HEAD(&hba->hba_dev_list); 114 spin_lock_init(&hba->device_lock); 115 spin_lock_init(&hba->hba_queue_lock); 116 mutex_init(&hba->hba_access_mutex); 117 118 hba->hba_index = scsi_get_new_index(SCSI_INST_INDEX); 119 hba->hba_flags |= hba_flags; 120 121 atomic_set(&hba->max_queue_depth, 0); 122 atomic_set(&hba->left_queue_depth, 0); 123 124 hba->transport = core_get_backend(plugin_name); 125 if (!hba->transport) { 126 ret = -EINVAL; 127 goto out_free_hba; 128 } 129 130 ret = hba->transport->attach_hba(hba, plugin_dep_id); 131 if (ret < 0) 132 goto out_module_put; 133 134 spin_lock(&se_global->hba_lock); 135 hba->hba_id = se_global->g_hba_id_counter++; 136 list_add_tail(&hba->hba_list, &se_global->g_hba_list); 137 spin_unlock(&se_global->hba_lock); 138 139 printk(KERN_INFO "CORE_HBA[%d] - Attached HBA to Generic Target" 140 " Core\n", hba->hba_id); 141 142 return hba; 143 144out_module_put: 145 if (hba->transport->owner) 146 module_put(hba->transport->owner); 147 hba->transport = NULL; 148out_free_hba: 149 kfree(hba); 150 return ERR_PTR(ret); 151} 152 153int 154core_delete_hba(struct se_hba *hba) 155{ 156 struct se_device *dev, *dev_tmp; 157 158 spin_lock(&hba->device_lock); 159 list_for_each_entry_safe(dev, dev_tmp, &hba->hba_dev_list, dev_list) { 160 161 se_clear_dev_ports(dev); 162 spin_unlock(&hba->device_lock); 163 164 se_release_device_for_hba(dev); 165 166 spin_lock(&hba->device_lock); 167 } 168 spin_unlock(&hba->device_lock); 169 170 hba->transport->detach_hba(hba); 171 172 spin_lock(&se_global->hba_lock); 173 list_del(&hba->hba_list); 174 spin_unlock(&se_global->hba_lock); 175 176 printk(KERN_INFO "CORE_HBA[%d] - Detached HBA from Generic Target" 177 " Core\n", hba->hba_id); 178 179 if (hba->transport->owner) 180 module_put(hba->transport->owner); 181 182 hba->transport = NULL; 183 kfree(hba); 184 return 0; 185}