13699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 23699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Copyright (c) 2010 Cisco Systems, Inc. 33699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * 43699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * This program is free software; you can redistribute it and/or modify it 53699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * under the terms and conditions of the GNU General Public License, 63699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * version 2, as published by the Free Software Foundation. 73699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * 83699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * This program is distributed in the hope it will be useful, but WITHOUT 93699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 103699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 113699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * more details. 123699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * 133699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * You should have received a copy of the GNU General Public License along with 143699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * this program; if not, write to the Free Software Foundation, Inc., 153699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 163699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 173699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 183699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* XXX TBD some includes may be extraneous */ 193699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 203699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/module.h> 213699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/moduleparam.h> 223699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <generated/utsrelease.h> 233699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/utsname.h> 243699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/init.h> 253699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/slab.h> 263699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/kthread.h> 273699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/types.h> 283699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/string.h> 293699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/configfs.h> 303699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/ctype.h> 313699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/hash.h> 323699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/rcupdate.h> 333699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/rculist.h> 343699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <linux/kref.h> 353699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <asm/unaligned.h> 363699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <scsi/scsi.h> 373699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <scsi/scsi_host.h> 383699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <scsi/scsi_device.h> 393699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <scsi/scsi_cmnd.h> 403699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <scsi/libfc.h> 413699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 423699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <target/target_core_base.h> 43c4795fb20edf2fe2c862c8fe9f8b681edeb79ac1Christoph Hellwig#include <target/target_core_fabric.h> 443699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <target/target_core_configfs.h> 453699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include <target/configfs_macros.h> 463699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 473699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil#include "tcm_fc.h" 483699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 493699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_sess_delete_all(struct ft_tport *); 503699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 513699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 523699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Lookup or allocate target local port. 533699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller holds ft_lport_lock. 543699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 553699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic struct ft_tport *ft_tport_create(struct fc_lport *lport) 563699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 573699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tpg *tpg; 583699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tport *tport; 593699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil int i; 603699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 611ee0932804c2526efca4c6623911b07f6992eb3fMark Rustad tport = rcu_dereference_protected(lport->prov[FC_TYPE_FCP], 621ee0932804c2526efca4c6623911b07f6992eb3fMark Rustad lockdep_is_held(&ft_lport_lock)); 633699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (tport && tport->tpg) 643699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return tport; 653699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 663699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tpg = ft_lport_find_tpg(lport); 673699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!tpg) 683699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NULL; 693699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 703699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (tport) { 713699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport->tpg = tpg; 723699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return tport; 733699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 743699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 753699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport = kzalloc(sizeof(*tport), GFP_KERNEL); 763699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!tport) 773699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NULL; 783699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 793699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport->lport = lport; 803699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport->tpg = tpg; 813699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tpg->tport = tport; 823699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil for (i = 0; i < FT_SESS_HASH_SIZE; i++) 833699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil INIT_HLIST_HEAD(&tport->hash[i]); 843699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 853699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rcu_assign_pointer(lport->prov[FC_TYPE_FCP], tport); 863699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return tport; 873699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 883699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 893699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 903699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Delete a target local port. 913699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller holds ft_lport_lock. 923699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 933699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_tport_delete(struct ft_tport *tport) 943699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 953699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct fc_lport *lport; 963699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tpg *tpg; 973699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 983699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_delete_all(tport); 993699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil lport = tport->lport; 1003699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil BUG_ON(tport != lport->prov[FC_TYPE_FCP]); 1013699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rcu_assign_pointer(lport->prov[FC_TYPE_FCP], NULL); 1023699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1033699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tpg = tport->tpg; 1043699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (tpg) { 1053699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tpg->tport = NULL; 1063699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport->tpg = NULL; 1073699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 108a6c76da8f8b4549ccec7425ba94d8395d68a2e56Paul E. McKenney kfree_rcu(tport, rcu); 1093699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 1103699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1113699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 1123699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Add local port. 1133699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Called thru fc_lport_iterate(). 1143699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 1153699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilvoid ft_lport_add(struct fc_lport *lport, void *arg) 1163699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 1173699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_lock(&ft_lport_lock); 1183699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_tport_create(lport); 1193699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 1203699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 1213699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1223699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 1233699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Delete local port. 1243699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Called thru fc_lport_iterate(). 1253699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 1263699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilvoid ft_lport_del(struct fc_lport *lport, void *arg) 1273699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 1283699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tport *tport; 1293699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1303699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_lock(&ft_lport_lock); 1313699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport = lport->prov[FC_TYPE_FCP]; 1323699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (tport) 1333699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_tport_delete(tport); 1343699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 1353699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 1363699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1373699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 1383699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Notification of local port change from libfc. 1393699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Create or delete local port and associated tport. 1403699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 1413699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilint ft_lport_notify(struct notifier_block *nb, unsigned long event, void *arg) 1423699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 1433699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct fc_lport *lport = arg; 1443699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1453699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil switch (event) { 1463699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil case FC_LPORT_EV_ADD: 1473699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_lport_add(lport, NULL); 1483699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil break; 1493699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil case FC_LPORT_EV_DEL: 1503699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_lport_del(lport, NULL); 1513699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil break; 1523699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 1533699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NOTIFY_DONE; 1543699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 1553699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1563699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 1573699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Hash function for FC_IDs. 1583699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 1593699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic u32 ft_sess_hash(u32 port_id) 1603699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 1613699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return hash_32(port_id, FT_SESS_HASH_BITS); 1623699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 1633699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1643699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 1653699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Find session in local port. 1663699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Sessions and hash lists are RCU-protected. 1673699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * A reference is taken which must be eventually freed. 1683699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 1693699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) 1703699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 1713699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tport *tport; 1723699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_head *head; 1733699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_node *pos; 1743699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 1753699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1763699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rcu_read_lock(); 1773699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); 1783699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!tport) 1793699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil goto out; 1803699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1813699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil head = &tport->hash[ft_sess_hash(port_id)]; 1823699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil hlist_for_each_entry_rcu(sess, pos, head, hash) { 1833699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (sess->port_id == port_id) { 1843699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil kref_get(&sess->kref); 1853699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rcu_read_unlock(); 1866708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("port_id %x found %p\n", port_id, sess); 1873699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return sess; 1883699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 1893699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 1903699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilout: 1913699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rcu_read_unlock(); 1926708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("port_id %x not found\n", port_id); 1933699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NULL; 1943699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 1953699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 1963699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 1973699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Allocate session and enter it in the hash for the local port. 1983699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller holds ft_lport_lock. 1993699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 2003699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, 2013699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_node_acl *acl) 2023699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 2033699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 2043699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_head *head; 2053699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_node *pos; 2063699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2073699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil head = &tport->hash[ft_sess_hash(port_id)]; 2083699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil hlist_for_each_entry_rcu(sess, pos, head, hash) 2093699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (sess->port_id == port_id) 2103699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return sess; 2113699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2123699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess = kzalloc(sizeof(*sess), GFP_KERNEL); 2133699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!sess) 2143699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NULL; 2153699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2163699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->se_sess = transport_init_session(); 217552523dcbf0f33d44d816da310be8227a2c1502aDan Carpenter if (IS_ERR(sess->se_sess)) { 2183699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil kfree(sess); 2193699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NULL; 2203699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 2213699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->se_sess->se_node_acl = &acl->se_node_acl; 2223699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->tport = tport; 2233699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->port_id = port_id; 2243699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil kref_init(&sess->kref); /* ref for table entry */ 2253699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil hlist_add_head_rcu(&sess->hash, head); 2263699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport->sess_count++; 2273699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2286708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("port_id %x sess %p\n", port_id, sess); 2293699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2303699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil transport_register_session(&tport->tpg->se_tpg, &acl->se_node_acl, 2313699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->se_sess, sess); 2323699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return sess; 2333699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 2343699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2353699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 2363699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Unhash the session. 2373699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller holds ft_lport_lock. 2383699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 2393699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_sess_unhash(struct ft_sess *sess) 2403699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 2413699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tport *tport = sess->tport; 2423699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2433699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil hlist_del_rcu(&sess->hash); 2443699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil BUG_ON(!tport->sess_count); 2453699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport->sess_count--; 2463699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->port_id = -1; 2473699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->params = 0; 2483699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 2493699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2503699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 2513699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Delete session from hash. 2523699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller holds ft_lport_lock. 2533699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 2543699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id) 2553699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 2563699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_head *head; 2573699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_node *pos; 2583699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 2593699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2603699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil head = &tport->hash[ft_sess_hash(port_id)]; 2613699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil hlist_for_each_entry_rcu(sess, pos, head, hash) { 2623699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (sess->port_id == port_id) { 2633699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_unhash(sess); 2643699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return sess; 2653699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 2663699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 2673699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return NULL; 2683699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 2693699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2703699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 2713699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Delete all sessions from tport. 2723699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller holds ft_lport_lock. 2733699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 2743699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_sess_delete_all(struct ft_tport *tport) 2753699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 2763699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_head *head; 2773699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct hlist_node *pos; 2783699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 2793699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2803699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil for (head = tport->hash; 2813699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil head < &tport->hash[FT_SESS_HASH_SIZE]; head++) { 2823699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil hlist_for_each_entry_rcu(sess, pos, head, hash) { 2833699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_unhash(sess); 2843699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil transport_deregister_session_configfs(sess->se_sess); 2853699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_put(sess); /* release from table */ 2863699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 2873699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 2883699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 2893699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2903699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 2913699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * TCM ops for sessions. 2923699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 2933699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 2943699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 2953699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Determine whether session is allowed to be shutdown in the current context. 2963699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Returns non-zero if the session should be shutdown. 2973699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 2983699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilint ft_sess_shutdown(struct se_session *se_sess) 2993699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 3003699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess = se_sess->fabric_sess_ptr; 3013699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3026708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("port_id %x\n", sess->port_id); 3033699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return 1; 3043699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 3053699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3063699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 3073699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Remove session and send PRLO. 3083699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * This is called when the ACL is being deleted or queue depth is changing. 3093699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 3103699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilvoid ft_sess_close(struct se_session *se_sess) 3113699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 3123699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess = se_sess->fabric_sess_ptr; 3133699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil u32 port_id; 3143699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3153699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_lock(&ft_lport_lock); 3163699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil port_id = sess->port_id; 3173699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (port_id == -1) { 3187c7cf3b9c31ed09822e5c186297991093ee13c49Dan Carpenter mutex_unlock(&ft_lport_lock); 3193699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return; 3203699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 3216708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("port_id %x\n", port_id); 3223699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_unhash(sess); 3233699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 3243699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil transport_deregister_session_configfs(se_sess); 3253699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_put(sess); 3263699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* XXX Send LOGO or PRLO */ 3273699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil synchronize_rcu(); /* let transport deregister happen */ 3283699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 3293699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3303699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilu32 ft_sess_get_index(struct se_session *se_sess) 3313699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 3323699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess = se_sess->fabric_sess_ptr; 3333699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3343699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return sess->port_id; /* XXX TBD probably not what is needed */ 3353699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 3363699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3373699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilu32 ft_sess_get_port_name(struct se_session *se_sess, 3383699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil unsigned char *buf, u32 len) 3393699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 3403699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess = se_sess->fabric_sess_ptr; 3413699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3423699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return ft_format_wwn(buf, len, sess->port_name); 3433699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 3443699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3453699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 3463699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * libfc ops involving sessions. 3473699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 3483699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3493699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, 3503699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil const struct fc_els_spp *rspp, struct fc_els_spp *spp) 3513699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 3523699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tport *tport; 3533699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 3543699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_node_acl *acl; 3553699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil u32 fcp_parm; 3563699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3573699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport = ft_tport_create(rdata->local_port); 3583699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!tport) 3593699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return 0; /* not a target for this local port */ 3603699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3613699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil acl = ft_acl_get(tport->tpg, rdata); 3623699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!acl) 3633699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return 0; 3643699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3653699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!rspp) 3663699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil goto fill; 3673699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3683699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (rspp->spp_flags & (FC_SPP_OPA_VAL | FC_SPP_RPA_VAL)) 3693699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return FC_SPP_RESP_NO_PA; 3703699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3713699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* 3723699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * If both target and initiator bits are off, the SPP is invalid. 3733699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 3743699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil fcp_parm = ntohl(rspp->spp_params); 3753699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!(fcp_parm & (FCP_SPPF_INIT_FCN | FCP_SPPF_TARG_FCN))) 3763699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return FC_SPP_RESP_INVL; 3773699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3783699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* 3793699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Create session (image pair) only if requested by 3803699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * EST_IMG_PAIR flag and if the requestor is an initiator. 3813699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 3823699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) { 3833699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil spp->spp_flags |= FC_SPP_EST_IMG_PAIR; 3843699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!(fcp_parm & FCP_SPPF_INIT_FCN)) 3853699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return FC_SPP_RESP_CONF; 3863699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess = ft_sess_create(tport, rdata->ids.port_id, acl); 3873699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!sess) 3883699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return FC_SPP_RESP_RES; 3893699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!sess->params) 3903699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rdata->prli_count++; 3913699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->params = fcp_parm; 3923699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->port_name = rdata->ids.port_name; 3933699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess->max_frame = rdata->maxframe_size; 3943699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3953699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* XXX TBD - clearing actions. unit attn, see 4.10 */ 3963699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 3973699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 3983699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* 3993699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * OR in our service parameters with other provider (initiator), if any. 4003699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * TBD XXX - indicate RETRY capability? 4013699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 4023699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilfill: 4033699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil fcp_parm = ntohl(spp->spp_params); 4043699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); 4053699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return FC_SPP_RESP_ACK; 4063699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4073699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4083699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/** 4093699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * tcm_fcp_prli() - Handle incoming or outgoing PRLI for the FCP target 4103699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * @rdata: remote port private 4113699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * @spp_len: service parameter page length 4123699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * @rspp: received service parameter page (NULL for outgoing PRLI) 4133699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * @spp: response service parameter page 4143699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * 4153699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Returns spp response code. 4163699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 4173699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, 4183699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil const struct fc_els_spp *rspp, struct fc_els_spp *spp) 4193699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 4203699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil int ret; 4213699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4223699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_lock(&ft_lport_lock); 4233699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ret = ft_prli_locked(rdata, spp_len, rspp, spp); 4243699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 4256708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("port_id %x flags %x ret %x\n", 4263699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); 4273699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return ret; 4283699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4293699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4303699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_sess_rcu_free(struct rcu_head *rcu) 4313699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 4323699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); 4333699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4343699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil transport_deregister_session(sess->se_sess); 4353699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil kfree(sess); 4363699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4373699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4383699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_sess_free(struct kref *kref) 4393699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 4403699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess = container_of(kref, struct ft_sess, kref); 4413699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4423699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil call_rcu(&sess->rcu, ft_sess_rcu_free); 4433699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4443699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4453699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilvoid ft_sess_put(struct ft_sess *sess) 4463699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 4473699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil int sess_held = atomic_read(&sess->kref.refcount); 4483699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4493699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil BUG_ON(!sess_held); 4503699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil kref_put(&sess->kref, ft_sess_free); 4513699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4523699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4533699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_prlo(struct fc_rport_priv *rdata) 4543699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 4553699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 4563699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_tport *tport; 4573699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4583699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_lock(&ft_lport_lock); 4593699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); 4603699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!tport) { 4613699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 4623699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return; 4633699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 4643699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess = ft_sess_delete(tport, rdata->ids.port_id); 4653699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!sess) { 4663699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 4673699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return; 4683699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 4693699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil mutex_unlock(&ft_lport_lock); 4703699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil transport_deregister_session_configfs(sess->se_sess); 4713699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_sess_put(sess); /* release from table */ 4723699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil rdata->prli_count--; 4733699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* XXX TBD - clearing actions. unit attn, see 4.10 */ 4743699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4753699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4763699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 4773699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Handle incoming FCP request. 4783699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Caller has verified that the frame is type FCP. 4793699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 4803699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstatic void ft_recv(struct fc_lport *lport, struct fc_frame *fp) 4813699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil{ 4823699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil struct ft_sess *sess; 4833699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil u32 sid = fc_frame_sid(fp); 4843699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4856708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("sid %x\n", sid); 4863699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4873699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil sess = ft_sess_get(lport, sid); 4883699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil if (!sess) { 4896708bb27bb2703da238f21f516034263348af5beAndy Grover pr_debug("sid %x sess lookup failed\n", sid); 4903699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil /* TBD XXX - if FCP_CMND, send PRLO */ 4913699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil fc_frame_free(fp); 4923699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil return; 4933699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil } 4943699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil ft_recv_req(sess, fp); /* must do ft_sess_put() */ 4953699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil} 4963699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil 4973699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil/* 4983699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil * Provider ops for libfc. 4993699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil */ 5003699d92a4d7b649bde67dff3cc681400992e0254Kiran Patilstruct fc4_prov ft_prov = { 5013699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil .prli = ft_prli, 5023699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil .prlo = ft_prlo, 5033699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil .recv = ft_recv, 5043699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil .module = THIS_MODULE, 5053699d92a4d7b649bde67dff3cc681400992e0254Kiran Patil}; 506