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