All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 1/5 RESEND] add libiscsi
@ 2005-11-20 21:27 Mike Christie
  0 siblings, 0 replies; only message in thread
From: Mike Christie @ 2005-11-20 21:27 UTC (permalink / raw)
  To: linux-scsi

Add libiscsi code. These functions are usable by HW or SW iscsi
LLDs.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>

diff -Naurp linux-2.6.15-rc2/drivers/scsi/libiscsi.c linux-2.6.15-rc2.diff/drivers/scsi/libiscsi.c
--- linux-2.6.15-rc2/drivers/scsi/libiscsi.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.15-rc2.diff/drivers/scsi/libiscsi.c	2005-11-20 15:06:49.000000000 -0600
@@ -0,0 +1,473 @@
+/*
+ * iSCSI lib functions
+ *
+ * Copyright (C) IBM Corporation, 2004
+ * Copyright (C) Mike Christie, 2004 - 2005
+ * Copyright (C) Dmitry Yusupov, 2004 - 2005
+ * Copyright (C) Alex Aizman, 2004 - 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/iscsi_session.h>
+
+#define dev_to_ihost(_dev) \
+	container_of(_dev, struct iscsi_host, dev)
+
+static LIST_HEAD(iscsi_hosts);
+static DEFINE_SPINLOCK(iscsi_hosts_lock);
+
+static void iscsi_host_release(struct device *dev)
+{
+	struct iscsi_host *ihost = dev_to_ihost(dev);
+	kfree(ihost);
+}
+
+/**
+ * iscsi_alloc_iscsi_host - allocate iscsi host
+ * iscsi_transport: iscsi_transport
+ * scsi_transport: scsi_transport returned from iscsi transport registration
+ * gpf: allocation mask
+ *
+ * HW iSCSI LLDs should allocte one of these per PCI device in their probe.
+ * SW iSCSI can allocate one per module/node or one per resource if it
+ * is being bound to HW resrouce.
+ **/
+struct iscsi_host *
+iscsi_alloc_iscsi_host(struct iscsi_transport *iscsi_transport,
+		       struct scsi_transport_template *scsi_transport)
+{
+	struct iscsi_host *ihost;
+	struct device *dev;
+
+	ihost = kzalloc(sizeof(*ihost) + iscsi_transport->ihostdata_size,
+			GFP_KERNEL);
+	if (!ihost)
+		return NULL;
+
+	ihost->scsi_transport = scsi_transport;
+	ihost->iscsi_transport = iscsi_transport;
+	/*
+	 * The LLD can set the can_queue to HW resource per card limit
+	 * or per target (for virtual LLDs) and we make sure the
+	 * the correct number of commands gets to them.
+	 */
+	ihost->cmds_per_iscsihost = iscsi_transport->host_template->can_queue;
+	INIT_LIST_HEAD(&ihost->sessions);
+	INIT_LIST_HEAD(&ihost->list);
+	spin_lock_init(&ihost->session_lock);
+
+	if (iscsi_transport->ihostdata_size)
+		ihost->dd_data = &ihost[1];
+
+	dev = &ihost->dev;
+	device_initialize(dev);
+	dev->release = iscsi_host_release;
+	return ihost;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_alloc_iscsi_host);
+
+/**
+ * iscsi_add_iscsi_host - complete setup by adding the host
+ * @ihost: iscsi host
+ * @dev: parent device
+ * @name: if there is no parent, name must be a unique name for this host
+ *
+ * This should be called after the host has been setup.
+ **/
+int iscsi_add_iscsi_host(struct iscsi_host *ihost, struct device *dev,
+			 const char *name)
+{
+	unsigned long flags;
+	int err;
+
+	if (dev) {
+		strlcpy(ihost->dev.bus_id, dev->bus_id, BUS_ID_SIZE);
+		ihost->dev.parent = dev;
+	} else {
+		strlcpy(ihost->dev.bus_id, name, BUS_ID_SIZE);
+		ihost->dev.parent = &platform_bus;
+	}
+
+	err = device_add(&ihost->dev);
+	if (err)
+		return err;	
+
+	spin_lock_irqsave(&iscsi_hosts_lock, flags);
+	list_add(&ihost->list, &iscsi_hosts);
+	spin_unlock_irqrestore(&iscsi_hosts_lock, flags);
+
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_add_iscsi_host);
+
+/**
+ * iscsi_remove_iscsi_host - remove iscsi host
+ * @ihost: iscsi host
+ **/
+void iscsi_remove_iscsi_host(struct iscsi_host *ihost)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&iscsi_hosts_lock, flags);
+	list_del(&ihost->list);
+	spin_unlock_irqrestore(&iscsi_hosts_lock, flags);
+	device_del(&ihost->dev);
+}
+
+EXPORT_SYMBOL_GPL(iscsi_remove_iscsi_host);
+
+static void iscsi_task_done(struct scsi_cmnd *cmd)
+{
+	struct scsi_device *sdev = cmd->device;
+	struct iscsi_session *session = hostdata_session(sdev->host->hostdata);
+	unsigned long flags;
+
+	/*
+	 * Bleh. Must think of something else
+	 */
+	spin_lock_irqsave(&session->ihost->session_lock, flags);
+	session->ihost->cmds_queued--;
+	spin_unlock_irqrestore(&session->ihost->session_lock, flags);
+
+	cmd->scsi_done(cmd);
+}
+
+/**
+ * iscsi_scsi_queuecmd - queue command to scsi_host
+ * @cmd: scsi cmd
+ * @done: scsi done function
+ *
+ * At this time we only check that scsi limits are honored. When iSER and
+ * Qlogic are closer to being merged we can move more state checking
+ * (iscsi eh state and iscsi sequence number checks) and iscsi_task
+ * allocation here so we can all share that code. Hopefully, we can
+ * share some TMF code with SAS.
+ **/
+int iscsi_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+	struct scsi_device *sdev = cmd->device;
+	struct Scsi_Host *shost = sdev->host;
+	struct iscsi_session *session = hostdata_session(shost->hostdata);
+	struct iscsi_host *ihost = session->ihost;
+	int ret = 0;
+
+	spin_unlock(shost->host_lock);
+	spin_lock(&ihost->session_lock);
+
+	if (ihost->cmds_queued >= ihost->cmds_per_iscsihost) {
+		ret = SCSI_MLQUEUE_HOST_BUSY;		
+		goto done;
+	}
+	ihost->cmds_queued++;
+
+	cmd->scsi_done = done;
+	ret = ihost->iscsi_transport->execute_task(cmd, iscsi_task_done);
+	if (!ret)
+		goto done;
+	ihost->cmds_queued--;
+
+	switch (ret) {
+	case ISCSI_FAILURE_WINDOW_CLOSED:
+		ret = SCSI_MLQUEUE_HOST_BUSY;
+		break;
+	default:
+		cmd->result = (DID_NO_CONNECT << 16);
+		cmd->resid = cmd->request_bufflen;
+		done(cmd);
+		ret = 0;
+	}
+
+done:
+	spin_unlock(&ihost->session_lock);
+	spin_lock(shost->host_lock);
+	return ret;	
+}
+
+EXPORT_SYMBOL_GPL(iscsi_scsi_queuecmd);
+
+struct iscsi_host *iscsi_find_iscsi_host(const char *bus_id)
+{
+	unsigned long flags;
+	struct iscsi_host *ihost;
+
+	spin_lock_irqsave(&iscsi_hosts_lock, flags);
+	list_for_each_entry(ihost, &iscsi_hosts, list) {
+		if (!strncmp(ihost->dev.bus_id, bus_id, BUS_ID_SIZE))
+			goto done;
+	}
+	ihost = NULL;
+ done:
+	spin_unlock_irqrestore(&iscsi_hosts_lock, flags);
+	return ihost;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_find_iscsi_host);
+
+/**
+ * iscsi_host_put - release handle to iscsi host
+ * @ihost: iscsi host
+ **/
+void iscsi_host_put(struct iscsi_host *ihost)
+{
+	put_device(&ihost->dev);
+}
+
+EXPORT_SYMBOL_GPL(iscsi_host_put);
+
+/*
+ * iSCSI Session's hostdata organization:
+ *
+ *    *------------------* <== host->hostdata
+ *    | transport        |
+ *    |------------------| <== iscsi_hostdata(host->hostdata)
+ *    | transport's data |
+ *    |------------------| <== hostdata_session(host->hostdata)
+ *    | classes's data   |
+ *    *------------------*
+ */
+
+#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
+				 _t->hostdata_size % sizeof(unsigned long) + \
+				 sizeof(struct iscsi_session))
+
+static void iscsi_session_release(struct device *dev)
+{
+	struct iscsi_session *session = iscsi_dev_to_session(dev);
+	struct iscsi_transport *transport = session->ihost->iscsi_transport;
+	struct Scsi_Host *shost;
+
+	shost = iscsi_session_to_shost(session);
+	scsi_host_put(shost);
+	module_put(transport->owner);
+}
+
+int iscsi_is_session_dev(const struct device *dev)
+{
+	return dev->release == iscsi_session_release;
+}
+
+/**
+ * iscsi_create_session - create iscsi class session
+ * @ihost: iscsi host
+ * @initial_cmdsn: initial iSCSI CmdSN
+ *
+ * This can be called from a LLD or iscsi_interface
+ **/
+struct iscsi_session *
+iscsi_create_session(struct iscsi_host *ihost, uint32_t initial_cmdsn)
+{
+	struct iscsi_transport *transport = ihost->iscsi_transport;
+	struct iscsi_session *session;
+	struct Scsi_Host *shost;
+	unsigned long flags;
+	int err;
+
+	if (!try_module_get(transport->owner))
+		return NULL;
+
+	shost = scsi_host_alloc(transport->host_template,
+				hostdata_privsize(transport));
+	if (!shost) {
+		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
+		       "session\n");
+		goto out_module_put;
+	}
+
+	shost->max_id = 1;
+	shost->max_channel = 0;
+	shost->max_lun = transport->max_lun;
+	shost->max_cmd_len = transport->max_cmd_len;
+	shost->transportt = ihost->scsi_transport;
+
+	/* store struct iscsi_transport in hostdata */
+	*(uint64_t*)shost->hostdata = iscsi_handle(transport);
+
+	/* initialize session */
+	if (transport->create_session) {
+		err = transport->create_session(ihost, shost, initial_cmdsn);
+		if (err)
+			goto out_host_put;
+	}
+
+	session = hostdata_session(shost->hostdata);
+	INIT_LIST_HEAD(&session->list);
+	session->ihost = ihost;
+
+	err = scsi_add_host(shost, &ihost->dev);
+	if (err)
+		goto out_destroy_session;
+
+	/* this is released in the dev's release function */
+	scsi_host_get(shost);
+	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
+	session->dev.parent = &shost->shost_gendev;
+	session->dev.release = iscsi_session_release;
+	err = device_register(&session->dev);
+	if (err) {
+		dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
+			   "register session's dev\n");
+		goto out_remove_host;
+	}
+	transport_register_device(&session->dev);
+
+
+	/* add this session to the list of active sessions */
+	spin_lock_irqsave(&ihost->session_lock, flags);
+	list_add(&session->list, &ihost->sessions);
+	spin_unlock_irqrestore(&ihost->session_lock, flags);
+
+	return session;
+
+out_remove_host:
+	scsi_remove_host(shost);
+out_destroy_session:
+	if (transport->destroy_session)
+		transport->destroy_session(ihost, shost);
+out_host_put:
+	scsi_host_put(shost);
+out_module_put:
+	module_put(transport->owner);
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_session);
+
+/**
+ * iscsi_destroy_session - destroy iscsi session
+ * @session: iscsi_session
+ *
+ * Can be called by a LLD or iscsi_interface. There must not be
+ * any running connections.
+ **/
+int iscsi_destroy_session(struct iscsi_session *session)
+{
+	struct iscsi_host *ihost = session->ihost;
+	struct iscsi_transport *transport = ihost->iscsi_transport;
+	struct Scsi_Host *shost;
+	unsigned long flags;
+
+	shost = iscsi_session_to_shost(session);
+	scsi_remove_host(shost);
+
+	if (transport->destroy_session)
+		transport->destroy_session(session->ihost, shost);
+
+	transport_unregister_device(&session->dev);
+	device_unregister(&session->dev);
+
+	/* remove this session from the list of active sessions */
+	spin_lock_irqsave(&ihost->session_lock, flags);
+	list_del(&session->list);
+	spin_unlock_irqrestore(&ihost->session_lock, flags);
+
+	/*
+	 * ref from host alloc (there was an extra get from the session->dev
+	 * relased in driver model release
+	 */
+	scsi_host_put(shost);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+
+static void iscsi_conn_release(struct device *dev)
+{
+	struct iscsi_conn *conn = iscsi_dev_to_conn(dev);
+	struct device *parent = conn->dev.parent;
+
+	kfree(conn);
+	put_device(parent);
+}
+
+int iscsi_is_conn_dev(const struct device *dev)
+{
+	return dev->release == iscsi_conn_release;
+}
+
+struct iscsi_conn *
+iscsi_create_conn(struct iscsi_session *session, uint32_t cid)
+{
+	struct iscsi_transport *transport = session->ihost->iscsi_transport;
+	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+	struct iscsi_conn *conn;
+	int err;
+
+	conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
+	if (!conn)
+		return NULL;
+
+	if (transport->conndata_size)
+		conn->dd_data = &conn[1];
+
+	INIT_LIST_HEAD(&conn->conn_list);
+	conn->transport = transport;
+
+	if (transport->create_conn) {
+		if (transport->create_conn(shost, conn->dd_data, cid))
+			goto free_conn;
+	}
+
+	/* this is released in the dev's release function */
+	if (!get_device(&session->dev))
+		goto destroy_conn;
+	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+		 shost->host_no, cid);
+	conn->dev.parent = &session->dev;
+	conn->dev.release = iscsi_conn_release;
+	err = device_register(&conn->dev);
+	if (err) {
+		dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
+			   "connection's dev\n");
+		goto release_parent_ref;
+	}
+	transport_register_device(&conn->dev);
+	return conn;
+
+release_parent_ref:
+	put_device(&session->dev);
+destroy_conn:
+	if (transport->destroy_conn)
+		transport->destroy_conn(conn->dd_data);
+free_conn:
+	kfree(conn);
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_conn);
+
+int iscsi_destroy_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_session *session = iscsi_dev_to_session(conn->dev.parent);
+	struct iscsi_transport *transport = session->ihost->iscsi_transport;
+
+	if (transport->destroy_conn)
+		transport->destroy_conn(conn->dd_data);
+
+	transport_unregister_device(&conn->dev);
+	device_unregister(&conn->dev);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
diff -Naurp linux-2.6.15-rc2/include/scsi/iscsi_session.h linux-2.6.15-rc2.diff/include/scsi/iscsi_session.h
--- linux-2.6.15-rc2/include/scsi/iscsi_session.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.15-rc2.diff/include/scsi/iscsi_session.h	2005-11-20 15:07:09.000000000 -0600
@@ -0,0 +1,90 @@
+/*
+ * iSCSI session and connection management functions and defnitions
+ *
+ * Copyright (C) IBM Corporation, 2004
+ * Copyright (C) Mike Christie, 2004 - 2005
+ * Copyright (C) Dmitry Yusupov, 2004 - 2005
+ * Copyright (C) Alex Aizman, 2004 - 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef SCSI_LIBISCSI_ISCSI_H
+#define SCSI_LIBISCSI_ISCSI_H
+
+#include <linux/mempool.h>
+#include <linux/device.h>
+#include <scsi/iscsi_if.h>
+
+struct iscsi_transport;
+struct iscsi_host;
+
+struct mempool_zone {
+	mempool_t *pool;
+	atomic_t allocated;
+	int size;
+	int hiwat;
+	struct list_head freequeue;
+	spinlock_t freelock;
+};
+
+struct iscsi_conn {
+	struct list_head conn_list;	/* item in connlist */
+	void *dd_data;			/* LLD private data */
+	struct iscsi_transport *transport;
+	iscsi_connh_t connh;
+	int active;			/* must be accessed with the connlock */
+	struct device dev;		/* sysfs transport/container device */
+	struct mempool_zone z_error;
+	struct mempool_zone z_pdu;
+	struct list_head freequeue;
+};
+
+#define iscsi_dev_to_conn(_dev) \
+	container_of(_dev, struct iscsi_conn, dev)
+
+struct iscsi_session {
+	struct list_head list;	/* item in session_list */
+	struct iscsi_host *ihost;
+	struct device dev;	/* sysfs transport/container device */
+};
+
+/**
+ * hostdata_session - get libiscsi session from hostdata
+ * @_hostdata: scsi host hostdata
+ **/
+#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \
+			((struct iscsi_transport *) \
+			iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
+
+#define iscsi_dev_to_session(_dev) \
+	container_of(_dev, struct iscsi_session, dev)
+
+#define iscsi_session_to_shost(_session) \
+	dev_to_shost(_session->dev.parent)
+
+/*
+ * session and connection calls
+ */
+extern struct iscsi_session *iscsi_create_session(struct iscsi_host *ihost,
+						  uint32_t initial_cmdsn);
+extern int iscsi_destroy_session(struct iscsi_session *session);
+extern int iscsi_is_session_dev(const struct device *dev);
+extern struct iscsi_conn *iscsi_create_conn(struct iscsi_session *session,
+					    uint32_t cid);
+extern int iscsi_destroy_conn(struct iscsi_conn *conn);
+extern int iscsi_is_conn_dev(const struct device *dev);
+
+
+#endif
diff -Naurp linux-2.6.15-rc2/include/scsi/scsi_transport_iscsi.h linux-2.6.15-rc2.diff/include/scsi/scsi_transport_iscsi.h
--- linux-2.6.15-rc2/include/scsi/scsi_transport_iscsi.h	2005-11-19 21:25:03.000000000 -0600
+++ linux-2.6.15-rc2.diff/include/scsi/scsi_transport_iscsi.h	2005-11-20 15:07:20.000000000 -0600
@@ -25,6 +25,11 @@
 
 #include <scsi/iscsi_if.h>
 
+struct scsi_transport_template;
+struct Scsi_Host;
+struct scsi_cmnd;
+struct iscsi_host;
+
 /**
  * struct iscsi_transport - iSCSI Transport template
  *
@@ -48,35 +53,87 @@ struct iscsi_transport {
 	char *name;
 	unsigned int caps;
 	struct scsi_host_template *host_template;
+	/* LLD session/scsi_host data size */
 	int hostdata_size;
+	/* LLD iscsi_host data size */
+	int ihostdata_size;
+	/* LLD connection data size */
+	int conndata_size;
 	int max_lun;
 	unsigned int max_conn;
 	unsigned int max_cmd_len;
-	iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn,
-					    struct Scsi_Host *shost);
-	void (*destroy_session) (iscsi_sessionh_t session);
-	iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid);
+	int (*create_session) (struct iscsi_host *ihost,
+			       struct Scsi_Host *shost,
+			       uint32_t initial_cmdsn);
+	void (*destroy_session) (struct iscsi_host *ihost,
+				struct Scsi_Host *shost);
+	int (*create_conn) (struct Scsi_Host *shost, void *conndata,
+			    uint32_t cid);
 	int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
 			  uint32_t transport_fd, int is_leading);
 	int (*start_conn) (iscsi_connh_t conn);
 	void (*stop_conn) (iscsi_connh_t conn, int flag);
-	void (*destroy_conn) (iscsi_connh_t conn);
+	void (*destroy_conn) (void *conndata);
 	int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
 			  uint32_t value);
-	int (*get_param) (iscsi_connh_t conn, enum iscsi_param param,
-			  uint32_t *value);
+	int (*get_conn_param) (void *conndata, enum iscsi_param param,
+			       uint32_t *value);
+	int (*get_session_param) (struct Scsi_Host *shost,
+				  enum iscsi_param param, uint32_t *value);
 	int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
 			 char *data, uint32_t data_size);
 	void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
+	int (*execute_task) (struct scsi_cmnd *cmd,
+			     void (*done)(struct scsi_cmnd *));
+};
+
+struct iscsi_host {
+	struct iscsi_transport *iscsi_transport;
+	struct scsi_transport_template *scsi_transport;
+
+	struct device dev;
+	struct list_head list;
+	struct list_head sessions;
+	spinlock_t session_lock;
+
+	void *dd_data;
+
+	int cmds_per_iscsihost;
+	int cmds_queued;
+};
+
+/*
+ * iSCSI LLD execute_task return codes
+ * (TODO make more iscsi/SAMish when SAS code is merged)
+ */
+enum {
+	ISCSI_FAILURE_BAD_HOST = 1,
+	ISCSI_FAILURE_SESSION_FAILED,
+	ISCSI_FAILURE_SESSION_FREED,
+	ISCSI_FAILURE_WINDOW_CLOSED,
+	ISCSI_FAILURE_SESSION_TERMINATE,
 };
 
 /*
  * transport registration upcalls
  */
-extern int iscsi_register_transport(struct iscsi_transport *tt);
+extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt);
 extern int iscsi_unregister_transport(struct iscsi_transport *tt);
 
 /*
+ * iscsi host setup/destroy/queue calls
+ */
+extern struct iscsi_host *iscsi_alloc_iscsi_host(struct iscsi_transport *xpt,
+				struct scsi_transport_template *scsi_transport);
+extern int iscsi_add_iscsi_host(struct iscsi_host *ihost, struct device *dev,
+				const char *name);
+extern void iscsi_remove_iscsi_host(struct iscsi_host *ihost);
+extern void iscsi_host_put(struct iscsi_host *ihost);
+extern struct iscsi_host *iscsi_find_iscsi_host(const char *bus_id);
+extern int iscsi_scsi_queuecmd(struct scsi_cmnd *cmd,
+			       void (*done)(struct scsi_cmnd *));
+
+/*
  * control plane upcalls
  */
 extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-11-20 21:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-20 21:27 [PATCH RFC 1/5 RESEND] add libiscsi Mike Christie

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.