[ewg] Re: [PATCH 2/2] IB/iser: add backport & kernel addons for open-iscsi over iSER support for RHAS4 up3 and up4
Erez Zilber
erezz at voltaire.com
Sun May 20 23:28:35 PDT 2007
Michael S. Tsirkin wrote:
>> Quoting Erez Zilber <erezz at voltaire.com>:
>> Subject: [PATCH 2/2] IB/iser: add backport & kernel addons for open-iscsi over iSER support for RHAS4 up3 and up4
>>
>>
>> Add the required backport patches & kernel addons for open-iscsi
>> over iSER in RHAS4 up3 and up4.
>>
>> Signed-off-by: Erez Zilber <erezz at voltaire.com>
>
> In addition to posting patches, could you pls publish a git tree to pull from,
> please? This makes it easy to test-build the patch as our build system
> knows how to do git checkout.
Added a git tree:
http://www.openfabrics.org/git/?p=~erezz/ofed_1_2_iser_rh4.git;a=summary
>
> ---
>
> Two comments, generally
> A: Please move code from kernel_patches to kernel_addons as much
> as possible. There are many places where you just add new headers,
> or add #include directives, or change the function called or
> remove extra parameters, all this can and should be done through addons.
>
Done
> B: Please do not add code to core unless there is more than 1 user -
> add it to the iser module instead. This way if there is
> compilation failure there, you do not break core for people.
Done
>
> Some specifics below:
> ....
>
>>
>> diff --git a/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
>> new file mode 100644
>> index 0000000..d77c663
>> --- /dev/null
>> +++ b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
>> @@ -0,0 +1,504 @@
>> +diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-backport-rh4-u3/drivers/scsi/iscsi_tcp.c
>> +--- linux-2.6.20/drivers/scsi/iscsi_tcp.c 2007-02-04 20:44:54.000000000 +0200
>> ++++ linux-2.6.20-backport-rh4-u3/drivers/scsi/iscsi_tcp.c 2007-04-01 13:11:17.000000000 +0300
>
> ...
>> +@@ -108,7 +108,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn
>> + {
>> + struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
>> +
>> +- crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
>> ++ crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc);
>> + buf->sg.length = tcp_conn->hdr_size;
>> + }
>> +
>
> You could make it a macro in addons if you had named the new field tx_hash.
I fixed that and other crypto function calls whenever possible.
>> +
>> + struct iscsi_internal {
>> + int daemon_pid;
>> +@@ -65,6 +69,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
>> + #define cdev_to_iscsi_internal(_cdev) \
>> + container_of(_cdev, struct iscsi_internal, cdev)
>> +
>> ++extern int attribute_container_init(void);
>> ++
>
> This does not look scsi-related. Why does this belong here?
This is a hack. In 2.6.20, attribute_container_init is called from drivers/base/init.c. Since I cannot do that, I'm calling it from the init function in scsi_transport_iscsi (because scsi_transport_iscsi uses the attribute container). Do you have a better suggestion?
>
>> diff --git a/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
>> new file mode 100644
>> index 0000000..3c2a969
>> --- /dev/null
>> +++ b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
>> @@ -0,0 +1,13 @@
>> +--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:13:43.000000000 +0200
>> ++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:14:31.000000000 +0200
>> +@@ -70,9 +70,8 @@
>> + #include <scsi/scsi_tcq.h>
>> + #include <scsi/scsi_host.h>
>> + #include <scsi/scsi.h>
>> +-#include <scsi/scsi_transport_iscsi.h>
>> +-
>> + #include "iscsi_iser.h"
>> ++#include <scsi/scsi_transport_iscsi.h>
>> +
>> + static unsigned int iscsi_max_lun = 512;
>> + module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
>
> Looks like the right thing to do anyway.
> So put it in fixes instead, and post upstream.
It is not required in newer kernels: mutex.h is included from include/scsi/scsi_host.h. Therefore, I don't want to post a patch upstream. Maybe we can add this inclusion to kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h. What do you think?
>
>> diff --git a/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch b/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch
>> index e84b964..52c0136 100644
>> --- a/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch
>> +++ b/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch
>> @@ -19,6 +19,62 @@ index 0000000..58cf933
>> +++ b/drivers/infiniband/core/kfifo.c
>> @@ -0,0 +1 @@
>> +#include "src/kfifo.c"
>> +diff --git a/drivers/infiniband/core/init.c b/drivers/infiniband/core/init.c
>> +new file mode 100644
>> +index 0000000..58cf933
>> +--- /dev/null
>> ++++ b/drivers/infiniband/core/init.c
>> +@@ -0,0 +1 @@
>> ++#include "src/init.c"
>> +diff --git a/drivers/infiniband/core/attribute_container.c b/drivers/infiniband/core/attribute_container.c
>> +new file mode 100644
>> +index 0000000..58cf933
>> +--- /dev/null
>> ++++ b/drivers/infiniband/core/attribute_container.c
>> +@@ -0,0 +1 @@
>> ++#include "src/attribute_container.c"
...
>> +diff --git a/drivers/infiniband/core/kref_new.c b/drivers/infiniband/core/kref_new.c
>> +new file mode 100644
>> +index 0000000..58cf933
>> +--- /dev/null
>> ++++ b/drivers/infiniband/core/kref_new.c
>> +@@ -0,0 +1 @@
>> ++#include "src/kref_new.c"
>> diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
>> index 50fb1cd..456bfd0 100644
>> --- a/drivers/infiniband/core/Makefile
>> @@ -28,4 +84,4 @@ index 50fb1cd..456bfd0 100644
>> ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o \
>> uverbs_marshall.o
>> +
>> -+ib_core-y += genalloc.o netevent.o kfifo.o
>> ++ib_core-y += genalloc.o netevent.o kfifo.o scsi.o scsi_lib.o scsi_scan.o init.o attribute_container.o transport_class.o klist.o kref_new.o
>
> Can we make these part of iser place?
> Linking scsi stuff into core does not look right.
Moved that into open-iscsi modules. This code is required for open-iscsi over any transport (not just iSER).
Here's the fixed patch (also available on my git tree):
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/attribute_container.h b/kernel_addons/backport/2.6.9_U3/include/linux/attribute_container.h
new file mode 100644
index 0000000..93bfb0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/attribute_container.h
@@ -0,0 +1,71 @@
+/*
+ * class_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _ATTRIBUTE_CONTAINER_H_
+#define _ATTRIBUTE_CONTAINER_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
+
+struct attribute_container {
+ struct list_head node;
+ struct klist containers;
+ struct class *class;
+ struct class_device_attribute **attrs;
+ int (*match)(struct attribute_container *, struct device *);
+#define ATTRIBUTE_CONTAINER_NO_CLASSDEVS 0x01
+ unsigned long flags;
+};
+
+static inline int
+attribute_container_no_classdevs(struct attribute_container *atc)
+{
+ return atc->flags & ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+static inline void
+attribute_container_set_no_classdevs(struct attribute_container *atc)
+{
+ atc->flags |= ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+int attribute_container_register(struct attribute_container *cont);
+int attribute_container_unregister(struct attribute_container *cont);
+void attribute_container_create_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *));
+int attribute_container_add_attrs(struct class_device *classdev);
+int attribute_container_add_class_device(struct class_device *classdev);
+int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev);
+void attribute_container_remove_attrs(struct class_device *classdev);
+void attribute_container_class_device_del(struct class_device *classdev);
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/crypto.h b/kernel_addons/backport/2.6.9_U3/include/linux/crypto.h
new file mode 100644
index 0000000..aecccde
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/crypto.h
@@ -0,0 +1,11 @@
+#ifndef LINUX_CRYPTO_BACKPORT_H
+#define LINUX_CRYPTO_BACKPORT_H
+
+#include_next <linux/crypto.h>
+
+#define crypto_hash_init(desc) crypto_digest_init(*desc)
+#define crypto_hash_digest(desc, sg, nbytes, out) crypto_digest_digest(*desc, sg, 1, out)
+#define crypto_hash_update(desc, sg, nbytes) crypto_digest_update(*desc, sg, 1)
+#define crypto_hash_final(desc, out) crypto_digest_final(*desc, out)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h b/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h
index a37dcd5..02a5907 100644
--- a/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h
@@ -4,4 +4,7 @@ #define BACKPORT_KERNEL_H_2_6_19
#include_next <linux/kernel.h>
#include <linux/log2.h>
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+
#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h b/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h
index 48eccd8..2b94461 100644
--- a/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h
@@ -25,6 +25,7 @@ #ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <linux/gfp.h>
struct kfifo {
unsigned char *buffer; /* the buffer holding the data */
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/klist.h b/kernel_addons/backport/2.6.9_U3/include/linux/klist.h
new file mode 100644
index 0000000..7407125
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/klist.h
@@ -0,0 +1,61 @@
+/*
+ * klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ * Implementations are found in lib/klist.c
+ *
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is rleased under the GPL v2.
+ */
+
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+struct klist_node;
+struct klist {
+ spinlock_t k_lock;
+ struct list_head k_list;
+ void (*get)(struct klist_node *);
+ void (*put)(struct klist_node *);
+};
+
+
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *));
+
+struct klist_node {
+ struct klist * n_klist;
+ struct list_head n_node;
+ struct kref n_ref;
+ struct completion n_removed;
+};
+
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+ struct klist * i_klist;
+ struct list_head * i_head;
+ struct klist_node * i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
+ struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/memory.h b/kernel_addons/backport/2.6.9_U3/include/linux/memory.h
new file mode 100644
index 0000000..654ef55
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/memory.h
@@ -0,0 +1,89 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+ unsigned long phys_index;
+ unsigned long state;
+ /*
+ * This serializes all state change requests. It isn't
+ * held during creation because the control files are
+ * created long after the critical areas during
+ * initialization.
+ */
+ struct semaphore state_sem;
+ int phys_device; /* to which fru does this belong? */
+ void *hw; /* optional pointer to fw/hw data */
+ int (*phys_callback)(struct memory_block *);
+ struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define MEM_ONLINE (1<<0) /* exposed to userspace */
+#define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */
+#define MEM_OFFLINE (1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid. The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working. Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define MEM_MAPPING_INVALID (1<<3)
+
+struct notifier_block;
+struct mem_section;
+
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int memory_dev_init(void)
+{
+ return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
+
+#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
+
+
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
+#define hotplug_memory_notifier(fn, pri) { \
+ static struct notifier_block fn##_mem_nb = \
+ { .notifier_call = fn, .priority = pri }; \
+ register_memory_notifier(&fn##_mem_nb); \
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/netlink.h b/kernel_addons/backport/2.6.9_U3/include/linux/netlink.h
new file mode 100644
index 0000000..6d69105
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/netlink.h
@@ -0,0 +1,14 @@
+#ifndef BACKPORT_LINUX_NETLINK_H
+#define BACKPORT_LINUX_NETLINK_H
+
+#include_next <linux/netlink.h>
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+ __nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#define netlink_kernel_create(uint, groups, input, mod) \
+ netlink_kernel_create(uint, input)
+
+#define NETLINK_ISCSI 8
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/transport_class.h b/kernel_addons/backport/2.6.9_U3/include/linux/transport_class.h
new file mode 100644
index 0000000..1d6cc22
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/transport_class.h
@@ -0,0 +1,100 @@
+/*
+ * transport_class.h - a generic container for all transport classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _TRANSPORT_CLASS_H_
+#define _TRANSPORT_CLASS_H_
+
+#include <linux/device.h>
+#include <linux/attribute_container.h>
+
+struct transport_container;
+
+struct transport_class {
+ struct class class;
+ int (*setup)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*configure)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*remove)(struct transport_container *, struct device *,
+ struct class_device *);
+};
+
+#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
+struct transport_class cls = { \
+ .class = { \
+ .name = nm, \
+ }, \
+ .setup = su, \
+ .remove = rm, \
+ .configure = cfg, \
+}
+
+
+struct anon_transport_class {
+ struct transport_class tclass;
+ struct attribute_container container;
+};
+
+#define DECLARE_ANON_TRANSPORT_CLASS(cls, mtch, cfg) \
+struct anon_transport_class cls = { \
+ .tclass = { \
+ .configure = cfg, \
+ }, \
+ . container = { \
+ .match = mtch, \
+ }, \
+}
+
+#define class_to_transport_class(x) \
+ container_of(x, struct transport_class, class)
+
+struct transport_container {
+ struct attribute_container ac;
+ struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+ container_of(x, struct transport_container, ac)
+
+void transport_remove_device(struct device *);
+void transport_add_device(struct device *);
+void transport_setup_device(struct device *);
+void transport_configure_device(struct device *);
+void transport_destroy_device(struct device *);
+
+static inline void
+transport_register_device(struct device *dev)
+{
+ transport_setup_device(dev);
+ transport_add_device(dev);
+}
+
+static inline void
+transport_unregister_device(struct device *dev)
+{
+ transport_remove_device(dev);
+ transport_destroy_device(dev);
+}
+
+static inline int transport_container_register(struct transport_container *tc)
+{
+ return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+ return attribute_container_unregister(&tc->ac);
+}
+
+int transport_class_register(struct transport_class *);
+int anon_transport_class_register(struct anon_transport_class *);
+void transport_class_unregister(struct transport_class *);
+void anon_transport_class_unregister(struct anon_transport_class *);
+
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/iscsi_proto.h b/kernel_addons/backport/2.6.9_U3/include/scsi/iscsi_proto.h
new file mode 100644
index 0000000..02f6e4b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/iscsi_proto.h
@@ -0,0 +1,587 @@
+/*
+ * RFC 3720 (iSCSI) protocol data types
+ *
+ * Copyright (C) 2005 Dmitry Yusupov
+ * Copyright (C) 2005 Alex Aizman
+ * maintained by open-iscsi at googlegroups.com
+ *
+ * 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.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#ifndef ISCSI_PROTO_H
+#define ISCSI_PROTO_H
+
+#define ISCSI_DRAFT20_VERSION 0x00
+
+/* default iSCSI listen port for incoming connections */
+#define ISCSI_LISTEN_PORT 3260
+
+/* Padding word length */
+#define PAD_WORD_LEN 4
+
+/*
+ * useful common(control and data pathes) macro
+ */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+ p[0] = (((v) >> 16) & 0xFF); \
+ p[1] = (((v) >> 8) & 0xFF); \
+ p[2] = ((v) & 0xFF); \
+}
+#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
+
+/*
+ * iSCSI Template Message Header
+ */
+struct iscsi_hdr {
+ uint8_t opcode;
+ uint8_t flags; /* Final bit */
+ uint8_t rsvd2[2];
+ uint8_t hlength; /* AHSs total length */
+ uint8_t dlength[3]; /* Data length */
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Task Tag */
+ __be32 statsn;
+ __be32 exp_statsn;
+ __be32 max_statsn;
+ uint8_t other[12];
+};
+
+/************************* RFC 3720 Begin *****************************/
+
+#define ISCSI_RESERVED_TAG 0xffffffff
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY 0x80
+#define ISCSI_OP_IMMEDIATE 0x40
+#define ISCSI_OPCODE_MASK 0x3F
+
+/* Initiator Opcode values */
+#define ISCSI_OP_NOOP_OUT 0x00
+#define ISCSI_OP_SCSI_CMD 0x01
+#define ISCSI_OP_SCSI_TMFUNC 0x02
+#define ISCSI_OP_LOGIN 0x03
+#define ISCSI_OP_TEXT 0x04
+#define ISCSI_OP_SCSI_DATA_OUT 0x05
+#define ISCSI_OP_LOGOUT 0x06
+#define ISCSI_OP_SNACK 0x10
+
+#define ISCSI_OP_VENDOR1_CMD 0x1c
+#define ISCSI_OP_VENDOR2_CMD 0x1d
+#define ISCSI_OP_VENDOR3_CMD 0x1e
+#define ISCSI_OP_VENDOR4_CMD 0x1f
+
+/* Target Opcode values */
+#define ISCSI_OP_NOOP_IN 0x20
+#define ISCSI_OP_SCSI_CMD_RSP 0x21
+#define ISCSI_OP_SCSI_TMFUNC_RSP 0x22
+#define ISCSI_OP_LOGIN_RSP 0x23
+#define ISCSI_OP_TEXT_RSP 0x24
+#define ISCSI_OP_SCSI_DATA_IN 0x25
+#define ISCSI_OP_LOGOUT_RSP 0x26
+#define ISCSI_OP_R2T 0x31
+#define ISCSI_OP_ASYNC_EVENT 0x32
+#define ISCSI_OP_REJECT 0x3f
+
+struct iscsi_ahs_hdr {
+ __be16 ahslength;
+ uint8_t ahstype;
+ uint8_t ahspec[5];
+};
+
+#define ISCSI_AHSTYPE_CDB 1
+#define ISCSI_AHSTYPE_RLENGTH 2
+
+/* iSCSI PDU Header */
+struct iscsi_cmd {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 data_length;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t cdb[16]; /* SCSI Command Block */
+ /* Additional Data (Command Dependent) */
+};
+
+/* Command PDU flags */
+#define ISCSI_FLAG_CMD_FINAL 0x80
+#define ISCSI_FLAG_CMD_READ 0x40
+#define ISCSI_FLAG_CMD_WRITE 0x20
+#define ISCSI_FLAG_CMD_ATTR_MASK 0x07 /* 3 bits */
+
+/* SCSI Command Attribute values */
+#define ISCSI_ATTR_UNTAGGED 0
+#define ISCSI_ATTR_SIMPLE 1
+#define ISCSI_ATTR_ORDERED 2
+#define ISCSI_ATTR_HEAD_OF_QUEUE 3
+#define ISCSI_ATTR_ACA 4
+
+struct iscsi_rlength_ahdr {
+ __be16 ahslength;
+ uint8_t ahstype;
+ uint8_t reserved;
+ __be32 read_length;
+};
+
+/* SCSI Response Header */
+struct iscsi_cmd_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response;
+ uint8_t cmd_status;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd1;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 exp_datasn;
+ __be32 bi_residual_count;
+ __be32 residual_count;
+ /* Response or Sense Data (optional) */
+};
+
+/* Command Response PDU flags */
+#define ISCSI_FLAG_CMD_BIDI_OVERFLOW 0x10
+#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW 0x08
+#define ISCSI_FLAG_CMD_OVERFLOW 0x04
+#define ISCSI_FLAG_CMD_UNDERFLOW 0x02
+
+/* iSCSI Status values. Valid if Rsp Selector bit is not set */
+#define ISCSI_STATUS_CMD_COMPLETED 0
+#define ISCSI_STATUS_TARGET_FAILURE 1
+#define ISCSI_STATUS_SUBSYS_FAILURE 2
+
+/* Asynchronous Event Header */
+struct iscsi_async {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ uint8_t rsvd4[8];
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t async_event;
+ uint8_t async_vcode;
+ __be16 param1;
+ __be16 param2;
+ __be16 param3;
+ uint8_t rsvd5[4];
+};
+
+/* iSCSI Event Codes */
+#define ISCSI_ASYNC_MSG_SCSI_EVENT 0
+#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT 1
+#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION 2
+#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS 3
+#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION 4
+#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC 255
+
+/* NOP-Out Message */
+struct iscsi_nopout {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd4[16];
+};
+
+/* NOP-In Message */
+struct iscsi_nopin {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd4[12];
+};
+
+/* SCSI Task Management Message Header */
+struct iscsi_tm {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd1[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rtt; /* Reference Task Tag */
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ __be32 refcmdsn;
+ __be32 exp_datasn;
+ uint8_t rsvd2[8];
+};
+
+#define ISCSI_FLAG_TM_FUNC_MASK 0x7F
+
+/* Function values */
+#define ISCSI_TM_FUNC_ABORT_TASK 1
+#define ISCSI_TM_FUNC_ABORT_TASK_SET 2
+#define ISCSI_TM_FUNC_CLEAR_ACA 3
+#define ISCSI_TM_FUNC_CLEAR_TASK_SET 4
+#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET 5
+#define ISCSI_TM_FUNC_TARGET_WARM_RESET 6
+#define ISCSI_TM_FUNC_TARGET_COLD_RESET 7
+#define ISCSI_TM_FUNC_TASK_REASSIGN 8
+
+/* SCSI Task Management Response Header */
+struct iscsi_tm_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response; /* see Response values below */
+ uint8_t qualifier;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd2[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rtt; /* Reference Task Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd3[12];
+};
+
+/* Response values */
+#define ISCSI_TMF_RSP_COMPLETE 0x00
+#define ISCSI_TMF_RSP_NO_TASK 0x01
+#define ISCSI_TMF_RSP_NO_LUN 0x02
+#define ISCSI_TMF_RSP_TASK_ALLEGIANT 0x03
+#define ISCSI_TMF_RSP_NO_FAILOVER 0x04
+#define ISCSI_TMF_RSP_NOT_SUPPORTED 0x05
+#define ISCSI_TMF_RSP_AUTH_FAILED 0x06
+#define ISCSI_TMF_RSP_REJECTED 0xff
+
+/* Ready To Transfer Header */
+struct iscsi_r2t_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 r2tsn;
+ __be32 data_offset;
+ __be32 data_length;
+};
+
+/* SCSI Data Hdr */
+struct iscsi_data {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 rsvd4;
+ __be32 exp_statsn;
+ __be32 rsvd5;
+ __be32 datasn;
+ __be32 offset;
+ __be32 rsvd6;
+ /* Payload */
+};
+
+/* SCSI Data Response Hdr */
+struct iscsi_data_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2;
+ uint8_t cmd_status;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 datasn;
+ __be32 offset;
+ __be32 residual_count;
+};
+
+/* Data Response PDU flags */
+#define ISCSI_FLAG_DATA_ACK 0x40
+#define ISCSI_FLAG_DATA_OVERFLOW 0x04
+#define ISCSI_FLAG_DATA_UNDERFLOW 0x02
+#define ISCSI_FLAG_DATA_STATUS 0x01
+
+/* Text Header */
+struct iscsi_text {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd4[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd5[16];
+ /* Text - key=value pairs */
+};
+
+#define ISCSI_FLAG_TEXT_CONTINUE 0x40
+
+/* Text Response Header */
+struct iscsi_text_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd4[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd5[12];
+ /* Text Response - key:value pairs */
+};
+
+/* Login Header */
+struct iscsi_login {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t max_version; /* Max. version supported */
+ uint8_t min_version; /* Min. version supported */
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t isid[6]; /* Initiator Session ID */
+ __be16 tsih; /* Target Session Handle */
+ __be32 itt; /* Initiator Task Tag */
+ __be16 cid;
+ __be16 rsvd3;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd5[16];
+};
+
+/* Login PDU flags */
+#define ISCSI_FLAG_LOGIN_TRANSIT 0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE 0x40
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK 0x0C /* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK 0x03 /* 2 bits */
+
+#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
+ ((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
+#define ISCSI_LOGIN_NEXT_STAGE(flags) \
+ (flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)
+
+/* Login Response Header */
+struct iscsi_login_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t max_version; /* Max. version supported */
+ uint8_t active_version; /* Active version */
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t isid[6]; /* Initiator Session ID */
+ __be16 tsih; /* Target Session Handle */
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd3;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t status_class; /* see Login RSP ststus classes below */
+ uint8_t status_detail; /* see Login RSP Status details below */
+ uint8_t rsvd4[10];
+};
+
+/* Login stage (phase) codes for CSG, NSG */
+#define ISCSI_INITIAL_LOGIN_STAGE -1
+#define ISCSI_SECURITY_NEGOTIATION_STAGE 0
+#define ISCSI_OP_PARMS_NEGOTIATION_STAGE 1
+#define ISCSI_FULL_FEATURE_PHASE 3
+
+/* Login Status response classes */
+#define ISCSI_STATUS_CLS_SUCCESS 0x00
+#define ISCSI_STATUS_CLS_REDIRECT 0x01
+#define ISCSI_STATUS_CLS_INITIATOR_ERR 0x02
+#define ISCSI_STATUS_CLS_TARGET_ERR 0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_LOGIN_STATUS_ACCEPT 0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP 0x01
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM 0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_LOGIN_STATUS_INIT_ERR 0x00
+#define ISCSI_LOGIN_STATUS_AUTH_FAILED 0x01
+#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN 0x02
+#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND 0x03
+#define ISCSI_LOGIN_STATUS_TGT_REMOVED 0x04
+#define ISCSI_LOGIN_STATUS_NO_VERSION 0x05
+#define ISCSI_LOGIN_STATUS_ISID_ERROR 0x06
+#define ISCSI_LOGIN_STATUS_MISSING_FIELDS 0x07
+#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED 0x08
+#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE 0x09
+#define ISCSI_LOGIN_STATUS_NO_SESSION 0x0a
+#define ISCSI_LOGIN_STATUS_INVALID_REQUEST 0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_LOGIN_STATUS_TARGET_ERROR 0x00
+#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE 0x01
+#define ISCSI_LOGIN_STATUS_NO_RESOURCES 0x02
+
+/* Logout Header */
+struct iscsi_logout {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd1[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd2[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be16 cid;
+ uint8_t rsvd3[2];
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd4[16];
+};
+
+/* Logout PDU flags */
+#define ISCSI_FLAG_LOGOUT_REASON_MASK 0x7F
+
+/* logout reason_code values */
+
+#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0
+#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1
+#define ISCSI_LOGOUT_REASON_RECOVERY 2
+#define ISCSI_LOGOUT_REASON_AEN_REQUEST 3
+
+/* Logout Response Header */
+struct iscsi_logout_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response; /* see Logout response values below */
+ uint8_t rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd3[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd4;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 rsvd5;
+ __be16 t2wait;
+ __be16 t2retain;
+ __be32 rsvd6;
+};
+
+/* logout response status values */
+
+#define ISCSI_LOGOUT_SUCCESS 0
+#define ISCSI_LOGOUT_CID_NOT_FOUND 1
+#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED 2
+#define ISCSI_LOGOUT_CLEANUP_FAILED 3
+
+/* SNACK Header */
+struct iscsi_snack {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[14];
+ __be32 itt;
+ __be32 begrun;
+ __be32 runlength;
+ __be32 exp_statsn;
+ __be32 rsvd3;
+ __be32 exp_datasn;
+ uint8_t rsvd6[8];
+};
+
+/* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */
+
+/* Reject Message Header */
+struct iscsi_reject {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t reason;
+ uint8_t rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd3[8];
+ __be32 ffffffff;
+ uint8_t rsvd4[4];
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 datasn;
+ uint8_t rsvd5[8];
+ /* Text - Rejected hdr */
+};
+
+/* Reason for Reject */
+#define ISCSI_REASON_CMD_BEFORE_LOGIN 1
+#define ISCSI_REASON_DATA_DIGEST_ERROR 2
+#define ISCSI_REASON_DATA_SNACK_REJECT 3
+#define ISCSI_REASON_PROTOCOL_ERROR 4
+#define ISCSI_REASON_CMD_NOT_SUPPORTED 5
+#define ISCSI_REASON_IMM_CMD_REJECT 6
+#define ISCSI_REASON_TASK_IN_PROGRESS 7
+#define ISCSI_REASON_INVALID_SNACK 8
+#define ISCSI_REASON_BOOKMARK_INVALID 9
+#define ISCSI_REASON_BOOKMARK_NO_RESOURCES 10
+#define ISCSI_REASON_NEGOTIATION_RESET 11
+
+/* Max. number of Key=Value pairs in a text message */
+#define MAX_KEY_VALUE_PAIRS 8192
+
+/* maximum length for text keys/values */
+#define KEY_MAXLEN 64
+#define VALUE_MAXLEN 255
+#define TARGET_NAME_MAXLEN VALUE_MAXLEN
+
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192
+
+/************************* RFC 3720 End *****************************/
+
+#endif /* ISCSI_PROTO_H */
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_device.h b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_device.h
new file mode 100644
index 0000000..f353e0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_device.h
@@ -0,0 +1,19 @@
+#ifndef _SCSI_SCSI_DEVICE_H_BACKPORT
+#define _SCSI_SCSI_DEVICE_H_BACKPORT
+
+#include_next <scsi/scsi_device.h>
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+struct scsi_lun;
+
+extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void starget_for_each_device(struct scsi_target *, void *,
+ void (*fn)(struct scsi_device *, void *));
+#endif /* _SCSI_SCSI_DEVICE_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_host.h b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_host.h
new file mode 100644
index 0000000..b7e019b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_host.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_HOST_H_BACKPORT
+#define _SCSI_SCSI_HOST_H_BACKPORT
+
+#include_next <scsi/scsi_host.h>
+
+#define scsi_queue_work(shost, work) schedule_work(work)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_transport.h b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..99c2b12
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_transport.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_TRANSPORT_H_BACKPORT
+#define _SCSI_SCSI_TRANSPORT_H_BACKPORT
+
+#include_next <scsi/scsi_transport.h>
+
+#include <linux/transport_class.h>
+
+#endif /* _SCSI_SCSI_TRANSPORT_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/attribute_container.c b/kernel_addons/backport/2.6.9_U3/include/src/attribute_container.c
new file mode 100644
index 0000000..44948d1
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/attribute_container.c
@@ -0,0 +1,438 @@
+/*
+ * attribute_container.c - implementation of a simple container for classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to enable a device to be attached to an
+ * aritrary numer of classes without having to allocate storage for them.
+ * Instead, the contained classes select the devices they need to attach
+ * to via a matching function.
+ */
+
+#include <linux/attribute_container.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include "base.h"
+
+/* This is a private structure used to tie the classdev and the
+ * container .. it should never be visible outside this file */
+struct internal_container {
+ struct klist_node node;
+ struct attribute_container *cont;
+ struct class_device classdev;
+};
+
+static void internal_container_klist_get(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_put(&ic->classdev);
+}
+
+
+/**
+ * attribute_container_classdev_to_container - given a classdev, return the container
+ *
+ * @classdev: the class device created by attribute_container_add_device.
+ *
+ * Returns the container associated with this classdev.
+ */
+struct attribute_container *
+attribute_container_classdev_to_container(struct class_device *classdev)
+{
+ struct internal_container *ic =
+ container_of(classdev, struct internal_container, classdev);
+ return ic->cont;
+}
+EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+
+static struct list_head attribute_container_list;
+
+static DECLARE_MUTEX(attribute_container_mutex);
+
+/**
+ * attribute_container_register - register an attribute container
+ *
+ * @cont: The container to register. This must be allocated by the
+ * callee and should also be zeroed by it.
+ */
+int
+attribute_container_register(struct attribute_container *cont)
+{
+ INIT_LIST_HEAD(&cont->node);
+ klist_init(&cont->containers,internal_container_klist_get,
+ internal_container_klist_put);
+
+ down(&attribute_container_mutex);
+ list_add_tail(&cont->node, &attribute_container_list);
+ up(&attribute_container_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_register);
+
+/**
+ * attribute_container_unregister - remove a container registration
+ *
+ * @cont: previously registered container to remove
+ */
+int
+attribute_container_unregister(struct attribute_container *cont)
+{
+ int retval = -EBUSY;
+ down(&attribute_container_mutex);
+ spin_lock(&cont->containers.k_lock);
+ if (!list_empty(&cont->containers.k_list))
+ goto out;
+ retval = 0;
+ list_del(&cont->node);
+ out:
+ spin_unlock(&cont->containers.k_lock);
+ up(&attribute_container_mutex);
+ return retval;
+
+}
+EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+/* private function used as class release */
+static void attribute_container_release(struct class_device *classdev)
+{
+ struct internal_container *ic
+ = container_of(classdev, struct internal_container, classdev);
+ struct device *dev = classdev->dev;
+
+ kfree(ic);
+ put_device(dev);
+}
+
+/**
+ * attribute_container_add_device - see if any container is interested in dev
+ *
+ * @dev: device to add attributes to
+ * @fn: function to trigger addition of class device.
+ *
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container). If no
+ * fn is provided, the code will simply register the class device via
+ * class_device_add. If a function is provided, it is expected to add
+ * the class device at the appropriate time. One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time. To do this, call this routine for
+ * allocation and initialisation and then use
+ * attribute_container_device_trigger() to call class_device_add() on
+ * it. Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+void
+attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+
+ if (attribute_container_no_classdevs(cont))
+ continue;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
+ if (!ic) {
+ dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+ continue;
+ }
+
+ ic->cont = cont;
+ class_device_initialize(&ic->classdev);
+ ic->classdev.dev = get_device(dev);
+ ic->classdev.class = cont->class;
+ cont->class->release = attribute_container_release;
+ strcpy(ic->classdev.class_id, dev->bus_id);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else
+ attribute_container_add_class_device(&ic->classdev);
+ klist_add_tail(&ic->node, &cont->containers);
+ }
+ up(&attribute_container_mutex);
+}
+
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+ for (klist_iter_init(head, iter); (pos = ({ \
+ struct klist_node *n = klist_next(iter); \
+ n ? container_of(n, typeof(*pos), member) : \
+ ({ klist_iter_exit(iter) ; NULL; }); \
+ }) ) != NULL; )
+
+
+/**
+ * attribute_container_remove_device - make device eligible for removal.
+ *
+ * @dev: The generic device
+ * @fn: A function to call to remove the device
+ *
+ * This routine triggers device removal. If fn is NULL, then it is
+ * simply done via class_device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released). If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+ * class_device_del() and then use
+ * attribute_container_device_trigger() to do the final put on the
+ * classdev.
+ */
+void
+attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ if (attribute_container_no_classdevs(cont))
+ continue;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (dev != ic->classdev.dev)
+ continue;
+ klist_del(&ic->node);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else {
+ attribute_container_remove_attrs(&ic->classdev);
+ class_device_unregister(&ic->classdev);
+ }
+ }
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_device_trigger - execute a trigger for each matching classdev
+ *
+ * @dev: The generic device to run the trigger for
+ * @fn the function to execute for each classdev.
+ *
+ * This funcion is for executing a trigger when you need to know both
+ * the container and the classdev. If you only care about the
+ * container, then use attribute_container_trigger() instead.
+ */
+void
+attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ if (attribute_container_no_classdevs(cont)) {
+ fn(cont, dev, NULL);
+ continue;
+ }
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (dev == ic->classdev.dev)
+ fn(cont, dev, &ic->classdev);
+ }
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_trigger - trigger a function for each matching container
+ *
+ * @dev: The generic device to activate the trigger for
+ * @fn: the function to trigger
+ *
+ * This routine triggers a function that only needs to know the
+ * matching containers (not the classdev) associated with a device.
+ * It is more lightweight than attribute_container_device_trigger, so
+ * should be used in preference unless the triggering function
+ * actually needs to know the classdev.
+ */
+void
+attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ if (cont->match(cont, dev))
+ fn(cont, dev);
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_add_attrs - add attributes
+ *
+ * @classdev: The class device
+ *
+ * This simply creates all the class device sysfs files from the
+ * attributes listed in the container
+ */
+int
+attribute_container_add_attrs(struct class_device *classdev)
+{
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+ struct class_device_attribute **attrs = cont->attrs;
+ int i, error;
+
+ if (!attrs)
+ return 0;
+
+ for (i = 0; attrs[i]; i++) {
+ error = class_device_create_file(classdev, attrs[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+/**
+ * attribute_container_add_class_device - same function as class_device_add
+ *
+ * @classdev: the class device to add
+ *
+ * This performs essentially the same function as class_device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+int
+attribute_container_add_class_device(struct class_device *classdev)
+{
+ int error = class_device_add(classdev);
+ if (error)
+ return error;
+ return attribute_container_add_attrs(classdev);
+}
+
+/**
+ * attribute_container_add_class_device_adapter - simple adapter for triggers
+ *
+ * This function is identical to attribute_container_add_class_device except
+ * that it is designed to be called from the triggers
+ */
+int
+attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ return attribute_container_add_class_device(classdev);
+}
+
+/**
+ * attribute_container_remove_attrs - remove any attribute files
+ *
+ * @classdev: The class device to remove the files from
+ *
+ */
+void
+attribute_container_remove_attrs(struct class_device *classdev)
+{
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+ struct class_device_attribute **attrs = cont->attrs;
+ int i;
+
+ if (!attrs)
+ return;
+
+ for (i = 0; attrs[i]; i++)
+ class_device_remove_file(classdev, attrs[i]);
+}
+
+/**
+ * attribute_container_class_device_del - equivalent of class_device_del
+ *
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+ * class_device_del.
+ */
+void
+attribute_container_class_device_del(struct class_device *classdev)
+{
+ attribute_container_remove_attrs(classdev);
+ class_device_del(classdev);
+}
+
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont: the container
+ * @dev: the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct class_device *cdev = NULL;
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (ic->classdev.dev == dev) {
+ cdev = &ic->classdev;
+ /* FIXME: must exit iterator then break */
+ klist_iter_exit(&iter);
+ break;
+ }
+ }
+
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
+int
+attribute_container_init(void)
+{
+ INIT_LIST_HEAD(&attribute_container_list);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_init);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/base.h b/kernel_addons/backport/2.6.9_U3/include/src/base.h
new file mode 100644
index 0000000..a5f8936
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/base.h
@@ -0,0 +1 @@
+extern int attribute_container_init(void);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/init.c b/kernel_addons/backport/2.6.9_U3/include/src/init.c
new file mode 100644
index 0000000..15f0bc6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/init.c
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
+
+/**
+ * driver_init - initialize driver model.
+ *
+ * Call the driver model init functions to initialize their
+ * subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+ attribute_container_init();
+}
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/klist.c b/kernel_addons/backport/2.6.9_U3/include/src/klist.c
new file mode 100644
index 0000000..3b29ebc
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/klist.c
@@ -0,0 +1,287 @@
+/*
+ * klist.c - Routines for manipulating klists.
+ *
+ *
+ * This klist interface provides a couple of structures that wrap around
+ * struct list_head to provide explicit list "head" (struct klist) and
+ * list "node" (struct klist_node) objects. For struct klist, a spinlock
+ * is included that protects access to the actual list itself. struct
+ * klist_node provides a pointer to the klist that owns it and a kref
+ * reference count that indicates the number of current users of that node
+ * in the list.
+ *
+ * The entire point is to provide an interface for iterating over a list
+ * that is safe and allows for modification of the list during the
+ * iteration (e.g. insertion and removal), including modification of the
+ * current node on the list.
+ *
+ * It works using a 3rd object type - struct klist_iter - that is declared
+ * and initialized before an iteration. klist_next() is used to acquire the
+ * next element in the list. It returns NULL if there are no more items.
+ * Internally, that routine takes the klist's lock, decrements the reference
+ * count of the previous klist_node and increments the count of the next
+ * klist_node. It then drops the lock and returns.
+ *
+ * There are primitives for adding and removing nodes to/from a klist.
+ * When deleting, klist_del() will simply decrement the reference count.
+ * Only when the count goes to 0 is the node removed from the list.
+ * klist_remove() will try to delete the node from the list and block
+ * until it is actually removed. This is useful for objects (like devices)
+ * that have been removed from the system and must be freed (but must wait
+ * until all accessors have finished).
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ * klist_init - Initialize a klist structure.
+ * @k: The klist we're initializing.
+ * @get: The get function for the embedding object (NULL if none)
+ * @put: The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure. If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
+ */
+
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *))
+{
+ INIT_LIST_HEAD(&k->k_list);
+ spin_lock_init(&k->k_lock);
+ k->get = get;
+ k->put = put;
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add_tail(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+ INIT_LIST_HEAD(&n->n_node);
+ init_completion(&n->n_removed);
+ kref_init(&n->n_ref);
+ n->n_klist = k;
+ if (k->get)
+ k->get(n);
+}
+
+
+/**
+ * klist_add_head - Initialize a klist_node and add it to front.
+ * @n: node we're adding.
+ * @k: klist it's going on.
+ */
+
+void klist_add_head(struct klist_node * n, struct klist * k)
+{
+ klist_node_init(k, n);
+ add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ * klist_add_tail - Initialize a klist_node and add it to back.
+ * @n: node we're adding.
+ * @k: klist it's going on.
+ */
+
+void klist_add_tail(struct klist_node * n, struct klist * k)
+{
+ klist_node_init(k, n);
+ add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+ struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+
+ list_del(&n->n_node);
+ complete(&n->n_removed);
+ n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+ return kref_put_new(&n->n_ref, klist_release);
+}
+
+
+/**
+ * klist_del - Decrement the reference count of node and try to remove.
+ * @n: node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+ struct klist * k = n->n_klist;
+ void (*put)(struct klist_node *) = k->put;
+
+ spin_lock(&k->k_lock);
+ if (!klist_dec_and_del(n))
+ put = NULL;
+ spin_unlock(&k->k_lock);
+ if (put)
+ put(n);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ * klist_remove - Decrement the refcount of node and wait for it to go away.
+ * @n: node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+ klist_del(n);
+ wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ * klist_node_attached - Say whether a node is bound to a list or not.
+ * @n: Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+ return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ * klist_iter_init_node - Initialize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter we're filling.
+ * @n: node to start with.
+ *
+ * Similar to klist_iter_init(), but starts the action off with @n,
+ * instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+ i->i_klist = k;
+ i->i_head = &k->k_list;
+ i->i_cur = n;
+ if (n)
+ kref_get(&n->n_ref);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ * klist_iter_init - Iniitalize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter structure we're filling.
+ *
+ * Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+ klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ * klist_iter_exit - Finish a list iteration.
+ * @i: Iterator structure.
+ *
+ * Must be called when done iterating over list, as it decrements the
+ * refcount of the current node. Necessary in case iteration exited before
+ * the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+ if (i->i_cur) {
+ klist_del(i->i_cur);
+ i->i_cur = NULL;
+ }
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+ return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ * klist_next - Ante up next node in list.
+ * @i: Iterator structure.
+ *
+ * First grab list lock. Decrement the reference count of the previous
+ * node, if there was one. Grab the next node, increment its reference
+ * count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+ struct list_head * next;
+ struct klist_node * lnode = i->i_cur;
+ struct klist_node * knode = NULL;
+ void (*put)(struct klist_node *) = i->i_klist->put;
+
+ spin_lock(&i->i_klist->k_lock);
+ if (lnode) {
+ next = lnode->n_node.next;
+ if (!klist_dec_and_del(lnode))
+ put = NULL;
+ } else
+ next = i->i_head->next;
+
+ if (next != i->i_head) {
+ knode = to_klist_node(next);
+ kref_get(&knode->n_ref);
+ }
+ i->i_cur = knode;
+ spin_unlock(&i->i_klist->k_lock);
+ if (put && lnode)
+ put(lnode);
+ return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/kref_new.c b/kernel_addons/backport/2.6.9_U3/include/src/kref_new.c
new file mode 100644
index 0000000..d45bb3f
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/kref_new.c
@@ -0,0 +1,29 @@
+#include <linux/kref.h>
+#include <linux/module.h>
+
+/**
+ * kref_put - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ * last reference to the object is released.
+ * This pointer is required, and it is not acceptable to pass kfree
+ * in as this function.
+ *
+ * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0. Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory. Only use the return value if you want to see if the kref is now
+ * gone, not present.
+ */
+int kref_put_new(struct kref *kref, void (*release)(struct kref *kref))
+{
+ WARN_ON(release == NULL);
+ WARN_ON(release == (void (*)(struct kref *))kfree);
+
+ if (atomic_dec_and_test(&kref->refcount)) {
+ release(kref);
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(kref_put_new);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/scsi.c b/kernel_addons/backport/2.6.9_U3/include/src/scsi.c
new file mode 100644
index 0000000..8c833c0
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/scsi.c
@@ -0,0 +1,50 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/unistd.h>
+#include <linux/spinlock.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * starget_for_each_device - helper to walk all devices of a target
+ * @starget: target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost. The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+ void (*fn)(struct scsi_device *, void *))
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct scsi_device *sdev;
+
+ printk("%s: entry\n", __FUNCTION__);
+ shost_for_each_device(sdev, shost) {
+ if ((sdev->channel == starget->channel) &&
+ (sdev->id == starget->id))
+ fn(sdev, data);
+ }
+ printk("%s: exit\n", __FUNCTION__);
+}
+EXPORT_SYMBOL(starget_for_each_device);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/scsi_lib.c b/kernel_addons/backport/2.6.9_U3/include/src/scsi_lib.c
new file mode 100644
index 0000000..f53f824
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/scsi_lib.c
@@ -0,0 +1,166 @@
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+int scsi_is_target_device(const struct device *dev)
+{
+ char *str = dev->bus_id;
+
+ if (strncmp(str, "target", 6) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * scsi_internal_device_block - internal function to put a device
+ * temporarily into the SDEV_BLOCK state
+ * @sdev: device to block
+ *
+ * Block request made by scsi lld's to temporarily stop all
+ * scsi commands on the specified device. Called from interrupt
+ * or normal process context.
+ *
+ * Returns zero if successful or error if not
+ *
+ * Notes:
+ * This routine transitions the device to the SDEV_BLOCK state
+ * (which must be a legal transition). When the device is in this
+ * state, all commands are deferred until the scsi lld reenables
+ * the device with scsi_device_unblock or device_block_tmo fires.
+ * This routine assumes the host_lock is held on entry.
+ **/
+int
+scsi_internal_device_block(struct scsi_device *sdev)
+{
+ request_queue_t *q = sdev->request_queue;
+ unsigned long flags;
+ int err = 0;
+
+ err = scsi_device_set_state(sdev, SDEV_BLOCK);
+ if (err)
+ return err;
+
+ /*
+ * The device has transitioned to SDEV_BLOCK. Stop the
+ * block layer from calling the midlayer with this device's
+ * request queue.
+ */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+
+/**
+ * scsi_internal_device_unblock - resume a device after a block request
+ * @sdev: device to resume
+ *
+ * Called by scsi lld's or the midlayer to restart the device queue
+ * for the previously suspended scsi device. Called from interrupt or
+ * normal process context.
+ *
+ * Returns zero if successful or error if not.
+ *
+ * Notes:
+ * This routine transitions the device to the SDEV_RUNNING state
+ * (which must be a legal transition) allowing the midlayer to
+ * goose the queue for this device. This routine assumes the
+ * host_lock is held upon entry.
+ **/
+int
+scsi_internal_device_unblock(struct scsi_device *sdev)
+{
+ request_queue_t *q = sdev->request_queue;
+ int err;
+ unsigned long flags;
+
+
+ /*
+ * Try to transition the scsi device to SDEV_RUNNING
+ * and goose the device queue if successful.
+ */
+ err = scsi_device_set_state(sdev, SDEV_RUNNING);
+ if (err)
+ return err;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+
+ return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+ else
+ device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ else
+ device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+MODULE_LICENSE("GPL");
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/scsi_scan.c b/kernel_addons/backport/2.6.9_U3/include/src/scsi_scan.c
new file mode 100644
index 0000000..b7b7674
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/scsi_scan.c
@@ -0,0 +1,48 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+
+/**
+ * int_to_scsilun: reverts an int into a scsi_lun
+ * @int: integer to be reverted
+ * @scsilun: struct scsi_lun to be set.
+ *
+ * Description:
+ * Reverts the functionality of the scsilun_to_int, which packed
+ * an 8-byte lun value into an int. This routine unpacks the int
+ * back into the lun value.
+ * Note: the scsilun_to_int() routine does not truly handle all
+ * 8bytes of the lun value. This functions restores only as much
+ * as was set by the routine.
+ *
+ * Notes:
+ * Given an integer : 0x0b030a04, this function returns a
+ * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *
+ **/
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+ int i;
+
+ memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+ for (i = 0; i < sizeof(lun); i += 2) {
+ scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+ scsilun->scsi_lun[i+1] = lun & 0xFF;
+ lun = lun >> 16;
+ }
+}
+EXPORT_SYMBOL(int_to_scsilun);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/transport_class.c b/kernel_addons/backport/2.6.9_U3/include/src/transport_class.c
new file mode 100644
index 0000000..f25e7c6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/transport_class.c
@@ -0,0 +1,280 @@
+/*
+ * transport_class.c - implementation of generic transport classes
+ * using attribute_containers
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to allow any "device controller" (which
+ * would most often be a Host Bus Adapter to use the services of one
+ * or more tranport classes for performing transport specific
+ * services. Transport specific services are things that the generic
+ * command layer doesn't want to know about (speed settings, line
+ * condidtioning, etc), but which the user might be interested in.
+ * Thus, the HBA's use the routines exported by the transport classes
+ * to perform these functions. The transport classes export certain
+ * values to the user via sysfs using attribute containers.
+ *
+ * Note: because not every HBA will care about every transport
+ * attribute, there's a many to one relationship that goes like this:
+ *
+ * transport class<-----attribute container<----class device
+ *
+ * Usually the attribute container is per-HBA, but the design doesn't
+ * mandate that. Although most of the services will be specific to
+ * the actual external storage connection used by the HBA, the generic
+ * transport class is framed entirely in terms of generic devices to
+ * allow it to be used by any physical HBA in the system.
+ */
+#include <linux/attribute_container.h>
+#include <linux/transport_class.h>
+
+/**
+ * transport_class_register - register an initial transport class
+ *
+ * @tclass: a pointer to the transport class structure to be initialised
+ *
+ * The transport class contains an embedded class which is used to
+ * identify it. The caller should initialise this structure with
+ * zeros and then generic class must have been initialised with the
+ * actual transport class unique name. There's a macro
+ * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
+ * be registered).
+ *
+ * Returns 0 on success or error on failure.
+ */
+int transport_class_register(struct transport_class *tclass)
+{
+ return class_register(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_register);
+
+/**
+ * transport_class_unregister - unregister a previously registered class
+ *
+ * @tclass: The transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the transport
+ * class.
+ */
+void transport_class_unregister(struct transport_class *tclass)
+{
+ class_unregister(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ /* do nothing */
+ return 0;
+}
+
+/**
+ * anon_transport_class_register - register an anonymous class
+ *
+ * @atc: The anon transport class to register
+ *
+ * The anonymous transport class contains both a transport class and a
+ * container. The idea of an anonymous class is that it never
+ * actually has any device attributes associated with it (and thus
+ * saves on container storage). So it can only be used for triggering
+ * events. Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
+ * initialise the anon transport class storage.
+ */
+int anon_transport_class_register(struct anon_transport_class *atc)
+{
+ int error;
+ atc->container.class = &atc->tclass.class;
+ attribute_container_set_no_classdevs(&atc->container);
+ error = attribute_container_register(&atc->container);
+ if (error)
+ return error;
+ atc->tclass.setup = anon_transport_dummy_function;
+ atc->tclass.remove = anon_transport_dummy_function;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_register);
+
+/**
+ * anon_transport_class_unregister - unregister an anon class
+ *
+ * @atc: Pointer to the anon transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the anon
+ * transport class.
+ */
+void anon_transport_class_unregister(struct anon_transport_class *atc)
+{
+ attribute_container_unregister(&atc->container);
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+static int transport_setup_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+ if (tclass->setup)
+ tclass->setup(tcont, dev, classdev);
+
+ return 0;
+}
+
+/**
+ * transport_setup_device - declare a new dev for transport class association
+ * but don't make it visible yet.
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus). This
+ * routine is simply a trigger point to see if any set of transport
+ * classes wishes to associate with the added device. This allocates
+ * storage for the class device and initialises it, but does not yet
+ * add it to the system or add attributes to it (you do this with
+ * transport_add_device). If you have no need for a separate setup
+ * and add operations, use transport_register_device (see
+ * transport_class.h).
+ */
+
+void transport_setup_device(struct device *dev)
+{
+ attribute_container_add_device(dev, transport_setup_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_setup_device);
+
+static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+
+ if (!error && tcont->statistics)
+ error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+ return error;
+}
+
+
+/**
+ * transport_add_device - declare a new dev for transport class association
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus). This
+ * routine is simply a trigger point used to add the device to the
+ * system and register attributes for it.
+ */
+
+void transport_add_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_add_class_device);
+}
+EXPORT_SYMBOL_GPL(transport_add_device);
+
+static int transport_configure(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+ if (tclass->configure)
+ tclass->configure(tcont, dev, cdev);
+
+ return 0;
+}
+
+/**
+ * transport_configure_device - configure an already set up device
+ *
+ * @dev: generic device representing device to be configured
+ *
+ * The idea of configure is simply to provide a point within the setup
+ * process to allow the transport class to extract information from a
+ * device after it has been setup. This is used in SCSI because we
+ * have to have a setup device to begin using the HBA, but after we
+ * send the initial inquiry, we use configure to extract the device
+ * parameters. The device need not have been added to be configured.
+ */
+void transport_configure_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_configure);
+}
+EXPORT_SYMBOL_GPL(transport_configure_device);
+
+static int transport_remove_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove)
+ tclass->remove(tcont, dev, classdev);
+
+ if (tclass->remove != anon_transport_dummy_function) {
+ if (tcont->statistics)
+ sysfs_remove_group(&classdev->kobj, tcont->statistics);
+ attribute_container_class_device_del(classdev);
+ }
+
+ return 0;
+}
+
+
+/**
+ * transport_remove_device - remove the visibility of a device
+ *
+ * @dev: generic device to remove
+ *
+ * This call removes the visibility of the device (to the user from
+ * sysfs), but does not destroy it. To eliminate a device entirely
+ * you must also call transport_destroy_device. If you don't need to
+ * do remove and destroy as separate operations, use
+ * transport_unregister_device() (see transport_class.h) which will
+ * perform both calls for you.
+ */
+void transport_remove_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_remove_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_remove_device);
+
+static void transport_destroy_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove != anon_transport_dummy_function)
+ class_device_put(classdev);
+}
+
+
+/**
+ * transport_destroy_device - destroy a removed device
+ *
+ * @dev: device to eliminate from the transport class.
+ *
+ * This call triggers the elimination of storage associated with the
+ * transport classdev. Note: all it really does is relinquish a
+ * reference to the classdev. The memory will not be freed until the
+ * last reference goes to zero. Note also that the classdev retains a
+ * reference count on dev, so dev too will remain for as long as the
+ * transport class device remains around.
+ */
+void transport_destroy_device(struct device *dev)
+{
+ attribute_container_remove_device(dev, transport_destroy_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_destroy_device);
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/attribute_container.h b/kernel_addons/backport/2.6.9_U4/include/linux/attribute_container.h
new file mode 100644
index 0000000..93bfb0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/attribute_container.h
@@ -0,0 +1,71 @@
+/*
+ * class_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _ATTRIBUTE_CONTAINER_H_
+#define _ATTRIBUTE_CONTAINER_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
+
+struct attribute_container {
+ struct list_head node;
+ struct klist containers;
+ struct class *class;
+ struct class_device_attribute **attrs;
+ int (*match)(struct attribute_container *, struct device *);
+#define ATTRIBUTE_CONTAINER_NO_CLASSDEVS 0x01
+ unsigned long flags;
+};
+
+static inline int
+attribute_container_no_classdevs(struct attribute_container *atc)
+{
+ return atc->flags & ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+static inline void
+attribute_container_set_no_classdevs(struct attribute_container *atc)
+{
+ atc->flags |= ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+int attribute_container_register(struct attribute_container *cont);
+int attribute_container_unregister(struct attribute_container *cont);
+void attribute_container_create_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *));
+int attribute_container_add_attrs(struct class_device *classdev);
+int attribute_container_add_class_device(struct class_device *classdev);
+int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev);
+void attribute_container_remove_attrs(struct class_device *classdev);
+void attribute_container_class_device_del(struct class_device *classdev);
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/crypto.h b/kernel_addons/backport/2.6.9_U4/include/linux/crypto.h
new file mode 100644
index 0000000..aecccde
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/crypto.h
@@ -0,0 +1,11 @@
+#ifndef LINUX_CRYPTO_BACKPORT_H
+#define LINUX_CRYPTO_BACKPORT_H
+
+#include_next <linux/crypto.h>
+
+#define crypto_hash_init(desc) crypto_digest_init(*desc)
+#define crypto_hash_digest(desc, sg, nbytes, out) crypto_digest_digest(*desc, sg, 1, out)
+#define crypto_hash_update(desc, sg, nbytes) crypto_digest_update(*desc, sg, 1)
+#define crypto_hash_final(desc, out) crypto_digest_final(*desc, out)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h b/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h
index a37dcd5..02a5907 100644
--- a/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h
@@ -4,4 +4,7 @@ #define BACKPORT_KERNEL_H_2_6_19
#include_next <linux/kernel.h>
#include <linux/log2.h>
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+
#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h b/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h
index 48eccd8..2b94461 100644
--- a/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h
@@ -25,6 +25,7 @@ #ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <linux/gfp.h>
struct kfifo {
unsigned char *buffer; /* the buffer holding the data */
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/klist.h b/kernel_addons/backport/2.6.9_U4/include/linux/klist.h
new file mode 100644
index 0000000..7407125
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/klist.h
@@ -0,0 +1,61 @@
+/*
+ * klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ * Implementations are found in lib/klist.c
+ *
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is rleased under the GPL v2.
+ */
+
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+struct klist_node;
+struct klist {
+ spinlock_t k_lock;
+ struct list_head k_list;
+ void (*get)(struct klist_node *);
+ void (*put)(struct klist_node *);
+};
+
+
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *));
+
+struct klist_node {
+ struct klist * n_klist;
+ struct list_head n_node;
+ struct kref n_ref;
+ struct completion n_removed;
+};
+
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+ struct klist * i_klist;
+ struct list_head * i_head;
+ struct klist_node * i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
+ struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/memory.h b/kernel_addons/backport/2.6.9_U4/include/linux/memory.h
new file mode 100644
index 0000000..654ef55
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/memory.h
@@ -0,0 +1,89 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+ unsigned long phys_index;
+ unsigned long state;
+ /*
+ * This serializes all state change requests. It isn't
+ * held during creation because the control files are
+ * created long after the critical areas during
+ * initialization.
+ */
+ struct semaphore state_sem;
+ int phys_device; /* to which fru does this belong? */
+ void *hw; /* optional pointer to fw/hw data */
+ int (*phys_callback)(struct memory_block *);
+ struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define MEM_ONLINE (1<<0) /* exposed to userspace */
+#define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */
+#define MEM_OFFLINE (1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid. The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working. Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define MEM_MAPPING_INVALID (1<<3)
+
+struct notifier_block;
+struct mem_section;
+
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int memory_dev_init(void)
+{
+ return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
+
+#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
+
+
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
+#define hotplug_memory_notifier(fn, pri) { \
+ static struct notifier_block fn##_mem_nb = \
+ { .notifier_call = fn, .priority = pri }; \
+ register_memory_notifier(&fn##_mem_nb); \
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/netlink.h b/kernel_addons/backport/2.6.9_U4/include/linux/netlink.h
new file mode 100644
index 0000000..6d69105
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/netlink.h
@@ -0,0 +1,14 @@
+#ifndef BACKPORT_LINUX_NETLINK_H
+#define BACKPORT_LINUX_NETLINK_H
+
+#include_next <linux/netlink.h>
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+ __nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#define netlink_kernel_create(uint, groups, input, mod) \
+ netlink_kernel_create(uint, input)
+
+#define NETLINK_ISCSI 8
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/transport_class.h b/kernel_addons/backport/2.6.9_U4/include/linux/transport_class.h
new file mode 100644
index 0000000..1d6cc22
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/transport_class.h
@@ -0,0 +1,100 @@
+/*
+ * transport_class.h - a generic container for all transport classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _TRANSPORT_CLASS_H_
+#define _TRANSPORT_CLASS_H_
+
+#include <linux/device.h>
+#include <linux/attribute_container.h>
+
+struct transport_container;
+
+struct transport_class {
+ struct class class;
+ int (*setup)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*configure)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*remove)(struct transport_container *, struct device *,
+ struct class_device *);
+};
+
+#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
+struct transport_class cls = { \
+ .class = { \
+ .name = nm, \
+ }, \
+ .setup = su, \
+ .remove = rm, \
+ .configure = cfg, \
+}
+
+
+struct anon_transport_class {
+ struct transport_class tclass;
+ struct attribute_container container;
+};
+
+#define DECLARE_ANON_TRANSPORT_CLASS(cls, mtch, cfg) \
+struct anon_transport_class cls = { \
+ .tclass = { \
+ .configure = cfg, \
+ }, \
+ . container = { \
+ .match = mtch, \
+ }, \
+}
+
+#define class_to_transport_class(x) \
+ container_of(x, struct transport_class, class)
+
+struct transport_container {
+ struct attribute_container ac;
+ struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+ container_of(x, struct transport_container, ac)
+
+void transport_remove_device(struct device *);
+void transport_add_device(struct device *);
+void transport_setup_device(struct device *);
+void transport_configure_device(struct device *);
+void transport_destroy_device(struct device *);
+
+static inline void
+transport_register_device(struct device *dev)
+{
+ transport_setup_device(dev);
+ transport_add_device(dev);
+}
+
+static inline void
+transport_unregister_device(struct device *dev)
+{
+ transport_remove_device(dev);
+ transport_destroy_device(dev);
+}
+
+static inline int transport_container_register(struct transport_container *tc)
+{
+ return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+ return attribute_container_unregister(&tc->ac);
+}
+
+int transport_class_register(struct transport_class *);
+int anon_transport_class_register(struct anon_transport_class *);
+void transport_class_unregister(struct transport_class *);
+void anon_transport_class_unregister(struct anon_transport_class *);
+
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/iscsi_proto.h b/kernel_addons/backport/2.6.9_U4/include/scsi/iscsi_proto.h
new file mode 100644
index 0000000..02f6e4b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/iscsi_proto.h
@@ -0,0 +1,587 @@
+/*
+ * RFC 3720 (iSCSI) protocol data types
+ *
+ * Copyright (C) 2005 Dmitry Yusupov
+ * Copyright (C) 2005 Alex Aizman
+ * maintained by open-iscsi at googlegroups.com
+ *
+ * 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.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#ifndef ISCSI_PROTO_H
+#define ISCSI_PROTO_H
+
+#define ISCSI_DRAFT20_VERSION 0x00
+
+/* default iSCSI listen port for incoming connections */
+#define ISCSI_LISTEN_PORT 3260
+
+/* Padding word length */
+#define PAD_WORD_LEN 4
+
+/*
+ * useful common(control and data pathes) macro
+ */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+ p[0] = (((v) >> 16) & 0xFF); \
+ p[1] = (((v) >> 8) & 0xFF); \
+ p[2] = ((v) & 0xFF); \
+}
+#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
+
+/*
+ * iSCSI Template Message Header
+ */
+struct iscsi_hdr {
+ uint8_t opcode;
+ uint8_t flags; /* Final bit */
+ uint8_t rsvd2[2];
+ uint8_t hlength; /* AHSs total length */
+ uint8_t dlength[3]; /* Data length */
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Task Tag */
+ __be32 statsn;
+ __be32 exp_statsn;
+ __be32 max_statsn;
+ uint8_t other[12];
+};
+
+/************************* RFC 3720 Begin *****************************/
+
+#define ISCSI_RESERVED_TAG 0xffffffff
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY 0x80
+#define ISCSI_OP_IMMEDIATE 0x40
+#define ISCSI_OPCODE_MASK 0x3F
+
+/* Initiator Opcode values */
+#define ISCSI_OP_NOOP_OUT 0x00
+#define ISCSI_OP_SCSI_CMD 0x01
+#define ISCSI_OP_SCSI_TMFUNC 0x02
+#define ISCSI_OP_LOGIN 0x03
+#define ISCSI_OP_TEXT 0x04
+#define ISCSI_OP_SCSI_DATA_OUT 0x05
+#define ISCSI_OP_LOGOUT 0x06
+#define ISCSI_OP_SNACK 0x10
+
+#define ISCSI_OP_VENDOR1_CMD 0x1c
+#define ISCSI_OP_VENDOR2_CMD 0x1d
+#define ISCSI_OP_VENDOR3_CMD 0x1e
+#define ISCSI_OP_VENDOR4_CMD 0x1f
+
+/* Target Opcode values */
+#define ISCSI_OP_NOOP_IN 0x20
+#define ISCSI_OP_SCSI_CMD_RSP 0x21
+#define ISCSI_OP_SCSI_TMFUNC_RSP 0x22
+#define ISCSI_OP_LOGIN_RSP 0x23
+#define ISCSI_OP_TEXT_RSP 0x24
+#define ISCSI_OP_SCSI_DATA_IN 0x25
+#define ISCSI_OP_LOGOUT_RSP 0x26
+#define ISCSI_OP_R2T 0x31
+#define ISCSI_OP_ASYNC_EVENT 0x32
+#define ISCSI_OP_REJECT 0x3f
+
+struct iscsi_ahs_hdr {
+ __be16 ahslength;
+ uint8_t ahstype;
+ uint8_t ahspec[5];
+};
+
+#define ISCSI_AHSTYPE_CDB 1
+#define ISCSI_AHSTYPE_RLENGTH 2
+
+/* iSCSI PDU Header */
+struct iscsi_cmd {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 data_length;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t cdb[16]; /* SCSI Command Block */
+ /* Additional Data (Command Dependent) */
+};
+
+/* Command PDU flags */
+#define ISCSI_FLAG_CMD_FINAL 0x80
+#define ISCSI_FLAG_CMD_READ 0x40
+#define ISCSI_FLAG_CMD_WRITE 0x20
+#define ISCSI_FLAG_CMD_ATTR_MASK 0x07 /* 3 bits */
+
+/* SCSI Command Attribute values */
+#define ISCSI_ATTR_UNTAGGED 0
+#define ISCSI_ATTR_SIMPLE 1
+#define ISCSI_ATTR_ORDERED 2
+#define ISCSI_ATTR_HEAD_OF_QUEUE 3
+#define ISCSI_ATTR_ACA 4
+
+struct iscsi_rlength_ahdr {
+ __be16 ahslength;
+ uint8_t ahstype;
+ uint8_t reserved;
+ __be32 read_length;
+};
+
+/* SCSI Response Header */
+struct iscsi_cmd_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response;
+ uint8_t cmd_status;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd1;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 exp_datasn;
+ __be32 bi_residual_count;
+ __be32 residual_count;
+ /* Response or Sense Data (optional) */
+};
+
+/* Command Response PDU flags */
+#define ISCSI_FLAG_CMD_BIDI_OVERFLOW 0x10
+#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW 0x08
+#define ISCSI_FLAG_CMD_OVERFLOW 0x04
+#define ISCSI_FLAG_CMD_UNDERFLOW 0x02
+
+/* iSCSI Status values. Valid if Rsp Selector bit is not set */
+#define ISCSI_STATUS_CMD_COMPLETED 0
+#define ISCSI_STATUS_TARGET_FAILURE 1
+#define ISCSI_STATUS_SUBSYS_FAILURE 2
+
+/* Asynchronous Event Header */
+struct iscsi_async {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ uint8_t rsvd4[8];
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t async_event;
+ uint8_t async_vcode;
+ __be16 param1;
+ __be16 param2;
+ __be16 param3;
+ uint8_t rsvd5[4];
+};
+
+/* iSCSI Event Codes */
+#define ISCSI_ASYNC_MSG_SCSI_EVENT 0
+#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT 1
+#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION 2
+#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS 3
+#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION 4
+#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC 255
+
+/* NOP-Out Message */
+struct iscsi_nopout {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd4[16];
+};
+
+/* NOP-In Message */
+struct iscsi_nopin {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd4[12];
+};
+
+/* SCSI Task Management Message Header */
+struct iscsi_tm {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd1[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rtt; /* Reference Task Tag */
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ __be32 refcmdsn;
+ __be32 exp_datasn;
+ uint8_t rsvd2[8];
+};
+
+#define ISCSI_FLAG_TM_FUNC_MASK 0x7F
+
+/* Function values */
+#define ISCSI_TM_FUNC_ABORT_TASK 1
+#define ISCSI_TM_FUNC_ABORT_TASK_SET 2
+#define ISCSI_TM_FUNC_CLEAR_ACA 3
+#define ISCSI_TM_FUNC_CLEAR_TASK_SET 4
+#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET 5
+#define ISCSI_TM_FUNC_TARGET_WARM_RESET 6
+#define ISCSI_TM_FUNC_TARGET_COLD_RESET 7
+#define ISCSI_TM_FUNC_TASK_REASSIGN 8
+
+/* SCSI Task Management Response Header */
+struct iscsi_tm_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response; /* see Response values below */
+ uint8_t qualifier;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd2[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rtt; /* Reference Task Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd3[12];
+};
+
+/* Response values */
+#define ISCSI_TMF_RSP_COMPLETE 0x00
+#define ISCSI_TMF_RSP_NO_TASK 0x01
+#define ISCSI_TMF_RSP_NO_LUN 0x02
+#define ISCSI_TMF_RSP_TASK_ALLEGIANT 0x03
+#define ISCSI_TMF_RSP_NO_FAILOVER 0x04
+#define ISCSI_TMF_RSP_NOT_SUPPORTED 0x05
+#define ISCSI_TMF_RSP_AUTH_FAILED 0x06
+#define ISCSI_TMF_RSP_REJECTED 0xff
+
+/* Ready To Transfer Header */
+struct iscsi_r2t_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 r2tsn;
+ __be32 data_offset;
+ __be32 data_length;
+};
+
+/* SCSI Data Hdr */
+struct iscsi_data {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 rsvd4;
+ __be32 exp_statsn;
+ __be32 rsvd5;
+ __be32 datasn;
+ __be32 offset;
+ __be32 rsvd6;
+ /* Payload */
+};
+
+/* SCSI Data Response Hdr */
+struct iscsi_data_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2;
+ uint8_t cmd_status;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 datasn;
+ __be32 offset;
+ __be32 residual_count;
+};
+
+/* Data Response PDU flags */
+#define ISCSI_FLAG_DATA_ACK 0x40
+#define ISCSI_FLAG_DATA_OVERFLOW 0x04
+#define ISCSI_FLAG_DATA_UNDERFLOW 0x02
+#define ISCSI_FLAG_DATA_STATUS 0x01
+
+/* Text Header */
+struct iscsi_text {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd4[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd5[16];
+ /* Text - key=value pairs */
+};
+
+#define ISCSI_FLAG_TEXT_CONTINUE 0x40
+
+/* Text Response Header */
+struct iscsi_text_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd4[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd5[12];
+ /* Text Response - key:value pairs */
+};
+
+/* Login Header */
+struct iscsi_login {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t max_version; /* Max. version supported */
+ uint8_t min_version; /* Min. version supported */
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t isid[6]; /* Initiator Session ID */
+ __be16 tsih; /* Target Session Handle */
+ __be32 itt; /* Initiator Task Tag */
+ __be16 cid;
+ __be16 rsvd3;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd5[16];
+};
+
+/* Login PDU flags */
+#define ISCSI_FLAG_LOGIN_TRANSIT 0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE 0x40
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK 0x0C /* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK 0x03 /* 2 bits */
+
+#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
+ ((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
+#define ISCSI_LOGIN_NEXT_STAGE(flags) \
+ (flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)
+
+/* Login Response Header */
+struct iscsi_login_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t max_version; /* Max. version supported */
+ uint8_t active_version; /* Active version */
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t isid[6]; /* Initiator Session ID */
+ __be16 tsih; /* Target Session Handle */
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd3;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t status_class; /* see Login RSP ststus classes below */
+ uint8_t status_detail; /* see Login RSP Status details below */
+ uint8_t rsvd4[10];
+};
+
+/* Login stage (phase) codes for CSG, NSG */
+#define ISCSI_INITIAL_LOGIN_STAGE -1
+#define ISCSI_SECURITY_NEGOTIATION_STAGE 0
+#define ISCSI_OP_PARMS_NEGOTIATION_STAGE 1
+#define ISCSI_FULL_FEATURE_PHASE 3
+
+/* Login Status response classes */
+#define ISCSI_STATUS_CLS_SUCCESS 0x00
+#define ISCSI_STATUS_CLS_REDIRECT 0x01
+#define ISCSI_STATUS_CLS_INITIATOR_ERR 0x02
+#define ISCSI_STATUS_CLS_TARGET_ERR 0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_LOGIN_STATUS_ACCEPT 0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP 0x01
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM 0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_LOGIN_STATUS_INIT_ERR 0x00
+#define ISCSI_LOGIN_STATUS_AUTH_FAILED 0x01
+#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN 0x02
+#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND 0x03
+#define ISCSI_LOGIN_STATUS_TGT_REMOVED 0x04
+#define ISCSI_LOGIN_STATUS_NO_VERSION 0x05
+#define ISCSI_LOGIN_STATUS_ISID_ERROR 0x06
+#define ISCSI_LOGIN_STATUS_MISSING_FIELDS 0x07
+#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED 0x08
+#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE 0x09
+#define ISCSI_LOGIN_STATUS_NO_SESSION 0x0a
+#define ISCSI_LOGIN_STATUS_INVALID_REQUEST 0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_LOGIN_STATUS_TARGET_ERROR 0x00
+#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE 0x01
+#define ISCSI_LOGIN_STATUS_NO_RESOURCES 0x02
+
+/* Logout Header */
+struct iscsi_logout {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd1[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd2[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be16 cid;
+ uint8_t rsvd3[2];
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd4[16];
+};
+
+/* Logout PDU flags */
+#define ISCSI_FLAG_LOGOUT_REASON_MASK 0x7F
+
+/* logout reason_code values */
+
+#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0
+#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1
+#define ISCSI_LOGOUT_REASON_RECOVERY 2
+#define ISCSI_LOGOUT_REASON_AEN_REQUEST 3
+
+/* Logout Response Header */
+struct iscsi_logout_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response; /* see Logout response values below */
+ uint8_t rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd3[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd4;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 rsvd5;
+ __be16 t2wait;
+ __be16 t2retain;
+ __be32 rsvd6;
+};
+
+/* logout response status values */
+
+#define ISCSI_LOGOUT_SUCCESS 0
+#define ISCSI_LOGOUT_CID_NOT_FOUND 1
+#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED 2
+#define ISCSI_LOGOUT_CLEANUP_FAILED 3
+
+/* SNACK Header */
+struct iscsi_snack {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[14];
+ __be32 itt;
+ __be32 begrun;
+ __be32 runlength;
+ __be32 exp_statsn;
+ __be32 rsvd3;
+ __be32 exp_datasn;
+ uint8_t rsvd6[8];
+};
+
+/* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */
+
+/* Reject Message Header */
+struct iscsi_reject {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t reason;
+ uint8_t rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd3[8];
+ __be32 ffffffff;
+ uint8_t rsvd4[4];
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 datasn;
+ uint8_t rsvd5[8];
+ /* Text - Rejected hdr */
+};
+
+/* Reason for Reject */
+#define ISCSI_REASON_CMD_BEFORE_LOGIN 1
+#define ISCSI_REASON_DATA_DIGEST_ERROR 2
+#define ISCSI_REASON_DATA_SNACK_REJECT 3
+#define ISCSI_REASON_PROTOCOL_ERROR 4
+#define ISCSI_REASON_CMD_NOT_SUPPORTED 5
+#define ISCSI_REASON_IMM_CMD_REJECT 6
+#define ISCSI_REASON_TASK_IN_PROGRESS 7
+#define ISCSI_REASON_INVALID_SNACK 8
+#define ISCSI_REASON_BOOKMARK_INVALID 9
+#define ISCSI_REASON_BOOKMARK_NO_RESOURCES 10
+#define ISCSI_REASON_NEGOTIATION_RESET 11
+
+/* Max. number of Key=Value pairs in a text message */
+#define MAX_KEY_VALUE_PAIRS 8192
+
+/* maximum length for text keys/values */
+#define KEY_MAXLEN 64
+#define VALUE_MAXLEN 255
+#define TARGET_NAME_MAXLEN VALUE_MAXLEN
+
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192
+
+/************************* RFC 3720 End *****************************/
+
+#endif /* ISCSI_PROTO_H */
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_device.h b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_device.h
new file mode 100644
index 0000000..f353e0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_device.h
@@ -0,0 +1,19 @@
+#ifndef _SCSI_SCSI_DEVICE_H_BACKPORT
+#define _SCSI_SCSI_DEVICE_H_BACKPORT
+
+#include_next <scsi/scsi_device.h>
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+struct scsi_lun;
+
+extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void starget_for_each_device(struct scsi_target *, void *,
+ void (*fn)(struct scsi_device *, void *));
+#endif /* _SCSI_SCSI_DEVICE_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h
new file mode 100644
index 0000000..b7e019b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_HOST_H_BACKPORT
+#define _SCSI_SCSI_HOST_H_BACKPORT
+
+#include_next <scsi/scsi_host.h>
+
+#define scsi_queue_work(shost, work) schedule_work(work)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_transport.h b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..99c2b12
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_transport.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_TRANSPORT_H_BACKPORT
+#define _SCSI_SCSI_TRANSPORT_H_BACKPORT
+
+#include_next <scsi/scsi_transport.h>
+
+#include <linux/transport_class.h>
+
+#endif /* _SCSI_SCSI_TRANSPORT_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/attribute_container.c b/kernel_addons/backport/2.6.9_U4/include/src/attribute_container.c
new file mode 100644
index 0000000..44948d1
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/attribute_container.c
@@ -0,0 +1,438 @@
+/*
+ * attribute_container.c - implementation of a simple container for classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to enable a device to be attached to an
+ * aritrary numer of classes without having to allocate storage for them.
+ * Instead, the contained classes select the devices they need to attach
+ * to via a matching function.
+ */
+
+#include <linux/attribute_container.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include "base.h"
+
+/* This is a private structure used to tie the classdev and the
+ * container .. it should never be visible outside this file */
+struct internal_container {
+ struct klist_node node;
+ struct attribute_container *cont;
+ struct class_device classdev;
+};
+
+static void internal_container_klist_get(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_put(&ic->classdev);
+}
+
+
+/**
+ * attribute_container_classdev_to_container - given a classdev, return the container
+ *
+ * @classdev: the class device created by attribute_container_add_device.
+ *
+ * Returns the container associated with this classdev.
+ */
+struct attribute_container *
+attribute_container_classdev_to_container(struct class_device *classdev)
+{
+ struct internal_container *ic =
+ container_of(classdev, struct internal_container, classdev);
+ return ic->cont;
+}
+EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+
+static struct list_head attribute_container_list;
+
+static DECLARE_MUTEX(attribute_container_mutex);
+
+/**
+ * attribute_container_register - register an attribute container
+ *
+ * @cont: The container to register. This must be allocated by the
+ * callee and should also be zeroed by it.
+ */
+int
+attribute_container_register(struct attribute_container *cont)
+{
+ INIT_LIST_HEAD(&cont->node);
+ klist_init(&cont->containers,internal_container_klist_get,
+ internal_container_klist_put);
+
+ down(&attribute_container_mutex);
+ list_add_tail(&cont->node, &attribute_container_list);
+ up(&attribute_container_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_register);
+
+/**
+ * attribute_container_unregister - remove a container registration
+ *
+ * @cont: previously registered container to remove
+ */
+int
+attribute_container_unregister(struct attribute_container *cont)
+{
+ int retval = -EBUSY;
+ down(&attribute_container_mutex);
+ spin_lock(&cont->containers.k_lock);
+ if (!list_empty(&cont->containers.k_list))
+ goto out;
+ retval = 0;
+ list_del(&cont->node);
+ out:
+ spin_unlock(&cont->containers.k_lock);
+ up(&attribute_container_mutex);
+ return retval;
+
+}
+EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+/* private function used as class release */
+static void attribute_container_release(struct class_device *classdev)
+{
+ struct internal_container *ic
+ = container_of(classdev, struct internal_container, classdev);
+ struct device *dev = classdev->dev;
+
+ kfree(ic);
+ put_device(dev);
+}
+
+/**
+ * attribute_container_add_device - see if any container is interested in dev
+ *
+ * @dev: device to add attributes to
+ * @fn: function to trigger addition of class device.
+ *
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container). If no
+ * fn is provided, the code will simply register the class device via
+ * class_device_add. If a function is provided, it is expected to add
+ * the class device at the appropriate time. One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time. To do this, call this routine for
+ * allocation and initialisation and then use
+ * attribute_container_device_trigger() to call class_device_add() on
+ * it. Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+void
+attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+
+ if (attribute_container_no_classdevs(cont))
+ continue;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
+ if (!ic) {
+ dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+ continue;
+ }
+
+ ic->cont = cont;
+ class_device_initialize(&ic->classdev);
+ ic->classdev.dev = get_device(dev);
+ ic->classdev.class = cont->class;
+ cont->class->release = attribute_container_release;
+ strcpy(ic->classdev.class_id, dev->bus_id);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else
+ attribute_container_add_class_device(&ic->classdev);
+ klist_add_tail(&ic->node, &cont->containers);
+ }
+ up(&attribute_container_mutex);
+}
+
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+ for (klist_iter_init(head, iter); (pos = ({ \
+ struct klist_node *n = klist_next(iter); \
+ n ? container_of(n, typeof(*pos), member) : \
+ ({ klist_iter_exit(iter) ; NULL; }); \
+ }) ) != NULL; )
+
+
+/**
+ * attribute_container_remove_device - make device eligible for removal.
+ *
+ * @dev: The generic device
+ * @fn: A function to call to remove the device
+ *
+ * This routine triggers device removal. If fn is NULL, then it is
+ * simply done via class_device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released). If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+ * class_device_del() and then use
+ * attribute_container_device_trigger() to do the final put on the
+ * classdev.
+ */
+void
+attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ if (attribute_container_no_classdevs(cont))
+ continue;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (dev != ic->classdev.dev)
+ continue;
+ klist_del(&ic->node);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else {
+ attribute_container_remove_attrs(&ic->classdev);
+ class_device_unregister(&ic->classdev);
+ }
+ }
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_device_trigger - execute a trigger for each matching classdev
+ *
+ * @dev: The generic device to run the trigger for
+ * @fn the function to execute for each classdev.
+ *
+ * This funcion is for executing a trigger when you need to know both
+ * the container and the classdev. If you only care about the
+ * container, then use attribute_container_trigger() instead.
+ */
+void
+attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ if (attribute_container_no_classdevs(cont)) {
+ fn(cont, dev, NULL);
+ continue;
+ }
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (dev == ic->classdev.dev)
+ fn(cont, dev, &ic->classdev);
+ }
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_trigger - trigger a function for each matching container
+ *
+ * @dev: The generic device to activate the trigger for
+ * @fn: the function to trigger
+ *
+ * This routine triggers a function that only needs to know the
+ * matching containers (not the classdev) associated with a device.
+ * It is more lightweight than attribute_container_device_trigger, so
+ * should be used in preference unless the triggering function
+ * actually needs to know the classdev.
+ */
+void
+attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ if (cont->match(cont, dev))
+ fn(cont, dev);
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_add_attrs - add attributes
+ *
+ * @classdev: The class device
+ *
+ * This simply creates all the class device sysfs files from the
+ * attributes listed in the container
+ */
+int
+attribute_container_add_attrs(struct class_device *classdev)
+{
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+ struct class_device_attribute **attrs = cont->attrs;
+ int i, error;
+
+ if (!attrs)
+ return 0;
+
+ for (i = 0; attrs[i]; i++) {
+ error = class_device_create_file(classdev, attrs[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+/**
+ * attribute_container_add_class_device - same function as class_device_add
+ *
+ * @classdev: the class device to add
+ *
+ * This performs essentially the same function as class_device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+int
+attribute_container_add_class_device(struct class_device *classdev)
+{
+ int error = class_device_add(classdev);
+ if (error)
+ return error;
+ return attribute_container_add_attrs(classdev);
+}
+
+/**
+ * attribute_container_add_class_device_adapter - simple adapter for triggers
+ *
+ * This function is identical to attribute_container_add_class_device except
+ * that it is designed to be called from the triggers
+ */
+int
+attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ return attribute_container_add_class_device(classdev);
+}
+
+/**
+ * attribute_container_remove_attrs - remove any attribute files
+ *
+ * @classdev: The class device to remove the files from
+ *
+ */
+void
+attribute_container_remove_attrs(struct class_device *classdev)
+{
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+ struct class_device_attribute **attrs = cont->attrs;
+ int i;
+
+ if (!attrs)
+ return;
+
+ for (i = 0; attrs[i]; i++)
+ class_device_remove_file(classdev, attrs[i]);
+}
+
+/**
+ * attribute_container_class_device_del - equivalent of class_device_del
+ *
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+ * class_device_del.
+ */
+void
+attribute_container_class_device_del(struct class_device *classdev)
+{
+ attribute_container_remove_attrs(classdev);
+ class_device_del(classdev);
+}
+
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont: the container
+ * @dev: the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct class_device *cdev = NULL;
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (ic->classdev.dev == dev) {
+ cdev = &ic->classdev;
+ /* FIXME: must exit iterator then break */
+ klist_iter_exit(&iter);
+ break;
+ }
+ }
+
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
+int
+attribute_container_init(void)
+{
+ INIT_LIST_HEAD(&attribute_container_list);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_init);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/base.h b/kernel_addons/backport/2.6.9_U4/include/src/base.h
new file mode 100644
index 0000000..a5f8936
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/base.h
@@ -0,0 +1 @@
+extern int attribute_container_init(void);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/init.c b/kernel_addons/backport/2.6.9_U4/include/src/init.c
new file mode 100644
index 0000000..15f0bc6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/init.c
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
+
+/**
+ * driver_init - initialize driver model.
+ *
+ * Call the driver model init functions to initialize their
+ * subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+ attribute_container_init();
+}
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/klist.c b/kernel_addons/backport/2.6.9_U4/include/src/klist.c
new file mode 100644
index 0000000..3b29ebc
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/klist.c
@@ -0,0 +1,287 @@
+/*
+ * klist.c - Routines for manipulating klists.
+ *
+ *
+ * This klist interface provides a couple of structures that wrap around
+ * struct list_head to provide explicit list "head" (struct klist) and
+ * list "node" (struct klist_node) objects. For struct klist, a spinlock
+ * is included that protects access to the actual list itself. struct
+ * klist_node provides a pointer to the klist that owns it and a kref
+ * reference count that indicates the number of current users of that node
+ * in the list.
+ *
+ * The entire point is to provide an interface for iterating over a list
+ * that is safe and allows for modification of the list during the
+ * iteration (e.g. insertion and removal), including modification of the
+ * current node on the list.
+ *
+ * It works using a 3rd object type - struct klist_iter - that is declared
+ * and initialized before an iteration. klist_next() is used to acquire the
+ * next element in the list. It returns NULL if there are no more items.
+ * Internally, that routine takes the klist's lock, decrements the reference
+ * count of the previous klist_node and increments the count of the next
+ * klist_node. It then drops the lock and returns.
+ *
+ * There are primitives for adding and removing nodes to/from a klist.
+ * When deleting, klist_del() will simply decrement the reference count.
+ * Only when the count goes to 0 is the node removed from the list.
+ * klist_remove() will try to delete the node from the list and block
+ * until it is actually removed. This is useful for objects (like devices)
+ * that have been removed from the system and must be freed (but must wait
+ * until all accessors have finished).
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ * klist_init - Initialize a klist structure.
+ * @k: The klist we're initializing.
+ * @get: The get function for the embedding object (NULL if none)
+ * @put: The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure. If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
+ */
+
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *))
+{
+ INIT_LIST_HEAD(&k->k_list);
+ spin_lock_init(&k->k_lock);
+ k->get = get;
+ k->put = put;
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add_tail(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+ INIT_LIST_HEAD(&n->n_node);
+ init_completion(&n->n_removed);
+ kref_init(&n->n_ref);
+ n->n_klist = k;
+ if (k->get)
+ k->get(n);
+}
+
+
+/**
+ * klist_add_head - Initialize a klist_node and add it to front.
+ * @n: node we're adding.
+ * @k: klist it's going on.
+ */
+
+void klist_add_head(struct klist_node * n, struct klist * k)
+{
+ klist_node_init(k, n);
+ add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ * klist_add_tail - Initialize a klist_node and add it to back.
+ * @n: node we're adding.
+ * @k: klist it's going on.
+ */
+
+void klist_add_tail(struct klist_node * n, struct klist * k)
+{
+ klist_node_init(k, n);
+ add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+ struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+
+ list_del(&n->n_node);
+ complete(&n->n_removed);
+ n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+ return kref_put_new(&n->n_ref, klist_release);
+}
+
+
+/**
+ * klist_del - Decrement the reference count of node and try to remove.
+ * @n: node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+ struct klist * k = n->n_klist;
+ void (*put)(struct klist_node *) = k->put;
+
+ spin_lock(&k->k_lock);
+ if (!klist_dec_and_del(n))
+ put = NULL;
+ spin_unlock(&k->k_lock);
+ if (put)
+ put(n);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ * klist_remove - Decrement the refcount of node and wait for it to go away.
+ * @n: node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+ klist_del(n);
+ wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ * klist_node_attached - Say whether a node is bound to a list or not.
+ * @n: Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+ return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ * klist_iter_init_node - Initialize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter we're filling.
+ * @n: node to start with.
+ *
+ * Similar to klist_iter_init(), but starts the action off with @n,
+ * instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+ i->i_klist = k;
+ i->i_head = &k->k_list;
+ i->i_cur = n;
+ if (n)
+ kref_get(&n->n_ref);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ * klist_iter_init - Iniitalize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter structure we're filling.
+ *
+ * Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+ klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ * klist_iter_exit - Finish a list iteration.
+ * @i: Iterator structure.
+ *
+ * Must be called when done iterating over list, as it decrements the
+ * refcount of the current node. Necessary in case iteration exited before
+ * the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+ if (i->i_cur) {
+ klist_del(i->i_cur);
+ i->i_cur = NULL;
+ }
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+ return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ * klist_next - Ante up next node in list.
+ * @i: Iterator structure.
+ *
+ * First grab list lock. Decrement the reference count of the previous
+ * node, if there was one. Grab the next node, increment its reference
+ * count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+ struct list_head * next;
+ struct klist_node * lnode = i->i_cur;
+ struct klist_node * knode = NULL;
+ void (*put)(struct klist_node *) = i->i_klist->put;
+
+ spin_lock(&i->i_klist->k_lock);
+ if (lnode) {
+ next = lnode->n_node.next;
+ if (!klist_dec_and_del(lnode))
+ put = NULL;
+ } else
+ next = i->i_head->next;
+
+ if (next != i->i_head) {
+ knode = to_klist_node(next);
+ kref_get(&knode->n_ref);
+ }
+ i->i_cur = knode;
+ spin_unlock(&i->i_klist->k_lock);
+ if (put && lnode)
+ put(lnode);
+ return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/kref_new.c b/kernel_addons/backport/2.6.9_U4/include/src/kref_new.c
new file mode 100644
index 0000000..d45bb3f
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/kref_new.c
@@ -0,0 +1,29 @@
+#include <linux/kref.h>
+#include <linux/module.h>
+
+/**
+ * kref_put - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ * last reference to the object is released.
+ * This pointer is required, and it is not acceptable to pass kfree
+ * in as this function.
+ *
+ * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0. Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory. Only use the return value if you want to see if the kref is now
+ * gone, not present.
+ */
+int kref_put_new(struct kref *kref, void (*release)(struct kref *kref))
+{
+ WARN_ON(release == NULL);
+ WARN_ON(release == (void (*)(struct kref *))kfree);
+
+ if (atomic_dec_and_test(&kref->refcount)) {
+ release(kref);
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(kref_put_new);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/scsi.c b/kernel_addons/backport/2.6.9_U4/include/src/scsi.c
new file mode 100644
index 0000000..8c833c0
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/scsi.c
@@ -0,0 +1,50 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/unistd.h>
+#include <linux/spinlock.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * starget_for_each_device - helper to walk all devices of a target
+ * @starget: target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost. The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+ void (*fn)(struct scsi_device *, void *))
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct scsi_device *sdev;
+
+ printk("%s: entry\n", __FUNCTION__);
+ shost_for_each_device(sdev, shost) {
+ if ((sdev->channel == starget->channel) &&
+ (sdev->id == starget->id))
+ fn(sdev, data);
+ }
+ printk("%s: exit\n", __FUNCTION__);
+}
+EXPORT_SYMBOL(starget_for_each_device);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/scsi_lib.c b/kernel_addons/backport/2.6.9_U4/include/src/scsi_lib.c
new file mode 100644
index 0000000..f53f824
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/scsi_lib.c
@@ -0,0 +1,166 @@
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+int scsi_is_target_device(const struct device *dev)
+{
+ char *str = dev->bus_id;
+
+ if (strncmp(str, "target", 6) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * scsi_internal_device_block - internal function to put a device
+ * temporarily into the SDEV_BLOCK state
+ * @sdev: device to block
+ *
+ * Block request made by scsi lld's to temporarily stop all
+ * scsi commands on the specified device. Called from interrupt
+ * or normal process context.
+ *
+ * Returns zero if successful or error if not
+ *
+ * Notes:
+ * This routine transitions the device to the SDEV_BLOCK state
+ * (which must be a legal transition). When the device is in this
+ * state, all commands are deferred until the scsi lld reenables
+ * the device with scsi_device_unblock or device_block_tmo fires.
+ * This routine assumes the host_lock is held on entry.
+ **/
+int
+scsi_internal_device_block(struct scsi_device *sdev)
+{
+ request_queue_t *q = sdev->request_queue;
+ unsigned long flags;
+ int err = 0;
+
+ err = scsi_device_set_state(sdev, SDEV_BLOCK);
+ if (err)
+ return err;
+
+ /*
+ * The device has transitioned to SDEV_BLOCK. Stop the
+ * block layer from calling the midlayer with this device's
+ * request queue.
+ */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+
+/**
+ * scsi_internal_device_unblock - resume a device after a block request
+ * @sdev: device to resume
+ *
+ * Called by scsi lld's or the midlayer to restart the device queue
+ * for the previously suspended scsi device. Called from interrupt or
+ * normal process context.
+ *
+ * Returns zero if successful or error if not.
+ *
+ * Notes:
+ * This routine transitions the device to the SDEV_RUNNING state
+ * (which must be a legal transition) allowing the midlayer to
+ * goose the queue for this device. This routine assumes the
+ * host_lock is held upon entry.
+ **/
+int
+scsi_internal_device_unblock(struct scsi_device *sdev)
+{
+ request_queue_t *q = sdev->request_queue;
+ int err;
+ unsigned long flags;
+
+
+ /*
+ * Try to transition the scsi device to SDEV_RUNNING
+ * and goose the device queue if successful.
+ */
+ err = scsi_device_set_state(sdev, SDEV_RUNNING);
+ if (err)
+ return err;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+
+ return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+ else
+ device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ else
+ device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+MODULE_LICENSE("GPL");
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/scsi_scan.c b/kernel_addons/backport/2.6.9_U4/include/src/scsi_scan.c
new file mode 100644
index 0000000..b7b7674
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/scsi_scan.c
@@ -0,0 +1,48 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+
+/**
+ * int_to_scsilun: reverts an int into a scsi_lun
+ * @int: integer to be reverted
+ * @scsilun: struct scsi_lun to be set.
+ *
+ * Description:
+ * Reverts the functionality of the scsilun_to_int, which packed
+ * an 8-byte lun value into an int. This routine unpacks the int
+ * back into the lun value.
+ * Note: the scsilun_to_int() routine does not truly handle all
+ * 8bytes of the lun value. This functions restores only as much
+ * as was set by the routine.
+ *
+ * Notes:
+ * Given an integer : 0x0b030a04, this function returns a
+ * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *
+ **/
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+ int i;
+
+ memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+ for (i = 0; i < sizeof(lun); i += 2) {
+ scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+ scsilun->scsi_lun[i+1] = lun & 0xFF;
+ lun = lun >> 16;
+ }
+}
+EXPORT_SYMBOL(int_to_scsilun);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/transport_class.c b/kernel_addons/backport/2.6.9_U4/include/src/transport_class.c
new file mode 100644
index 0000000..f25e7c6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/transport_class.c
@@ -0,0 +1,280 @@
+/*
+ * transport_class.c - implementation of generic transport classes
+ * using attribute_containers
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to allow any "device controller" (which
+ * would most often be a Host Bus Adapter to use the services of one
+ * or more tranport classes for performing transport specific
+ * services. Transport specific services are things that the generic
+ * command layer doesn't want to know about (speed settings, line
+ * condidtioning, etc), but which the user might be interested in.
+ * Thus, the HBA's use the routines exported by the transport classes
+ * to perform these functions. The transport classes export certain
+ * values to the user via sysfs using attribute containers.
+ *
+ * Note: because not every HBA will care about every transport
+ * attribute, there's a many to one relationship that goes like this:
+ *
+ * transport class<-----attribute container<----class device
+ *
+ * Usually the attribute container is per-HBA, but the design doesn't
+ * mandate that. Although most of the services will be specific to
+ * the actual external storage connection used by the HBA, the generic
+ * transport class is framed entirely in terms of generic devices to
+ * allow it to be used by any physical HBA in the system.
+ */
+#include <linux/attribute_container.h>
+#include <linux/transport_class.h>
+
+/**
+ * transport_class_register - register an initial transport class
+ *
+ * @tclass: a pointer to the transport class structure to be initialised
+ *
+ * The transport class contains an embedded class which is used to
+ * identify it. The caller should initialise this structure with
+ * zeros and then generic class must have been initialised with the
+ * actual transport class unique name. There's a macro
+ * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
+ * be registered).
+ *
+ * Returns 0 on success or error on failure.
+ */
+int transport_class_register(struct transport_class *tclass)
+{
+ return class_register(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_register);
+
+/**
+ * transport_class_unregister - unregister a previously registered class
+ *
+ * @tclass: The transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the transport
+ * class.
+ */
+void transport_class_unregister(struct transport_class *tclass)
+{
+ class_unregister(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ /* do nothing */
+ return 0;
+}
+
+/**
+ * anon_transport_class_register - register an anonymous class
+ *
+ * @atc: The anon transport class to register
+ *
+ * The anonymous transport class contains both a transport class and a
+ * container. The idea of an anonymous class is that it never
+ * actually has any device attributes associated with it (and thus
+ * saves on container storage). So it can only be used for triggering
+ * events. Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
+ * initialise the anon transport class storage.
+ */
+int anon_transport_class_register(struct anon_transport_class *atc)
+{
+ int error;
+ atc->container.class = &atc->tclass.class;
+ attribute_container_set_no_classdevs(&atc->container);
+ error = attribute_container_register(&atc->container);
+ if (error)
+ return error;
+ atc->tclass.setup = anon_transport_dummy_function;
+ atc->tclass.remove = anon_transport_dummy_function;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_register);
+
+/**
+ * anon_transport_class_unregister - unregister an anon class
+ *
+ * @atc: Pointer to the anon transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the anon
+ * transport class.
+ */
+void anon_transport_class_unregister(struct anon_transport_class *atc)
+{
+ attribute_container_unregister(&atc->container);
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+static int transport_setup_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+ if (tclass->setup)
+ tclass->setup(tcont, dev, classdev);
+
+ return 0;
+}
+
+/**
+ * transport_setup_device - declare a new dev for transport class association
+ * but don't make it visible yet.
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus). This
+ * routine is simply a trigger point to see if any set of transport
+ * classes wishes to associate with the added device. This allocates
+ * storage for the class device and initialises it, but does not yet
+ * add it to the system or add attributes to it (you do this with
+ * transport_add_device). If you have no need for a separate setup
+ * and add operations, use transport_register_device (see
+ * transport_class.h).
+ */
+
+void transport_setup_device(struct device *dev)
+{
+ attribute_container_add_device(dev, transport_setup_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_setup_device);
+
+static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+
+ if (!error && tcont->statistics)
+ error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+ return error;
+}
+
+
+/**
+ * transport_add_device - declare a new dev for transport class association
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus). This
+ * routine is simply a trigger point used to add the device to the
+ * system and register attributes for it.
+ */
+
+void transport_add_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_add_class_device);
+}
+EXPORT_SYMBOL_GPL(transport_add_device);
+
+static int transport_configure(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+ if (tclass->configure)
+ tclass->configure(tcont, dev, cdev);
+
+ return 0;
+}
+
+/**
+ * transport_configure_device - configure an already set up device
+ *
+ * @dev: generic device representing device to be configured
+ *
+ * The idea of configure is simply to provide a point within the setup
+ * process to allow the transport class to extract information from a
+ * device after it has been setup. This is used in SCSI because we
+ * have to have a setup device to begin using the HBA, but after we
+ * send the initial inquiry, we use configure to extract the device
+ * parameters. The device need not have been added to be configured.
+ */
+void transport_configure_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_configure);
+}
+EXPORT_SYMBOL_GPL(transport_configure_device);
+
+static int transport_remove_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove)
+ tclass->remove(tcont, dev, classdev);
+
+ if (tclass->remove != anon_transport_dummy_function) {
+ if (tcont->statistics)
+ sysfs_remove_group(&classdev->kobj, tcont->statistics);
+ attribute_container_class_device_del(classdev);
+ }
+
+ return 0;
+}
+
+
+/**
+ * transport_remove_device - remove the visibility of a device
+ *
+ * @dev: generic device to remove
+ *
+ * This call removes the visibility of the device (to the user from
+ * sysfs), but does not destroy it. To eliminate a device entirely
+ * you must also call transport_destroy_device. If you don't need to
+ * do remove and destroy as separate operations, use
+ * transport_unregister_device() (see transport_class.h) which will
+ * perform both calls for you.
+ */
+void transport_remove_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_remove_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_remove_device);
+
+static void transport_destroy_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove != anon_transport_dummy_function)
+ class_device_put(classdev);
+}
+
+
+/**
+ * transport_destroy_device - destroy a removed device
+ *
+ * @dev: device to eliminate from the transport class.
+ *
+ * This call triggers the elimination of storage associated with the
+ * transport classdev. Note: all it really does is relinquish a
+ * reference to the classdev. The memory will not be freed until the
+ * last reference goes to zero. Note also that the classdev retains a
+ * reference count on dev, so dev too will remain for as long as the
+ * transport class device remains around.
+ */
+void transport_destroy_device(struct device *dev)
+{
+ attribute_container_remove_device(dev, transport_destroy_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_destroy_device);
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/attribute_container.h b/kernel_addons/backport/2.6.9_U5/include/linux/attribute_container.h
new file mode 100644
index 0000000..93bfb0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/attribute_container.h
@@ -0,0 +1,71 @@
+/*
+ * class_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _ATTRIBUTE_CONTAINER_H_
+#define _ATTRIBUTE_CONTAINER_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
+
+struct attribute_container {
+ struct list_head node;
+ struct klist containers;
+ struct class *class;
+ struct class_device_attribute **attrs;
+ int (*match)(struct attribute_container *, struct device *);
+#define ATTRIBUTE_CONTAINER_NO_CLASSDEVS 0x01
+ unsigned long flags;
+};
+
+static inline int
+attribute_container_no_classdevs(struct attribute_container *atc)
+{
+ return atc->flags & ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+static inline void
+attribute_container_set_no_classdevs(struct attribute_container *atc)
+{
+ atc->flags |= ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+int attribute_container_register(struct attribute_container *cont);
+int attribute_container_unregister(struct attribute_container *cont);
+void attribute_container_create_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *));
+void attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *));
+int attribute_container_add_attrs(struct class_device *classdev);
+int attribute_container_add_class_device(struct class_device *classdev);
+int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev);
+void attribute_container_remove_attrs(struct class_device *classdev);
+void attribute_container_class_device_del(struct class_device *classdev);
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/crypto.h b/kernel_addons/backport/2.6.9_U5/include/linux/crypto.h
new file mode 100644
index 0000000..aecccde
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/crypto.h
@@ -0,0 +1,11 @@
+#ifndef LINUX_CRYPTO_BACKPORT_H
+#define LINUX_CRYPTO_BACKPORT_H
+
+#include_next <linux/crypto.h>
+
+#define crypto_hash_init(desc) crypto_digest_init(*desc)
+#define crypto_hash_digest(desc, sg, nbytes, out) crypto_digest_digest(*desc, sg, 1, out)
+#define crypto_hash_update(desc, sg, nbytes) crypto_digest_update(*desc, sg, 1)
+#define crypto_hash_final(desc, out) crypto_digest_final(*desc, out)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h b/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h
index a37dcd5..02a5907 100644
--- a/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h
@@ -4,4 +4,7 @@ #define BACKPORT_KERNEL_H_2_6_19
#include_next <linux/kernel.h>
#include <linux/log2.h>
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+
#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h b/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h
index 48eccd8..2b94461 100644
--- a/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h
@@ -25,6 +25,7 @@ #ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <linux/gfp.h>
struct kfifo {
unsigned char *buffer; /* the buffer holding the data */
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/klist.h b/kernel_addons/backport/2.6.9_U5/include/linux/klist.h
new file mode 100644
index 0000000..7407125
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/klist.h
@@ -0,0 +1,61 @@
+/*
+ * klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ * Implementations are found in lib/klist.c
+ *
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is rleased under the GPL v2.
+ */
+
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+struct klist_node;
+struct klist {
+ spinlock_t k_lock;
+ struct list_head k_list;
+ void (*get)(struct klist_node *);
+ void (*put)(struct klist_node *);
+};
+
+
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *));
+
+struct klist_node {
+ struct klist * n_klist;
+ struct list_head n_node;
+ struct kref n_ref;
+ struct completion n_removed;
+};
+
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+ struct klist * i_klist;
+ struct list_head * i_head;
+ struct klist_node * i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
+ struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/memory.h b/kernel_addons/backport/2.6.9_U5/include/linux/memory.h
new file mode 100644
index 0000000..654ef55
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/memory.h
@@ -0,0 +1,89 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+ unsigned long phys_index;
+ unsigned long state;
+ /*
+ * This serializes all state change requests. It isn't
+ * held during creation because the control files are
+ * created long after the critical areas during
+ * initialization.
+ */
+ struct semaphore state_sem;
+ int phys_device; /* to which fru does this belong? */
+ void *hw; /* optional pointer to fw/hw data */
+ int (*phys_callback)(struct memory_block *);
+ struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define MEM_ONLINE (1<<0) /* exposed to userspace */
+#define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */
+#define MEM_OFFLINE (1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid. The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working. Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define MEM_MAPPING_INVALID (1<<3)
+
+struct notifier_block;
+struct mem_section;
+
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int memory_dev_init(void)
+{
+ return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
+
+#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
+
+
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
+#define hotplug_memory_notifier(fn, pri) { \
+ static struct notifier_block fn##_mem_nb = \
+ { .notifier_call = fn, .priority = pri }; \
+ register_memory_notifier(&fn##_mem_nb); \
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/netlink.h b/kernel_addons/backport/2.6.9_U5/include/linux/netlink.h
new file mode 100644
index 0000000..6d69105
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/netlink.h
@@ -0,0 +1,14 @@
+#ifndef BACKPORT_LINUX_NETLINK_H
+#define BACKPORT_LINUX_NETLINK_H
+
+#include_next <linux/netlink.h>
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+ __nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#define netlink_kernel_create(uint, groups, input, mod) \
+ netlink_kernel_create(uint, input)
+
+#define NETLINK_ISCSI 8
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/transport_class.h b/kernel_addons/backport/2.6.9_U5/include/linux/transport_class.h
new file mode 100644
index 0000000..1d6cc22
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/transport_class.h
@@ -0,0 +1,100 @@
+/*
+ * transport_class.h - a generic container for all transport classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _TRANSPORT_CLASS_H_
+#define _TRANSPORT_CLASS_H_
+
+#include <linux/device.h>
+#include <linux/attribute_container.h>
+
+struct transport_container;
+
+struct transport_class {
+ struct class class;
+ int (*setup)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*configure)(struct transport_container *, struct device *,
+ struct class_device *);
+ int (*remove)(struct transport_container *, struct device *,
+ struct class_device *);
+};
+
+#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
+struct transport_class cls = { \
+ .class = { \
+ .name = nm, \
+ }, \
+ .setup = su, \
+ .remove = rm, \
+ .configure = cfg, \
+}
+
+
+struct anon_transport_class {
+ struct transport_class tclass;
+ struct attribute_container container;
+};
+
+#define DECLARE_ANON_TRANSPORT_CLASS(cls, mtch, cfg) \
+struct anon_transport_class cls = { \
+ .tclass = { \
+ .configure = cfg, \
+ }, \
+ . container = { \
+ .match = mtch, \
+ }, \
+}
+
+#define class_to_transport_class(x) \
+ container_of(x, struct transport_class, class)
+
+struct transport_container {
+ struct attribute_container ac;
+ struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+ container_of(x, struct transport_container, ac)
+
+void transport_remove_device(struct device *);
+void transport_add_device(struct device *);
+void transport_setup_device(struct device *);
+void transport_configure_device(struct device *);
+void transport_destroy_device(struct device *);
+
+static inline void
+transport_register_device(struct device *dev)
+{
+ transport_setup_device(dev);
+ transport_add_device(dev);
+}
+
+static inline void
+transport_unregister_device(struct device *dev)
+{
+ transport_remove_device(dev);
+ transport_destroy_device(dev);
+}
+
+static inline int transport_container_register(struct transport_container *tc)
+{
+ return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+ return attribute_container_unregister(&tc->ac);
+}
+
+int transport_class_register(struct transport_class *);
+int anon_transport_class_register(struct anon_transport_class *);
+void transport_class_unregister(struct transport_class *);
+void anon_transport_class_unregister(struct anon_transport_class *);
+
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/iscsi_proto.h b/kernel_addons/backport/2.6.9_U5/include/scsi/iscsi_proto.h
new file mode 100644
index 0000000..02f6e4b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/iscsi_proto.h
@@ -0,0 +1,587 @@
+/*
+ * RFC 3720 (iSCSI) protocol data types
+ *
+ * Copyright (C) 2005 Dmitry Yusupov
+ * Copyright (C) 2005 Alex Aizman
+ * maintained by open-iscsi at googlegroups.com
+ *
+ * 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.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#ifndef ISCSI_PROTO_H
+#define ISCSI_PROTO_H
+
+#define ISCSI_DRAFT20_VERSION 0x00
+
+/* default iSCSI listen port for incoming connections */
+#define ISCSI_LISTEN_PORT 3260
+
+/* Padding word length */
+#define PAD_WORD_LEN 4
+
+/*
+ * useful common(control and data pathes) macro
+ */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+ p[0] = (((v) >> 16) & 0xFF); \
+ p[1] = (((v) >> 8) & 0xFF); \
+ p[2] = ((v) & 0xFF); \
+}
+#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
+
+/*
+ * iSCSI Template Message Header
+ */
+struct iscsi_hdr {
+ uint8_t opcode;
+ uint8_t flags; /* Final bit */
+ uint8_t rsvd2[2];
+ uint8_t hlength; /* AHSs total length */
+ uint8_t dlength[3]; /* Data length */
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Task Tag */
+ __be32 statsn;
+ __be32 exp_statsn;
+ __be32 max_statsn;
+ uint8_t other[12];
+};
+
+/************************* RFC 3720 Begin *****************************/
+
+#define ISCSI_RESERVED_TAG 0xffffffff
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY 0x80
+#define ISCSI_OP_IMMEDIATE 0x40
+#define ISCSI_OPCODE_MASK 0x3F
+
+/* Initiator Opcode values */
+#define ISCSI_OP_NOOP_OUT 0x00
+#define ISCSI_OP_SCSI_CMD 0x01
+#define ISCSI_OP_SCSI_TMFUNC 0x02
+#define ISCSI_OP_LOGIN 0x03
+#define ISCSI_OP_TEXT 0x04
+#define ISCSI_OP_SCSI_DATA_OUT 0x05
+#define ISCSI_OP_LOGOUT 0x06
+#define ISCSI_OP_SNACK 0x10
+
+#define ISCSI_OP_VENDOR1_CMD 0x1c
+#define ISCSI_OP_VENDOR2_CMD 0x1d
+#define ISCSI_OP_VENDOR3_CMD 0x1e
+#define ISCSI_OP_VENDOR4_CMD 0x1f
+
+/* Target Opcode values */
+#define ISCSI_OP_NOOP_IN 0x20
+#define ISCSI_OP_SCSI_CMD_RSP 0x21
+#define ISCSI_OP_SCSI_TMFUNC_RSP 0x22
+#define ISCSI_OP_LOGIN_RSP 0x23
+#define ISCSI_OP_TEXT_RSP 0x24
+#define ISCSI_OP_SCSI_DATA_IN 0x25
+#define ISCSI_OP_LOGOUT_RSP 0x26
+#define ISCSI_OP_R2T 0x31
+#define ISCSI_OP_ASYNC_EVENT 0x32
+#define ISCSI_OP_REJECT 0x3f
+
+struct iscsi_ahs_hdr {
+ __be16 ahslength;
+ uint8_t ahstype;
+ uint8_t ahspec[5];
+};
+
+#define ISCSI_AHSTYPE_CDB 1
+#define ISCSI_AHSTYPE_RLENGTH 2
+
+/* iSCSI PDU Header */
+struct iscsi_cmd {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 data_length;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t cdb[16]; /* SCSI Command Block */
+ /* Additional Data (Command Dependent) */
+};
+
+/* Command PDU flags */
+#define ISCSI_FLAG_CMD_FINAL 0x80
+#define ISCSI_FLAG_CMD_READ 0x40
+#define ISCSI_FLAG_CMD_WRITE 0x20
+#define ISCSI_FLAG_CMD_ATTR_MASK 0x07 /* 3 bits */
+
+/* SCSI Command Attribute values */
+#define ISCSI_ATTR_UNTAGGED 0
+#define ISCSI_ATTR_SIMPLE 1
+#define ISCSI_ATTR_ORDERED 2
+#define ISCSI_ATTR_HEAD_OF_QUEUE 3
+#define ISCSI_ATTR_ACA 4
+
+struct iscsi_rlength_ahdr {
+ __be16 ahslength;
+ uint8_t ahstype;
+ uint8_t reserved;
+ __be32 read_length;
+};
+
+/* SCSI Response Header */
+struct iscsi_cmd_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response;
+ uint8_t cmd_status;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd1;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 exp_datasn;
+ __be32 bi_residual_count;
+ __be32 residual_count;
+ /* Response or Sense Data (optional) */
+};
+
+/* Command Response PDU flags */
+#define ISCSI_FLAG_CMD_BIDI_OVERFLOW 0x10
+#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW 0x08
+#define ISCSI_FLAG_CMD_OVERFLOW 0x04
+#define ISCSI_FLAG_CMD_UNDERFLOW 0x02
+
+/* iSCSI Status values. Valid if Rsp Selector bit is not set */
+#define ISCSI_STATUS_CMD_COMPLETED 0
+#define ISCSI_STATUS_TARGET_FAILURE 1
+#define ISCSI_STATUS_SUBSYS_FAILURE 2
+
+/* Asynchronous Event Header */
+struct iscsi_async {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ uint8_t rsvd4[8];
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t async_event;
+ uint8_t async_vcode;
+ __be16 param1;
+ __be16 param2;
+ __be16 param3;
+ uint8_t rsvd5[4];
+};
+
+/* iSCSI Event Codes */
+#define ISCSI_ASYNC_MSG_SCSI_EVENT 0
+#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT 1
+#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION 2
+#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS 3
+#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION 4
+#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC 255
+
+/* NOP-Out Message */
+struct iscsi_nopout {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd4[16];
+};
+
+/* NOP-In Message */
+struct iscsi_nopin {
+ uint8_t opcode;
+ uint8_t flags;
+ __be16 rsvd2;
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd4[12];
+};
+
+/* SCSI Task Management Message Header */
+struct iscsi_tm {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd1[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rtt; /* Reference Task Tag */
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ __be32 refcmdsn;
+ __be32 exp_datasn;
+ uint8_t rsvd2[8];
+};
+
+#define ISCSI_FLAG_TM_FUNC_MASK 0x7F
+
+/* Function values */
+#define ISCSI_TM_FUNC_ABORT_TASK 1
+#define ISCSI_TM_FUNC_ABORT_TASK_SET 2
+#define ISCSI_TM_FUNC_CLEAR_ACA 3
+#define ISCSI_TM_FUNC_CLEAR_TASK_SET 4
+#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET 5
+#define ISCSI_TM_FUNC_TARGET_WARM_RESET 6
+#define ISCSI_TM_FUNC_TARGET_COLD_RESET 7
+#define ISCSI_TM_FUNC_TASK_REASSIGN 8
+
+/* SCSI Task Management Response Header */
+struct iscsi_tm_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response; /* see Response values below */
+ uint8_t qualifier;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd2[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rtt; /* Reference Task Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd3[12];
+};
+
+/* Response values */
+#define ISCSI_TMF_RSP_COMPLETE 0x00
+#define ISCSI_TMF_RSP_NO_TASK 0x01
+#define ISCSI_TMF_RSP_NO_LUN 0x02
+#define ISCSI_TMF_RSP_TASK_ALLEGIANT 0x03
+#define ISCSI_TMF_RSP_NO_FAILOVER 0x04
+#define ISCSI_TMF_RSP_NOT_SUPPORTED 0x05
+#define ISCSI_TMF_RSP_AUTH_FAILED 0x06
+#define ISCSI_TMF_RSP_REJECTED 0xff
+
+/* Ready To Transfer Header */
+struct iscsi_r2t_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 ttt; /* Target Transfer Tag */
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 r2tsn;
+ __be32 data_offset;
+ __be32 data_length;
+};
+
+/* SCSI Data Hdr */
+struct iscsi_data {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t rsvd3;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 rsvd4;
+ __be32 exp_statsn;
+ __be32 rsvd5;
+ __be32 datasn;
+ __be32 offset;
+ __be32 rsvd6;
+ /* Payload */
+};
+
+/* SCSI Data Response Hdr */
+struct iscsi_data_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2;
+ uint8_t cmd_status;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t lun[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 datasn;
+ __be32 offset;
+ __be32 residual_count;
+};
+
+/* Data Response PDU flags */
+#define ISCSI_FLAG_DATA_ACK 0x40
+#define ISCSI_FLAG_DATA_OVERFLOW 0x04
+#define ISCSI_FLAG_DATA_UNDERFLOW 0x02
+#define ISCSI_FLAG_DATA_STATUS 0x01
+
+/* Text Header */
+struct iscsi_text {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd4[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd5[16];
+ /* Text - key=value pairs */
+};
+
+#define ISCSI_FLAG_TEXT_CONTINUE 0x40
+
+/* Text Response Header */
+struct iscsi_text_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd4[8];
+ __be32 itt;
+ __be32 ttt;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t rsvd5[12];
+ /* Text Response - key:value pairs */
+};
+
+/* Login Header */
+struct iscsi_login {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t max_version; /* Max. version supported */
+ uint8_t min_version; /* Min. version supported */
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t isid[6]; /* Initiator Session ID */
+ __be16 tsih; /* Target Session Handle */
+ __be32 itt; /* Initiator Task Tag */
+ __be16 cid;
+ __be16 rsvd3;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd5[16];
+};
+
+/* Login PDU flags */
+#define ISCSI_FLAG_LOGIN_TRANSIT 0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE 0x40
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK 0x0C /* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK 0x03 /* 2 bits */
+
+#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
+ ((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
+#define ISCSI_LOGIN_NEXT_STAGE(flags) \
+ (flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)
+
+/* Login Response Header */
+struct iscsi_login_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t max_version; /* Max. version supported */
+ uint8_t active_version; /* Active version */
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t isid[6]; /* Initiator Session ID */
+ __be16 tsih; /* Target Session Handle */
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd3;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ uint8_t status_class; /* see Login RSP ststus classes below */
+ uint8_t status_detail; /* see Login RSP Status details below */
+ uint8_t rsvd4[10];
+};
+
+/* Login stage (phase) codes for CSG, NSG */
+#define ISCSI_INITIAL_LOGIN_STAGE -1
+#define ISCSI_SECURITY_NEGOTIATION_STAGE 0
+#define ISCSI_OP_PARMS_NEGOTIATION_STAGE 1
+#define ISCSI_FULL_FEATURE_PHASE 3
+
+/* Login Status response classes */
+#define ISCSI_STATUS_CLS_SUCCESS 0x00
+#define ISCSI_STATUS_CLS_REDIRECT 0x01
+#define ISCSI_STATUS_CLS_INITIATOR_ERR 0x02
+#define ISCSI_STATUS_CLS_TARGET_ERR 0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_LOGIN_STATUS_ACCEPT 0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP 0x01
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM 0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_LOGIN_STATUS_INIT_ERR 0x00
+#define ISCSI_LOGIN_STATUS_AUTH_FAILED 0x01
+#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN 0x02
+#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND 0x03
+#define ISCSI_LOGIN_STATUS_TGT_REMOVED 0x04
+#define ISCSI_LOGIN_STATUS_NO_VERSION 0x05
+#define ISCSI_LOGIN_STATUS_ISID_ERROR 0x06
+#define ISCSI_LOGIN_STATUS_MISSING_FIELDS 0x07
+#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED 0x08
+#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE 0x09
+#define ISCSI_LOGIN_STATUS_NO_SESSION 0x0a
+#define ISCSI_LOGIN_STATUS_INVALID_REQUEST 0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_LOGIN_STATUS_TARGET_ERROR 0x00
+#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE 0x01
+#define ISCSI_LOGIN_STATUS_NO_RESOURCES 0x02
+
+/* Logout Header */
+struct iscsi_logout {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd1[2];
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd2[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be16 cid;
+ uint8_t rsvd3[2];
+ __be32 cmdsn;
+ __be32 exp_statsn;
+ uint8_t rsvd4[16];
+};
+
+/* Logout PDU flags */
+#define ISCSI_FLAG_LOGOUT_REASON_MASK 0x7F
+
+/* logout reason_code values */
+
+#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0
+#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1
+#define ISCSI_LOGOUT_REASON_RECOVERY 2
+#define ISCSI_LOGOUT_REASON_AEN_REQUEST 3
+
+/* Logout Response Header */
+struct iscsi_logout_rsp {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t response; /* see Logout response values below */
+ uint8_t rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd3[8];
+ __be32 itt; /* Initiator Task Tag */
+ __be32 rsvd4;
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 rsvd5;
+ __be16 t2wait;
+ __be16 t2retain;
+ __be32 rsvd6;
+};
+
+/* logout response status values */
+
+#define ISCSI_LOGOUT_SUCCESS 0
+#define ISCSI_LOGOUT_CID_NOT_FOUND 1
+#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED 2
+#define ISCSI_LOGOUT_CLEANUP_FAILED 3
+
+/* SNACK Header */
+struct iscsi_snack {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t rsvd2[14];
+ __be32 itt;
+ __be32 begrun;
+ __be32 runlength;
+ __be32 exp_statsn;
+ __be32 rsvd3;
+ __be32 exp_datasn;
+ uint8_t rsvd6[8];
+};
+
+/* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */
+
+/* Reject Message Header */
+struct iscsi_reject {
+ uint8_t opcode;
+ uint8_t flags;
+ uint8_t reason;
+ uint8_t rsvd2;
+ uint8_t hlength;
+ uint8_t dlength[3];
+ uint8_t rsvd3[8];
+ __be32 ffffffff;
+ uint8_t rsvd4[4];
+ __be32 statsn;
+ __be32 exp_cmdsn;
+ __be32 max_cmdsn;
+ __be32 datasn;
+ uint8_t rsvd5[8];
+ /* Text - Rejected hdr */
+};
+
+/* Reason for Reject */
+#define ISCSI_REASON_CMD_BEFORE_LOGIN 1
+#define ISCSI_REASON_DATA_DIGEST_ERROR 2
+#define ISCSI_REASON_DATA_SNACK_REJECT 3
+#define ISCSI_REASON_PROTOCOL_ERROR 4
+#define ISCSI_REASON_CMD_NOT_SUPPORTED 5
+#define ISCSI_REASON_IMM_CMD_REJECT 6
+#define ISCSI_REASON_TASK_IN_PROGRESS 7
+#define ISCSI_REASON_INVALID_SNACK 8
+#define ISCSI_REASON_BOOKMARK_INVALID 9
+#define ISCSI_REASON_BOOKMARK_NO_RESOURCES 10
+#define ISCSI_REASON_NEGOTIATION_RESET 11
+
+/* Max. number of Key=Value pairs in a text message */
+#define MAX_KEY_VALUE_PAIRS 8192
+
+/* maximum length for text keys/values */
+#define KEY_MAXLEN 64
+#define VALUE_MAXLEN 255
+#define TARGET_NAME_MAXLEN VALUE_MAXLEN
+
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192
+
+/************************* RFC 3720 End *****************************/
+
+#endif /* ISCSI_PROTO_H */
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_device.h b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_device.h
new file mode 100644
index 0000000..f353e0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_device.h
@@ -0,0 +1,19 @@
+#ifndef _SCSI_SCSI_DEVICE_H_BACKPORT
+#define _SCSI_SCSI_DEVICE_H_BACKPORT
+
+#include_next <scsi/scsi_device.h>
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+struct scsi_lun;
+
+extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void starget_for_each_device(struct scsi_target *, void *,
+ void (*fn)(struct scsi_device *, void *));
+#endif /* _SCSI_SCSI_DEVICE_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_host.h b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_host.h
new file mode 100644
index 0000000..b7e019b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_host.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_HOST_H_BACKPORT
+#define _SCSI_SCSI_HOST_H_BACKPORT
+
+#include_next <scsi/scsi_host.h>
+
+#define scsi_queue_work(shost, work) schedule_work(work)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_transport.h b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..99c2b12
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_transport.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_TRANSPORT_H_BACKPORT
+#define _SCSI_SCSI_TRANSPORT_H_BACKPORT
+
+#include_next <scsi/scsi_transport.h>
+
+#include <linux/transport_class.h>
+
+#endif /* _SCSI_SCSI_TRANSPORT_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/attribute_container.c b/kernel_addons/backport/2.6.9_U5/include/src/attribute_container.c
new file mode 100644
index 0000000..44948d1
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/attribute_container.c
@@ -0,0 +1,438 @@
+/*
+ * attribute_container.c - implementation of a simple container for classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to enable a device to be attached to an
+ * aritrary numer of classes without having to allocate storage for them.
+ * Instead, the contained classes select the devices they need to attach
+ * to via a matching function.
+ */
+
+#include <linux/attribute_container.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include "base.h"
+
+/* This is a private structure used to tie the classdev and the
+ * container .. it should never be visible outside this file */
+struct internal_container {
+ struct klist_node node;
+ struct attribute_container *cont;
+ struct class_device classdev;
+};
+
+static void internal_container_klist_get(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+ class_device_put(&ic->classdev);
+}
+
+
+/**
+ * attribute_container_classdev_to_container - given a classdev, return the container
+ *
+ * @classdev: the class device created by attribute_container_add_device.
+ *
+ * Returns the container associated with this classdev.
+ */
+struct attribute_container *
+attribute_container_classdev_to_container(struct class_device *classdev)
+{
+ struct internal_container *ic =
+ container_of(classdev, struct internal_container, classdev);
+ return ic->cont;
+}
+EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+
+static struct list_head attribute_container_list;
+
+static DECLARE_MUTEX(attribute_container_mutex);
+
+/**
+ * attribute_container_register - register an attribute container
+ *
+ * @cont: The container to register. This must be allocated by the
+ * callee and should also be zeroed by it.
+ */
+int
+attribute_container_register(struct attribute_container *cont)
+{
+ INIT_LIST_HEAD(&cont->node);
+ klist_init(&cont->containers,internal_container_klist_get,
+ internal_container_klist_put);
+
+ down(&attribute_container_mutex);
+ list_add_tail(&cont->node, &attribute_container_list);
+ up(&attribute_container_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_register);
+
+/**
+ * attribute_container_unregister - remove a container registration
+ *
+ * @cont: previously registered container to remove
+ */
+int
+attribute_container_unregister(struct attribute_container *cont)
+{
+ int retval = -EBUSY;
+ down(&attribute_container_mutex);
+ spin_lock(&cont->containers.k_lock);
+ if (!list_empty(&cont->containers.k_list))
+ goto out;
+ retval = 0;
+ list_del(&cont->node);
+ out:
+ spin_unlock(&cont->containers.k_lock);
+ up(&attribute_container_mutex);
+ return retval;
+
+}
+EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+/* private function used as class release */
+static void attribute_container_release(struct class_device *classdev)
+{
+ struct internal_container *ic
+ = container_of(classdev, struct internal_container, classdev);
+ struct device *dev = classdev->dev;
+
+ kfree(ic);
+ put_device(dev);
+}
+
+/**
+ * attribute_container_add_device - see if any container is interested in dev
+ *
+ * @dev: device to add attributes to
+ * @fn: function to trigger addition of class device.
+ *
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container). If no
+ * fn is provided, the code will simply register the class device via
+ * class_device_add. If a function is provided, it is expected to add
+ * the class device at the appropriate time. One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time. To do this, call this routine for
+ * allocation and initialisation and then use
+ * attribute_container_device_trigger() to call class_device_add() on
+ * it. Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+void
+attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+
+ if (attribute_container_no_classdevs(cont))
+ continue;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
+ if (!ic) {
+ dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+ continue;
+ }
+
+ ic->cont = cont;
+ class_device_initialize(&ic->classdev);
+ ic->classdev.dev = get_device(dev);
+ ic->classdev.class = cont->class;
+ cont->class->release = attribute_container_release;
+ strcpy(ic->classdev.class_id, dev->bus_id);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else
+ attribute_container_add_class_device(&ic->classdev);
+ klist_add_tail(&ic->node, &cont->containers);
+ }
+ up(&attribute_container_mutex);
+}
+
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+ for (klist_iter_init(head, iter); (pos = ({ \
+ struct klist_node *n = klist_next(iter); \
+ n ? container_of(n, typeof(*pos), member) : \
+ ({ klist_iter_exit(iter) ; NULL; }); \
+ }) ) != NULL; )
+
+
+/**
+ * attribute_container_remove_device - make device eligible for removal.
+ *
+ * @dev: The generic device
+ * @fn: A function to call to remove the device
+ *
+ * This routine triggers device removal. If fn is NULL, then it is
+ * simply done via class_device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released). If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+ * class_device_del() and then use
+ * attribute_container_device_trigger() to do the final put on the
+ * classdev.
+ */
+void
+attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ if (attribute_container_no_classdevs(cont))
+ continue;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (dev != ic->classdev.dev)
+ continue;
+ klist_del(&ic->node);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else {
+ attribute_container_remove_attrs(&ic->classdev);
+ class_device_unregister(&ic->classdev);
+ }
+ }
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_device_trigger - execute a trigger for each matching classdev
+ *
+ * @dev: The generic device to run the trigger for
+ * @fn the function to execute for each classdev.
+ *
+ * This funcion is for executing a trigger when you need to know both
+ * the container and the classdev. If you only care about the
+ * container, then use attribute_container_trigger() instead.
+ */
+void
+attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+ struct class_device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ if (!cont->match(cont, dev))
+ continue;
+
+ if (attribute_container_no_classdevs(cont)) {
+ fn(cont, dev, NULL);
+ continue;
+ }
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (dev == ic->classdev.dev)
+ fn(cont, dev, &ic->classdev);
+ }
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_trigger - trigger a function for each matching container
+ *
+ * @dev: The generic device to activate the trigger for
+ * @fn: the function to trigger
+ *
+ * This routine triggers a function that only needs to know the
+ * matching containers (not the classdev) associated with a device.
+ * It is more lightweight than attribute_container_device_trigger, so
+ * should be used in preference unless the triggering function
+ * actually needs to know the classdev.
+ */
+void
+attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *))
+{
+ struct attribute_container *cont;
+
+ down(&attribute_container_mutex);
+ list_for_each_entry(cont, &attribute_container_list, node) {
+ if (cont->match(cont, dev))
+ fn(cont, dev);
+ }
+ up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_add_attrs - add attributes
+ *
+ * @classdev: The class device
+ *
+ * This simply creates all the class device sysfs files from the
+ * attributes listed in the container
+ */
+int
+attribute_container_add_attrs(struct class_device *classdev)
+{
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+ struct class_device_attribute **attrs = cont->attrs;
+ int i, error;
+
+ if (!attrs)
+ return 0;
+
+ for (i = 0; attrs[i]; i++) {
+ error = class_device_create_file(classdev, attrs[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+/**
+ * attribute_container_add_class_device - same function as class_device_add
+ *
+ * @classdev: the class device to add
+ *
+ * This performs essentially the same function as class_device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+int
+attribute_container_add_class_device(struct class_device *classdev)
+{
+ int error = class_device_add(classdev);
+ if (error)
+ return error;
+ return attribute_container_add_attrs(classdev);
+}
+
+/**
+ * attribute_container_add_class_device_adapter - simple adapter for triggers
+ *
+ * This function is identical to attribute_container_add_class_device except
+ * that it is designed to be called from the triggers
+ */
+int
+attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ return attribute_container_add_class_device(classdev);
+}
+
+/**
+ * attribute_container_remove_attrs - remove any attribute files
+ *
+ * @classdev: The class device to remove the files from
+ *
+ */
+void
+attribute_container_remove_attrs(struct class_device *classdev)
+{
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+ struct class_device_attribute **attrs = cont->attrs;
+ int i;
+
+ if (!attrs)
+ return;
+
+ for (i = 0; attrs[i]; i++)
+ class_device_remove_file(classdev, attrs[i]);
+}
+
+/**
+ * attribute_container_class_device_del - equivalent of class_device_del
+ *
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+ * class_device_del.
+ */
+void
+attribute_container_class_device_del(struct class_device *classdev)
+{
+ attribute_container_remove_attrs(classdev);
+ class_device_del(classdev);
+}
+
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont: the container
+ * @dev: the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct class_device *cdev = NULL;
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+ if (ic->classdev.dev == dev) {
+ cdev = &ic->classdev;
+ /* FIXME: must exit iterator then break */
+ klist_iter_exit(&iter);
+ break;
+ }
+ }
+
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
+int
+attribute_container_init(void)
+{
+ INIT_LIST_HEAD(&attribute_container_list);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_init);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/base.h b/kernel_addons/backport/2.6.9_U5/include/src/base.h
new file mode 100644
index 0000000..a5f8936
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/base.h
@@ -0,0 +1 @@
+extern int attribute_container_init(void);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/init.c b/kernel_addons/backport/2.6.9_U5/include/src/init.c
new file mode 100644
index 0000000..15f0bc6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/init.c
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
+
+/**
+ * driver_init - initialize driver model.
+ *
+ * Call the driver model init functions to initialize their
+ * subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+ attribute_container_init();
+}
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/klist.c b/kernel_addons/backport/2.6.9_U5/include/src/klist.c
new file mode 100644
index 0000000..3b29ebc
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/klist.c
@@ -0,0 +1,287 @@
+/*
+ * klist.c - Routines for manipulating klists.
+ *
+ *
+ * This klist interface provides a couple of structures that wrap around
+ * struct list_head to provide explicit list "head" (struct klist) and
+ * list "node" (struct klist_node) objects. For struct klist, a spinlock
+ * is included that protects access to the actual list itself. struct
+ * klist_node provides a pointer to the klist that owns it and a kref
+ * reference count that indicates the number of current users of that node
+ * in the list.
+ *
+ * The entire point is to provide an interface for iterating over a list
+ * that is safe and allows for modification of the list during the
+ * iteration (e.g. insertion and removal), including modification of the
+ * current node on the list.
+ *
+ * It works using a 3rd object type - struct klist_iter - that is declared
+ * and initialized before an iteration. klist_next() is used to acquire the
+ * next element in the list. It returns NULL if there are no more items.
+ * Internally, that routine takes the klist's lock, decrements the reference
+ * count of the previous klist_node and increments the count of the next
+ * klist_node. It then drops the lock and returns.
+ *
+ * There are primitives for adding and removing nodes to/from a klist.
+ * When deleting, klist_del() will simply decrement the reference count.
+ * Only when the count goes to 0 is the node removed from the list.
+ * klist_remove() will try to delete the node from the list and block
+ * until it is actually removed. This is useful for objects (like devices)
+ * that have been removed from the system and must be freed (but must wait
+ * until all accessors have finished).
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ * klist_init - Initialize a klist structure.
+ * @k: The klist we're initializing.
+ * @get: The get function for the embedding object (NULL if none)
+ * @put: The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure. If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
+ */
+
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+ void (*put)(struct klist_node *))
+{
+ INIT_LIST_HEAD(&k->k_list);
+ spin_lock_init(&k->k_lock);
+ k->get = get;
+ k->put = put;
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add_tail(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+ INIT_LIST_HEAD(&n->n_node);
+ init_completion(&n->n_removed);
+ kref_init(&n->n_ref);
+ n->n_klist = k;
+ if (k->get)
+ k->get(n);
+}
+
+
+/**
+ * klist_add_head - Initialize a klist_node and add it to front.
+ * @n: node we're adding.
+ * @k: klist it's going on.
+ */
+
+void klist_add_head(struct klist_node * n, struct klist * k)
+{
+ klist_node_init(k, n);
+ add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ * klist_add_tail - Initialize a klist_node and add it to back.
+ * @n: node we're adding.
+ * @k: klist it's going on.
+ */
+
+void klist_add_tail(struct klist_node * n, struct klist * k)
+{
+ klist_node_init(k, n);
+ add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+ struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+
+ list_del(&n->n_node);
+ complete(&n->n_removed);
+ n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+ return kref_put_new(&n->n_ref, klist_release);
+}
+
+
+/**
+ * klist_del - Decrement the reference count of node and try to remove.
+ * @n: node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+ struct klist * k = n->n_klist;
+ void (*put)(struct klist_node *) = k->put;
+
+ spin_lock(&k->k_lock);
+ if (!klist_dec_and_del(n))
+ put = NULL;
+ spin_unlock(&k->k_lock);
+ if (put)
+ put(n);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ * klist_remove - Decrement the refcount of node and wait for it to go away.
+ * @n: node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+ klist_del(n);
+ wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ * klist_node_attached - Say whether a node is bound to a list or not.
+ * @n: Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+ return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ * klist_iter_init_node - Initialize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter we're filling.
+ * @n: node to start with.
+ *
+ * Similar to klist_iter_init(), but starts the action off with @n,
+ * instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+ i->i_klist = k;
+ i->i_head = &k->k_list;
+ i->i_cur = n;
+ if (n)
+ kref_get(&n->n_ref);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ * klist_iter_init - Iniitalize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter structure we're filling.
+ *
+ * Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+ klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ * klist_iter_exit - Finish a list iteration.
+ * @i: Iterator structure.
+ *
+ * Must be called when done iterating over list, as it decrements the
+ * refcount of the current node. Necessary in case iteration exited before
+ * the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+ if (i->i_cur) {
+ klist_del(i->i_cur);
+ i->i_cur = NULL;
+ }
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+ return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ * klist_next - Ante up next node in list.
+ * @i: Iterator structure.
+ *
+ * First grab list lock. Decrement the reference count of the previous
+ * node, if there was one. Grab the next node, increment its reference
+ * count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+ struct list_head * next;
+ struct klist_node * lnode = i->i_cur;
+ struct klist_node * knode = NULL;
+ void (*put)(struct klist_node *) = i->i_klist->put;
+
+ spin_lock(&i->i_klist->k_lock);
+ if (lnode) {
+ next = lnode->n_node.next;
+ if (!klist_dec_and_del(lnode))
+ put = NULL;
+ } else
+ next = i->i_head->next;
+
+ if (next != i->i_head) {
+ knode = to_klist_node(next);
+ kref_get(&knode->n_ref);
+ }
+ i->i_cur = knode;
+ spin_unlock(&i->i_klist->k_lock);
+ if (put && lnode)
+ put(lnode);
+ return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/kref_new.c b/kernel_addons/backport/2.6.9_U5/include/src/kref_new.c
new file mode 100644
index 0000000..d45bb3f
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/kref_new.c
@@ -0,0 +1,29 @@
+#include <linux/kref.h>
+#include <linux/module.h>
+
+/**
+ * kref_put - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ * last reference to the object is released.
+ * This pointer is required, and it is not acceptable to pass kfree
+ * in as this function.
+ *
+ * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0. Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory. Only use the return value if you want to see if the kref is now
+ * gone, not present.
+ */
+int kref_put_new(struct kref *kref, void (*release)(struct kref *kref))
+{
+ WARN_ON(release == NULL);
+ WARN_ON(release == (void (*)(struct kref *))kfree);
+
+ if (atomic_dec_and_test(&kref->refcount)) {
+ release(kref);
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(kref_put_new);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/scsi.c b/kernel_addons/backport/2.6.9_U5/include/src/scsi.c
new file mode 100644
index 0000000..8c833c0
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/scsi.c
@@ -0,0 +1,50 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/unistd.h>
+#include <linux/spinlock.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * starget_for_each_device - helper to walk all devices of a target
+ * @starget: target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost. The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+ void (*fn)(struct scsi_device *, void *))
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct scsi_device *sdev;
+
+ printk("%s: entry\n", __FUNCTION__);
+ shost_for_each_device(sdev, shost) {
+ if ((sdev->channel == starget->channel) &&
+ (sdev->id == starget->id))
+ fn(sdev, data);
+ }
+ printk("%s: exit\n", __FUNCTION__);
+}
+EXPORT_SYMBOL(starget_for_each_device);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/scsi_lib.c b/kernel_addons/backport/2.6.9_U5/include/src/scsi_lib.c
new file mode 100644
index 0000000..f53f824
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/scsi_lib.c
@@ -0,0 +1,166 @@
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+int scsi_is_target_device(const struct device *dev)
+{
+ char *str = dev->bus_id;
+
+ if (strncmp(str, "target", 6) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * scsi_internal_device_block - internal function to put a device
+ * temporarily into the SDEV_BLOCK state
+ * @sdev: device to block
+ *
+ * Block request made by scsi lld's to temporarily stop all
+ * scsi commands on the specified device. Called from interrupt
+ * or normal process context.
+ *
+ * Returns zero if successful or error if not
+ *
+ * Notes:
+ * This routine transitions the device to the SDEV_BLOCK state
+ * (which must be a legal transition). When the device is in this
+ * state, all commands are deferred until the scsi lld reenables
+ * the device with scsi_device_unblock or device_block_tmo fires.
+ * This routine assumes the host_lock is held on entry.
+ **/
+int
+scsi_internal_device_block(struct scsi_device *sdev)
+{
+ request_queue_t *q = sdev->request_queue;
+ unsigned long flags;
+ int err = 0;
+
+ err = scsi_device_set_state(sdev, SDEV_BLOCK);
+ if (err)
+ return err;
+
+ /*
+ * The device has transitioned to SDEV_BLOCK. Stop the
+ * block layer from calling the midlayer with this device's
+ * request queue.
+ */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+
+/**
+ * scsi_internal_device_unblock - resume a device after a block request
+ * @sdev: device to resume
+ *
+ * Called by scsi lld's or the midlayer to restart the device queue
+ * for the previously suspended scsi device. Called from interrupt or
+ * normal process context.
+ *
+ * Returns zero if successful or error if not.
+ *
+ * Notes:
+ * This routine transitions the device to the SDEV_RUNNING state
+ * (which must be a legal transition) allowing the midlayer to
+ * goose the queue for this device. This routine assumes the
+ * host_lock is held upon entry.
+ **/
+int
+scsi_internal_device_unblock(struct scsi_device *sdev)
+{
+ request_queue_t *q = sdev->request_queue;
+ int err;
+ unsigned long flags;
+
+
+ /*
+ * Try to transition the scsi device to SDEV_RUNNING
+ * and goose the device queue if successful.
+ */
+ err = scsi_device_set_state(sdev, SDEV_RUNNING);
+ if (err)
+ return err;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+
+ return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+ else
+ device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ else
+ device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+MODULE_LICENSE("GPL");
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/scsi_scan.c b/kernel_addons/backport/2.6.9_U5/include/src/scsi_scan.c
new file mode 100644
index 0000000..b7b7674
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/scsi_scan.c
@@ -0,0 +1,48 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+
+/**
+ * int_to_scsilun: reverts an int into a scsi_lun
+ * @int: integer to be reverted
+ * @scsilun: struct scsi_lun to be set.
+ *
+ * Description:
+ * Reverts the functionality of the scsilun_to_int, which packed
+ * an 8-byte lun value into an int. This routine unpacks the int
+ * back into the lun value.
+ * Note: the scsilun_to_int() routine does not truly handle all
+ * 8bytes of the lun value. This functions restores only as much
+ * as was set by the routine.
+ *
+ * Notes:
+ * Given an integer : 0x0b030a04, this function returns a
+ * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *
+ **/
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+ int i;
+
+ memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+ for (i = 0; i < sizeof(lun); i += 2) {
+ scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+ scsilun->scsi_lun[i+1] = lun & 0xFF;
+ lun = lun >> 16;
+ }
+}
+EXPORT_SYMBOL(int_to_scsilun);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/transport_class.c b/kernel_addons/backport/2.6.9_U5/include/src/transport_class.c
new file mode 100644
index 0000000..f25e7c6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/transport_class.c
@@ -0,0 +1,280 @@
+/*
+ * transport_class.c - implementation of generic transport classes
+ * using attribute_containers
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to allow any "device controller" (which
+ * would most often be a Host Bus Adapter to use the services of one
+ * or more tranport classes for performing transport specific
+ * services. Transport specific services are things that the generic
+ * command layer doesn't want to know about (speed settings, line
+ * condidtioning, etc), but which the user might be interested in.
+ * Thus, the HBA's use the routines exported by the transport classes
+ * to perform these functions. The transport classes export certain
+ * values to the user via sysfs using attribute containers.
+ *
+ * Note: because not every HBA will care about every transport
+ * attribute, there's a many to one relationship that goes like this:
+ *
+ * transport class<-----attribute container<----class device
+ *
+ * Usually the attribute container is per-HBA, but the design doesn't
+ * mandate that. Although most of the services will be specific to
+ * the actual external storage connection used by the HBA, the generic
+ * transport class is framed entirely in terms of generic devices to
+ * allow it to be used by any physical HBA in the system.
+ */
+#include <linux/attribute_container.h>
+#include <linux/transport_class.h>
+
+/**
+ * transport_class_register - register an initial transport class
+ *
+ * @tclass: a pointer to the transport class structure to be initialised
+ *
+ * The transport class contains an embedded class which is used to
+ * identify it. The caller should initialise this structure with
+ * zeros and then generic class must have been initialised with the
+ * actual transport class unique name. There's a macro
+ * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
+ * be registered).
+ *
+ * Returns 0 on success or error on failure.
+ */
+int transport_class_register(struct transport_class *tclass)
+{
+ return class_register(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_register);
+
+/**
+ * transport_class_unregister - unregister a previously registered class
+ *
+ * @tclass: The transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the transport
+ * class.
+ */
+void transport_class_unregister(struct transport_class *tclass)
+{
+ class_unregister(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ /* do nothing */
+ return 0;
+}
+
+/**
+ * anon_transport_class_register - register an anonymous class
+ *
+ * @atc: The anon transport class to register
+ *
+ * The anonymous transport class contains both a transport class and a
+ * container. The idea of an anonymous class is that it never
+ * actually has any device attributes associated with it (and thus
+ * saves on container storage). So it can only be used for triggering
+ * events. Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
+ * initialise the anon transport class storage.
+ */
+int anon_transport_class_register(struct anon_transport_class *atc)
+{
+ int error;
+ atc->container.class = &atc->tclass.class;
+ attribute_container_set_no_classdevs(&atc->container);
+ error = attribute_container_register(&atc->container);
+ if (error)
+ return error;
+ atc->tclass.setup = anon_transport_dummy_function;
+ atc->tclass.remove = anon_transport_dummy_function;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_register);
+
+/**
+ * anon_transport_class_unregister - unregister an anon class
+ *
+ * @atc: Pointer to the anon transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the anon
+ * transport class.
+ */
+void anon_transport_class_unregister(struct anon_transport_class *atc)
+{
+ attribute_container_unregister(&atc->container);
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+static int transport_setup_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+ if (tclass->setup)
+ tclass->setup(tcont, dev, classdev);
+
+ return 0;
+}
+
+/**
+ * transport_setup_device - declare a new dev for transport class association
+ * but don't make it visible yet.
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus). This
+ * routine is simply a trigger point to see if any set of transport
+ * classes wishes to associate with the added device. This allocates
+ * storage for the class device and initialises it, but does not yet
+ * add it to the system or add attributes to it (you do this with
+ * transport_add_device). If you have no need for a separate setup
+ * and add operations, use transport_register_device (see
+ * transport_class.h).
+ */
+
+void transport_setup_device(struct device *dev)
+{
+ attribute_container_add_device(dev, transport_setup_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_setup_device);
+
+static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+
+ if (!error && tcont->statistics)
+ error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+ return error;
+}
+
+
+/**
+ * transport_add_device - declare a new dev for transport class association
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus). This
+ * routine is simply a trigger point used to add the device to the
+ * system and register attributes for it.
+ */
+
+void transport_add_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_add_class_device);
+}
+EXPORT_SYMBOL_GPL(transport_add_device);
+
+static int transport_configure(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *cdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+ if (tclass->configure)
+ tclass->configure(tcont, dev, cdev);
+
+ return 0;
+}
+
+/**
+ * transport_configure_device - configure an already set up device
+ *
+ * @dev: generic device representing device to be configured
+ *
+ * The idea of configure is simply to provide a point within the setup
+ * process to allow the transport class to extract information from a
+ * device after it has been setup. This is used in SCSI because we
+ * have to have a setup device to begin using the HBA, but after we
+ * send the initial inquiry, we use configure to extract the device
+ * parameters. The device need not have been added to be configured.
+ */
+void transport_configure_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_configure);
+}
+EXPORT_SYMBOL_GPL(transport_configure_device);
+
+static int transport_remove_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove)
+ tclass->remove(tcont, dev, classdev);
+
+ if (tclass->remove != anon_transport_dummy_function) {
+ if (tcont->statistics)
+ sysfs_remove_group(&classdev->kobj, tcont->statistics);
+ attribute_container_class_device_del(classdev);
+ }
+
+ return 0;
+}
+
+
+/**
+ * transport_remove_device - remove the visibility of a device
+ *
+ * @dev: generic device to remove
+ *
+ * This call removes the visibility of the device (to the user from
+ * sysfs), but does not destroy it. To eliminate a device entirely
+ * you must also call transport_destroy_device. If you don't need to
+ * do remove and destroy as separate operations, use
+ * transport_unregister_device() (see transport_class.h) which will
+ * perform both calls for you.
+ */
+void transport_remove_device(struct device *dev)
+{
+ attribute_container_device_trigger(dev, transport_remove_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_remove_device);
+
+static void transport_destroy_classdev(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove != anon_transport_dummy_function)
+ class_device_put(classdev);
+}
+
+
+/**
+ * transport_destroy_device - destroy a removed device
+ *
+ * @dev: device to eliminate from the transport class.
+ *
+ * This call triggers the elimination of storage associated with the
+ * transport classdev. Note: all it really does is relinquish a
+ * reference to the classdev. The memory will not be freed until the
+ * last reference goes to zero. Note also that the classdev retains a
+ * reference count on dev, so dev too will remain for as long as the
+ * transport class device remains around.
+ */
+void transport_destroy_device(struct device *dev)
+{
+ attribute_container_remove_device(dev, transport_destroy_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_destroy_device);
diff --git a/kernel_patches/backport/2.6.16_sles10/iscsi_scsi_makefile.patch b/kernel_patches/backport/2.6.16_sles10/iscsi_scsi_makefile.patch
new file mode 100644
index 0000000..30b6f0e
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10/iscsi_scsi_makefile.patch
@@ -0,0 +1,9 @@
+diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
+--- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile 2006-12-28 17:01:22.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o
++libiscsi-y := libiscsi_f.o
diff --git a/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_scsi_makefile.patch b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_scsi_makefile.patch
new file mode 100644
index 0000000..30b6f0e
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_scsi_makefile.patch
@@ -0,0 +1,9 @@
+diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
+--- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile 2006-12-28 17:01:22.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o
++libiscsi-y := libiscsi_f.o
diff --git a/kernel_patches/backport/2.6.18/iscsi_scsi_makefile.patch b/kernel_patches/backport/2.6.18/iscsi_scsi_makefile.patch
new file mode 100644
index 0000000..30b6f0e
--- /dev/null
+++ b/kernel_patches/backport/2.6.18/iscsi_scsi_makefile.patch
@@ -0,0 +1,9 @@
+diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
+--- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile 2006-12-28 17:01:22.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o
++libiscsi-y := libiscsi_f.o
diff --git a/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
new file mode 100644
index 0000000..a339163
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
@@ -0,0 +1,270 @@
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c 2007-05-17 16:55:43.000000000 +0300
+@@ -676,7 +676,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn,
+ }
+
+ static inline void
+-partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
++partial_sg_digest_update(struct crypto_tfm *desc, struct scatterlist *sg,
+ int offset, int length)
+ {
+ struct scatterlist temp;
+@@ -684,7 +684,7 @@ partial_sg_digest_update(struct hash_des
+ memcpy(&temp, sg, sizeof(struct scatterlist));
+ temp.offset = offset;
+ temp.length = length;
+- crypto_hash_update(desc, &temp, length);
++ crypto_hash_update(&desc, &temp, length);
+ }
+
+ static void
+@@ -1774,22 +1774,18 @@ iscsi_tcp_conn_create(struct iscsi_cls_s
+ /* initial operational parameters */
+ tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+
+- tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+- CRYPTO_ALG_ASYNC);
+- tcp_conn->tx_hash.flags = 0;
+- if (IS_ERR(tcp_conn->tx_hash.tfm))
++ tcp_conn->tx_hash = crypto_alloc_tfm("crc32c", 0);
++ if (!tcp_conn->tx_hash)
+ goto free_tcp_conn;
+
+- tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+- CRYPTO_ALG_ASYNC);
+- tcp_conn->rx_hash.flags = 0;
+- if (IS_ERR(tcp_conn->rx_hash.tfm))
++ tcp_conn->rx_hash = crypto_alloc_tfm("crc32c", 0);
++ if (!tcp_conn->rx_hash)
+ goto free_tx_tfm;
+
+ return cls_conn;
+
+ free_tx_tfm:
+- crypto_free_hash(tcp_conn->tx_hash.tfm);
++ crypto_free_tfm(tcp_conn->tx_hash);
+ free_tcp_conn:
+ kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+@@ -1823,10 +1819,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_
+ iscsi_tcp_release_conn(conn);
+ iscsi_conn_teardown(cls_conn);
+
+- if (tcp_conn->tx_hash.tfm)
+- crypto_free_hash(tcp_conn->tx_hash.tfm);
+- if (tcp_conn->rx_hash.tfm)
+- crypto_free_hash(tcp_conn->rx_hash.tfm);
++ if (tcp_conn->tx_hash)
++ crypto_free_tfm(tcp_conn->tx_hash);
++ if (tcp_conn->rx_hash)
++ crypto_free_tfm(tcp_conn->rx_hash);
+
+ kfree(tcp_conn);
+ }
+@@ -2017,7 +2013,7 @@ iscsi_tcp_conn_get_param(struct iscsi_cl
+ {
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+- struct inet_sock *inet;
++ struct inet_opt *inet;
+ struct ipv6_pinfo *np;
+ struct sock *sk;
+ int len;
+@@ -2135,7 +2131,6 @@ static void iscsi_tcp_session_destroy(st
+ static struct scsi_host_template iscsi_sht = {
+ .name = "iSCSI Initiator over TCP/IP",
+ .queuecommand = iscsi_queuecommand,
+- .change_queue_depth = iscsi_change_queue_depth,
+ .can_queue = ISCSI_XMIT_CMDS_MAX - 1,
+ .sg_tablesize = ISCSI_SG_TABLESIZE,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.h linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h 2007-05-17 16:38:14.000000000 +0300
+@@ -49,7 +49,6 @@
+ #define ISCSI_SG_TABLESIZE SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN 16
+
+-struct crypto_hash;
+ struct socket;
+
+ /* Socket connection recieve helper */
+@@ -93,8 +92,8 @@ struct iscsi_tcp_conn {
+ void (*old_write_space)(struct sock *);
+
+ /* data and header digests */
+- struct hash_desc tx_hash; /* CRC32C (Tx) */
+- struct hash_desc rx_hash; /* CRC32C (Rx) */
++ struct crypto_tfm *tx_hash; /* CRC32C (Tx) */
++ struct crypto_tfm *rx_hash; /* CRC32C (Rx) */
+
+ /* MIB custom statistics */
+ uint32_t sendpage_failures_cnt;
+diff -rup linux-2.6.20/drivers/scsi/libiscsi.c linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c
+--- linux-2.6.20/drivers/scsi/libiscsi.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c 2007-05-17 16:38:14.000000000 +0300
+@@ -1370,7 +1370,6 @@ iscsi_session_setup(struct iscsi_transpo
+ shost->max_lun = iscsit->max_lun;
+ shost->max_cmd_len = iscsit->max_cmd_len;
+ shost->transportt = scsit;
+- shost->transportt->create_work_queue = 1;
+ *hostno = shost->host_no;
+
+ session = iscsi_hostdata(shost->hostdata);
+diff -rup linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c 2007-05-17 16:38:14.000000000 +0300
+@@ -65,6 +65,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
+ #define cdev_to_iscsi_internal(_cdev) \
+ container_of(_cdev, struct iscsi_internal, cdev)
+
++extern int attribute_container_init(void);
++
+ static void iscsi_transport_release(struct class_device *cdev)
+ {
+ struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+@@ -80,6 +82,17 @@ static struct class iscsi_transport_clas
+ .release = iscsi_transport_release,
+ };
+
++static void iscsi_host_class_release(struct class_device *class_dev)
++{
++ struct Scsi_Host *shost = transport_class_to_shost(class_dev);
++ put_device(&shost->shost_gendev);
++}
++
++struct class iscsi_host_class = {
++ .name = "iscsi_host",
++ .release = iscsi_host_class_release,
++};
++
+ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+@@ -115,10 +128,8 @@ static struct attribute_group iscsi_tran
+ .attrs = iscsi_transport_attrs,
+ };
+
+-static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++static int iscsi_setup_host(struct Scsi_Host *shost)
+ {
+- struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_host *ihost = shost->shost_data;
+
+ memset(ihost, 0, sizeof(*ihost));
+@@ -127,12 +138,6 @@ static int iscsi_setup_host(struct trans
+ return 0;
+ }
+
+-static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+- "iscsi_host",
+- iscsi_setup_host,
+- NULL,
+- NULL);
+-
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ "iscsi_session",
+ NULL,
+@@ -216,24 +221,6 @@ static int iscsi_is_session_dev(const st
+ return dev->release == iscsi_session_release;
+ }
+
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+- uint id, uint lun)
+-{
+- struct iscsi_host *ihost = shost->shost_data;
+- struct iscsi_cls_session *session;
+-
+- mutex_lock(&ihost->mutex);
+- list_for_each_entry(session, &ihost->sessions, host_list) {
+- if ((channel == SCAN_WILD_CARD || channel == 0) &&
+- (id == SCAN_WILD_CARD || id == session->target_id))
+- scsi_scan_target(&session->dev, 0,
+- session->target_id, lun, 1);
+- }
+- mutex_unlock(&ihost->mutex);
+-
+- return 0;
+-}
+-
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ struct iscsi_cls_session *session =
+@@ -362,8 +349,6 @@ void iscsi_remove_session(struct iscsi_c
+ list_del(&session->host_list);
+ mutex_unlock(&ihost->mutex);
+
+- scsi_remove_target(&session->dev);
+-
+ transport_unregister_device(&session->dev);
+ device_del(&session->dev);
+ }
+@@ -1269,24 +1254,6 @@ static int iscsi_conn_match(struct attri
+ return &priv->conn_cont.ac == cont;
+ }
+
+-static int iscsi_host_match(struct attribute_container *cont,
+- struct device *dev)
+-{
+- struct Scsi_Host *shost;
+- struct iscsi_internal *priv;
+-
+- if (!scsi_is_host_device(dev))
+- return 0;
+-
+- shost = dev_to_shost(dev);
+- if (!shost->transportt ||
+- shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+- return 0;
+-
+- priv = to_iscsi_internal(shost->transportt);
+- return &priv->t.host_attrs.ac == cont;
+-}
+-
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1306,7 +1273,6 @@ iscsi_register_transport(struct iscsi_tr
+ INIT_LIST_HEAD(&priv->list);
+ priv->daemon_pid = -1;
+ priv->iscsi_transport = tt;
+- priv->t.user_scan = iscsi_user_scan;
+
+ priv->cdev.class = &iscsi_transport_class;
+ snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1319,12 +1285,11 @@ iscsi_register_transport(struct iscsi_tr
+ goto unregister_cdev;
+
+ /* host parameters */
+- priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+- priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+- priv->t.host_attrs.ac.match = iscsi_host_match;
++
++ priv->t.host_attrs = &priv->host_attrs[0];
++ priv->t.host_class = &iscsi_host_class;
++ priv->t.host_setup = iscsi_setup_host;
+ priv->t.host_size = sizeof(struct iscsi_host);
+- priv->host_attrs[0] = NULL;
+- transport_container_register(&priv->t.host_attrs);
+
+ /* connection parameters */
+ priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+@@ -1402,7 +1367,6 @@ int iscsi_unregister_transport(struct is
+
+ transport_container_unregister(&priv->conn_cont);
+ transport_container_unregister(&priv->session_cont);
+- transport_container_unregister(&priv->t.host_attrs);
+
+ sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ class_device_unregister(&priv->cdev);
+@@ -1419,6 +1383,8 @@ static __init int iscsi_transport_init(v
+ printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ ISCSI_TRANSPORT_VERSION);
+
++ attribute_container_init();
++
+ err = class_register(&iscsi_transport_class);
+ if (err)
+ return err;
diff --git a/kernel_patches/backport/2.6.9_U3/add_open_iscsi_h.patch b/kernel_patches/backport/2.6.9_U3/add_open_iscsi_h.patch
new file mode 100644
index 0000000..21715fd
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/add_open_iscsi_h.patch
@@ -0,0 +1,35 @@
+diff -rup linux-2.6.20/include/scsi/iscsi_if.h linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h
+--- linux-2.6.20/include/scsi/iscsi_if.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h 2007-05-15 08:49:53.000000000 +0300
+@@ -277,7 +277,6 @@ enum iscsi_param {
+ * These flags describes reason of stop_conn() call
+ */
+ #define STOP_CONN_TERM 0x1
+-#define STOP_CONN_SUSPEND 0x2
+ #define STOP_CONN_RECOVER 0x3
+
+ #define ISCSI_STATS_CUSTOM_MAX 32
+diff -rup linux-2.6.20/include/scsi/libiscsi.h linux-2.6.20-rh4-backport/include/scsi/libiscsi.h
+--- linux-2.6.20/include/scsi/libiscsi.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/libiscsi.h 2007-05-15 08:54:49.000000000 +0300
+@@ -25,8 +25,6 @@
+
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+-#include <linux/timer.h>
+-#include <linux/workqueue.h>
+ #include <scsi/iscsi_proto.h>
+ #include <scsi/iscsi_if.h>
+
+diff -rup linux-2.6.20/include/scsi/scsi_transport_iscsi.h linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.20/include/scsi/scsi_transport_iscsi.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h 2007-05-15 08:54:24.000000000 +0300
+@@ -24,7 +24,7 @@
+ #define SCSI_TRANSPORT_ISCSI_H
+
+ #include <linux/device.h>
+-#include <scsi/iscsi_if.h>
++#include "iscsi_if.h"
+
+ struct scsi_transport_template;
+ struct iscsi_transport;
diff --git a/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
new file mode 100644
index 0000000..3c2a969
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:13:43.000000000 +0200
++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:14:31.000000000 +0200
+@@ -70,9 +70,8 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+-#include <scsi/scsi_transport_iscsi.h>
+-
+ #include "iscsi_iser.h"
++#include <scsi/scsi_transport_iscsi.h>
+
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
diff --git a/kernel_patches/backport/2.6.9_U3/iscsi_scsi_addons.patch b/kernel_patches/backport/2.6.9_U3/iscsi_scsi_addons.patch
new file mode 100644
index 0000000..ffa0598
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/iscsi_scsi_addons.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/scsi/init.c b/drivers/scsi/init.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/init.c
+@@ -0,0 +1 @@
++#include "src/init.c"
+diff --git a/drivers/scsi/attribute_container.c b/drivers/scsi/attribute_container.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/attribute_container.c
+@@ -0,0 +1 @@
++#include "src/attribute_container.c"
+diff --git a/drivers/scsi/transport_class.c b/drivers/scsi/transport_class.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/transport_class.c
+@@ -0,0 +1 @@
++#include "src/transport_class.c"
+diff --git a/drivers/scsi/klist.c b/drivers/scsi/klist.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/klist.c
+@@ -0,0 +1 @@
++#include "src/klist.c"
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi.c
+@@ -0,0 +1 @@
++#include "src/scsi.c"
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_lib.c
+@@ -0,0 +1 @@
++#include "src/scsi_lib.c"
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_scan.c
+@@ -0,0 +1 @@
++#include "src/scsi_scan.c"
+diff --git a/drivers/scsi/kref_new.c b/drivers/scsi/kref_new.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/kref_new.c
+@@ -0,0 +1 @@
++#include "src/kref_new.c"
+diff -rupN ofa_kernel-1.2/drivers/scsi/Makefile ofa_kernel-1.2-iscsi/drivers/scsi/Makefile
+--- ofa_kernel-1.2/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ ofa_kernel-1.2-iscsi/drivers/scsi/Makefile 2007-05-16 14:12:22.000000000 +0300
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o scsi.o scsi_lib.o init.o kref_new.o klist.o attribute_container.o transport_class.o
++libiscsi-y := libiscsi_f.o scsi_scan.o
diff --git a/kernel_patches/backport/2.6.9_U4/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U4/add_open_iscsi.patch
new file mode 100644
index 0000000..a339163
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/add_open_iscsi.patch
@@ -0,0 +1,270 @@
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c 2007-05-17 16:55:43.000000000 +0300
+@@ -676,7 +676,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn,
+ }
+
+ static inline void
+-partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
++partial_sg_digest_update(struct crypto_tfm *desc, struct scatterlist *sg,
+ int offset, int length)
+ {
+ struct scatterlist temp;
+@@ -684,7 +684,7 @@ partial_sg_digest_update(struct hash_des
+ memcpy(&temp, sg, sizeof(struct scatterlist));
+ temp.offset = offset;
+ temp.length = length;
+- crypto_hash_update(desc, &temp, length);
++ crypto_hash_update(&desc, &temp, length);
+ }
+
+ static void
+@@ -1774,22 +1774,18 @@ iscsi_tcp_conn_create(struct iscsi_cls_s
+ /* initial operational parameters */
+ tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+
+- tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+- CRYPTO_ALG_ASYNC);
+- tcp_conn->tx_hash.flags = 0;
+- if (IS_ERR(tcp_conn->tx_hash.tfm))
++ tcp_conn->tx_hash = crypto_alloc_tfm("crc32c", 0);
++ if (!tcp_conn->tx_hash)
+ goto free_tcp_conn;
+
+- tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+- CRYPTO_ALG_ASYNC);
+- tcp_conn->rx_hash.flags = 0;
+- if (IS_ERR(tcp_conn->rx_hash.tfm))
++ tcp_conn->rx_hash = crypto_alloc_tfm("crc32c", 0);
++ if (!tcp_conn->rx_hash)
+ goto free_tx_tfm;
+
+ return cls_conn;
+
+ free_tx_tfm:
+- crypto_free_hash(tcp_conn->tx_hash.tfm);
++ crypto_free_tfm(tcp_conn->tx_hash);
+ free_tcp_conn:
+ kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+@@ -1823,10 +1819,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_
+ iscsi_tcp_release_conn(conn);
+ iscsi_conn_teardown(cls_conn);
+
+- if (tcp_conn->tx_hash.tfm)
+- crypto_free_hash(tcp_conn->tx_hash.tfm);
+- if (tcp_conn->rx_hash.tfm)
+- crypto_free_hash(tcp_conn->rx_hash.tfm);
++ if (tcp_conn->tx_hash)
++ crypto_free_tfm(tcp_conn->tx_hash);
++ if (tcp_conn->rx_hash)
++ crypto_free_tfm(tcp_conn->rx_hash);
+
+ kfree(tcp_conn);
+ }
+@@ -2017,7 +2013,7 @@ iscsi_tcp_conn_get_param(struct iscsi_cl
+ {
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+- struct inet_sock *inet;
++ struct inet_opt *inet;
+ struct ipv6_pinfo *np;
+ struct sock *sk;
+ int len;
+@@ -2135,7 +2131,6 @@ static void iscsi_tcp_session_destroy(st
+ static struct scsi_host_template iscsi_sht = {
+ .name = "iSCSI Initiator over TCP/IP",
+ .queuecommand = iscsi_queuecommand,
+- .change_queue_depth = iscsi_change_queue_depth,
+ .can_queue = ISCSI_XMIT_CMDS_MAX - 1,
+ .sg_tablesize = ISCSI_SG_TABLESIZE,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.h linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h 2007-05-17 16:38:14.000000000 +0300
+@@ -49,7 +49,6 @@
+ #define ISCSI_SG_TABLESIZE SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN 16
+
+-struct crypto_hash;
+ struct socket;
+
+ /* Socket connection recieve helper */
+@@ -93,8 +92,8 @@ struct iscsi_tcp_conn {
+ void (*old_write_space)(struct sock *);
+
+ /* data and header digests */
+- struct hash_desc tx_hash; /* CRC32C (Tx) */
+- struct hash_desc rx_hash; /* CRC32C (Rx) */
++ struct crypto_tfm *tx_hash; /* CRC32C (Tx) */
++ struct crypto_tfm *rx_hash; /* CRC32C (Rx) */
+
+ /* MIB custom statistics */
+ uint32_t sendpage_failures_cnt;
+diff -rup linux-2.6.20/drivers/scsi/libiscsi.c linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c
+--- linux-2.6.20/drivers/scsi/libiscsi.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c 2007-05-17 16:38:14.000000000 +0300
+@@ -1370,7 +1370,6 @@ iscsi_session_setup(struct iscsi_transpo
+ shost->max_lun = iscsit->max_lun;
+ shost->max_cmd_len = iscsit->max_cmd_len;
+ shost->transportt = scsit;
+- shost->transportt->create_work_queue = 1;
+ *hostno = shost->host_no;
+
+ session = iscsi_hostdata(shost->hostdata);
+diff -rup linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c 2007-05-17 16:38:14.000000000 +0300
+@@ -65,6 +65,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
+ #define cdev_to_iscsi_internal(_cdev) \
+ container_of(_cdev, struct iscsi_internal, cdev)
+
++extern int attribute_container_init(void);
++
+ static void iscsi_transport_release(struct class_device *cdev)
+ {
+ struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+@@ -80,6 +82,17 @@ static struct class iscsi_transport_clas
+ .release = iscsi_transport_release,
+ };
+
++static void iscsi_host_class_release(struct class_device *class_dev)
++{
++ struct Scsi_Host *shost = transport_class_to_shost(class_dev);
++ put_device(&shost->shost_gendev);
++}
++
++struct class iscsi_host_class = {
++ .name = "iscsi_host",
++ .release = iscsi_host_class_release,
++};
++
+ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+@@ -115,10 +128,8 @@ static struct attribute_group iscsi_tran
+ .attrs = iscsi_transport_attrs,
+ };
+
+-static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++static int iscsi_setup_host(struct Scsi_Host *shost)
+ {
+- struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_host *ihost = shost->shost_data;
+
+ memset(ihost, 0, sizeof(*ihost));
+@@ -127,12 +138,6 @@ static int iscsi_setup_host(struct trans
+ return 0;
+ }
+
+-static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+- "iscsi_host",
+- iscsi_setup_host,
+- NULL,
+- NULL);
+-
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ "iscsi_session",
+ NULL,
+@@ -216,24 +221,6 @@ static int iscsi_is_session_dev(const st
+ return dev->release == iscsi_session_release;
+ }
+
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+- uint id, uint lun)
+-{
+- struct iscsi_host *ihost = shost->shost_data;
+- struct iscsi_cls_session *session;
+-
+- mutex_lock(&ihost->mutex);
+- list_for_each_entry(session, &ihost->sessions, host_list) {
+- if ((channel == SCAN_WILD_CARD || channel == 0) &&
+- (id == SCAN_WILD_CARD || id == session->target_id))
+- scsi_scan_target(&session->dev, 0,
+- session->target_id, lun, 1);
+- }
+- mutex_unlock(&ihost->mutex);
+-
+- return 0;
+-}
+-
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ struct iscsi_cls_session *session =
+@@ -362,8 +349,6 @@ void iscsi_remove_session(struct iscsi_c
+ list_del(&session->host_list);
+ mutex_unlock(&ihost->mutex);
+
+- scsi_remove_target(&session->dev);
+-
+ transport_unregister_device(&session->dev);
+ device_del(&session->dev);
+ }
+@@ -1269,24 +1254,6 @@ static int iscsi_conn_match(struct attri
+ return &priv->conn_cont.ac == cont;
+ }
+
+-static int iscsi_host_match(struct attribute_container *cont,
+- struct device *dev)
+-{
+- struct Scsi_Host *shost;
+- struct iscsi_internal *priv;
+-
+- if (!scsi_is_host_device(dev))
+- return 0;
+-
+- shost = dev_to_shost(dev);
+- if (!shost->transportt ||
+- shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+- return 0;
+-
+- priv = to_iscsi_internal(shost->transportt);
+- return &priv->t.host_attrs.ac == cont;
+-}
+-
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1306,7 +1273,6 @@ iscsi_register_transport(struct iscsi_tr
+ INIT_LIST_HEAD(&priv->list);
+ priv->daemon_pid = -1;
+ priv->iscsi_transport = tt;
+- priv->t.user_scan = iscsi_user_scan;
+
+ priv->cdev.class = &iscsi_transport_class;
+ snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1319,12 +1285,11 @@ iscsi_register_transport(struct iscsi_tr
+ goto unregister_cdev;
+
+ /* host parameters */
+- priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+- priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+- priv->t.host_attrs.ac.match = iscsi_host_match;
++
++ priv->t.host_attrs = &priv->host_attrs[0];
++ priv->t.host_class = &iscsi_host_class;
++ priv->t.host_setup = iscsi_setup_host;
+ priv->t.host_size = sizeof(struct iscsi_host);
+- priv->host_attrs[0] = NULL;
+- transport_container_register(&priv->t.host_attrs);
+
+ /* connection parameters */
+ priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+@@ -1402,7 +1367,6 @@ int iscsi_unregister_transport(struct is
+
+ transport_container_unregister(&priv->conn_cont);
+ transport_container_unregister(&priv->session_cont);
+- transport_container_unregister(&priv->t.host_attrs);
+
+ sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ class_device_unregister(&priv->cdev);
+@@ -1419,6 +1383,8 @@ static __init int iscsi_transport_init(v
+ printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ ISCSI_TRANSPORT_VERSION);
+
++ attribute_container_init();
++
+ err = class_register(&iscsi_transport_class);
+ if (err)
+ return err;
diff --git a/kernel_patches/backport/2.6.9_U4/add_open_iscsi_h.patch b/kernel_patches/backport/2.6.9_U4/add_open_iscsi_h.patch
new file mode 100644
index 0000000..21715fd
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/add_open_iscsi_h.patch
@@ -0,0 +1,35 @@
+diff -rup linux-2.6.20/include/scsi/iscsi_if.h linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h
+--- linux-2.6.20/include/scsi/iscsi_if.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h 2007-05-15 08:49:53.000000000 +0300
+@@ -277,7 +277,6 @@ enum iscsi_param {
+ * These flags describes reason of stop_conn() call
+ */
+ #define STOP_CONN_TERM 0x1
+-#define STOP_CONN_SUSPEND 0x2
+ #define STOP_CONN_RECOVER 0x3
+
+ #define ISCSI_STATS_CUSTOM_MAX 32
+diff -rup linux-2.6.20/include/scsi/libiscsi.h linux-2.6.20-rh4-backport/include/scsi/libiscsi.h
+--- linux-2.6.20/include/scsi/libiscsi.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/libiscsi.h 2007-05-15 08:54:49.000000000 +0300
+@@ -25,8 +25,6 @@
+
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+-#include <linux/timer.h>
+-#include <linux/workqueue.h>
+ #include <scsi/iscsi_proto.h>
+ #include <scsi/iscsi_if.h>
+
+diff -rup linux-2.6.20/include/scsi/scsi_transport_iscsi.h linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.20/include/scsi/scsi_transport_iscsi.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h 2007-05-15 08:54:24.000000000 +0300
+@@ -24,7 +24,7 @@
+ #define SCSI_TRANSPORT_ISCSI_H
+
+ #include <linux/device.h>
+-#include <scsi/iscsi_if.h>
++#include "iscsi_if.h"
+
+ struct scsi_transport_template;
+ struct iscsi_transport;
diff --git a/kernel_patches/backport/2.6.9_U4/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U4/fix_inclusion_order_iscsi_iser.patch
new file mode 100644
index 0000000..3c2a969
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/fix_inclusion_order_iscsi_iser.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:13:43.000000000 +0200
++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:14:31.000000000 +0200
+@@ -70,9 +70,8 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+-#include <scsi/scsi_transport_iscsi.h>
+-
+ #include "iscsi_iser.h"
++#include <scsi/scsi_transport_iscsi.h>
+
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
diff --git a/kernel_patches/backport/2.6.9_U4/iscsi_scsi_addons.patch b/kernel_patches/backport/2.6.9_U4/iscsi_scsi_addons.patch
new file mode 100644
index 0000000..ffa0598
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/iscsi_scsi_addons.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/scsi/init.c b/drivers/scsi/init.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/init.c
+@@ -0,0 +1 @@
++#include "src/init.c"
+diff --git a/drivers/scsi/attribute_container.c b/drivers/scsi/attribute_container.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/attribute_container.c
+@@ -0,0 +1 @@
++#include "src/attribute_container.c"
+diff --git a/drivers/scsi/transport_class.c b/drivers/scsi/transport_class.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/transport_class.c
+@@ -0,0 +1 @@
++#include "src/transport_class.c"
+diff --git a/drivers/scsi/klist.c b/drivers/scsi/klist.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/klist.c
+@@ -0,0 +1 @@
++#include "src/klist.c"
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi.c
+@@ -0,0 +1 @@
++#include "src/scsi.c"
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_lib.c
+@@ -0,0 +1 @@
++#include "src/scsi_lib.c"
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_scan.c
+@@ -0,0 +1 @@
++#include "src/scsi_scan.c"
+diff --git a/drivers/scsi/kref_new.c b/drivers/scsi/kref_new.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/kref_new.c
+@@ -0,0 +1 @@
++#include "src/kref_new.c"
+diff -rupN ofa_kernel-1.2/drivers/scsi/Makefile ofa_kernel-1.2-iscsi/drivers/scsi/Makefile
+--- ofa_kernel-1.2/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ ofa_kernel-1.2-iscsi/drivers/scsi/Makefile 2007-05-16 14:12:22.000000000 +0300
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o scsi.o scsi_lib.o init.o kref_new.o klist.o attribute_container.o transport_class.o
++libiscsi-y := libiscsi_f.o scsi_scan.o
diff --git a/kernel_patches/backport/2.6.9_U5/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U5/add_open_iscsi.patch
new file mode 100644
index 0000000..a339163
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/add_open_iscsi.patch
@@ -0,0 +1,270 @@
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c 2007-05-17 16:55:43.000000000 +0300
+@@ -676,7 +676,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn,
+ }
+
+ static inline void
+-partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
++partial_sg_digest_update(struct crypto_tfm *desc, struct scatterlist *sg,
+ int offset, int length)
+ {
+ struct scatterlist temp;
+@@ -684,7 +684,7 @@ partial_sg_digest_update(struct hash_des
+ memcpy(&temp, sg, sizeof(struct scatterlist));
+ temp.offset = offset;
+ temp.length = length;
+- crypto_hash_update(desc, &temp, length);
++ crypto_hash_update(&desc, &temp, length);
+ }
+
+ static void
+@@ -1774,22 +1774,18 @@ iscsi_tcp_conn_create(struct iscsi_cls_s
+ /* initial operational parameters */
+ tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+
+- tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+- CRYPTO_ALG_ASYNC);
+- tcp_conn->tx_hash.flags = 0;
+- if (IS_ERR(tcp_conn->tx_hash.tfm))
++ tcp_conn->tx_hash = crypto_alloc_tfm("crc32c", 0);
++ if (!tcp_conn->tx_hash)
+ goto free_tcp_conn;
+
+- tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+- CRYPTO_ALG_ASYNC);
+- tcp_conn->rx_hash.flags = 0;
+- if (IS_ERR(tcp_conn->rx_hash.tfm))
++ tcp_conn->rx_hash = crypto_alloc_tfm("crc32c", 0);
++ if (!tcp_conn->rx_hash)
+ goto free_tx_tfm;
+
+ return cls_conn;
+
+ free_tx_tfm:
+- crypto_free_hash(tcp_conn->tx_hash.tfm);
++ crypto_free_tfm(tcp_conn->tx_hash);
+ free_tcp_conn:
+ kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+@@ -1823,10 +1819,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_
+ iscsi_tcp_release_conn(conn);
+ iscsi_conn_teardown(cls_conn);
+
+- if (tcp_conn->tx_hash.tfm)
+- crypto_free_hash(tcp_conn->tx_hash.tfm);
+- if (tcp_conn->rx_hash.tfm)
+- crypto_free_hash(tcp_conn->rx_hash.tfm);
++ if (tcp_conn->tx_hash)
++ crypto_free_tfm(tcp_conn->tx_hash);
++ if (tcp_conn->rx_hash)
++ crypto_free_tfm(tcp_conn->rx_hash);
+
+ kfree(tcp_conn);
+ }
+@@ -2017,7 +2013,7 @@ iscsi_tcp_conn_get_param(struct iscsi_cl
+ {
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+- struct inet_sock *inet;
++ struct inet_opt *inet;
+ struct ipv6_pinfo *np;
+ struct sock *sk;
+ int len;
+@@ -2135,7 +2131,6 @@ static void iscsi_tcp_session_destroy(st
+ static struct scsi_host_template iscsi_sht = {
+ .name = "iSCSI Initiator over TCP/IP",
+ .queuecommand = iscsi_queuecommand,
+- .change_queue_depth = iscsi_change_queue_depth,
+ .can_queue = ISCSI_XMIT_CMDS_MAX - 1,
+ .sg_tablesize = ISCSI_SG_TABLESIZE,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.h linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h 2007-05-17 16:38:14.000000000 +0300
+@@ -49,7 +49,6 @@
+ #define ISCSI_SG_TABLESIZE SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN 16
+
+-struct crypto_hash;
+ struct socket;
+
+ /* Socket connection recieve helper */
+@@ -93,8 +92,8 @@ struct iscsi_tcp_conn {
+ void (*old_write_space)(struct sock *);
+
+ /* data and header digests */
+- struct hash_desc tx_hash; /* CRC32C (Tx) */
+- struct hash_desc rx_hash; /* CRC32C (Rx) */
++ struct crypto_tfm *tx_hash; /* CRC32C (Tx) */
++ struct crypto_tfm *rx_hash; /* CRC32C (Rx) */
+
+ /* MIB custom statistics */
+ uint32_t sendpage_failures_cnt;
+diff -rup linux-2.6.20/drivers/scsi/libiscsi.c linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c
+--- linux-2.6.20/drivers/scsi/libiscsi.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c 2007-05-17 16:38:14.000000000 +0300
+@@ -1370,7 +1370,6 @@ iscsi_session_setup(struct iscsi_transpo
+ shost->max_lun = iscsit->max_lun;
+ shost->max_cmd_len = iscsit->max_cmd_len;
+ shost->transportt = scsit;
+- shost->transportt->create_work_queue = 1;
+ *hostno = shost->host_no;
+
+ session = iscsi_hostdata(shost->hostdata);
+diff -rup linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c 2007-05-17 16:38:14.000000000 +0300
+@@ -65,6 +65,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
+ #define cdev_to_iscsi_internal(_cdev) \
+ container_of(_cdev, struct iscsi_internal, cdev)
+
++extern int attribute_container_init(void);
++
+ static void iscsi_transport_release(struct class_device *cdev)
+ {
+ struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+@@ -80,6 +82,17 @@ static struct class iscsi_transport_clas
+ .release = iscsi_transport_release,
+ };
+
++static void iscsi_host_class_release(struct class_device *class_dev)
++{
++ struct Scsi_Host *shost = transport_class_to_shost(class_dev);
++ put_device(&shost->shost_gendev);
++}
++
++struct class iscsi_host_class = {
++ .name = "iscsi_host",
++ .release = iscsi_host_class_release,
++};
++
+ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+@@ -115,10 +128,8 @@ static struct attribute_group iscsi_tran
+ .attrs = iscsi_transport_attrs,
+ };
+
+-static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++static int iscsi_setup_host(struct Scsi_Host *shost)
+ {
+- struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_host *ihost = shost->shost_data;
+
+ memset(ihost, 0, sizeof(*ihost));
+@@ -127,12 +138,6 @@ static int iscsi_setup_host(struct trans
+ return 0;
+ }
+
+-static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+- "iscsi_host",
+- iscsi_setup_host,
+- NULL,
+- NULL);
+-
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ "iscsi_session",
+ NULL,
+@@ -216,24 +221,6 @@ static int iscsi_is_session_dev(const st
+ return dev->release == iscsi_session_release;
+ }
+
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+- uint id, uint lun)
+-{
+- struct iscsi_host *ihost = shost->shost_data;
+- struct iscsi_cls_session *session;
+-
+- mutex_lock(&ihost->mutex);
+- list_for_each_entry(session, &ihost->sessions, host_list) {
+- if ((channel == SCAN_WILD_CARD || channel == 0) &&
+- (id == SCAN_WILD_CARD || id == session->target_id))
+- scsi_scan_target(&session->dev, 0,
+- session->target_id, lun, 1);
+- }
+- mutex_unlock(&ihost->mutex);
+-
+- return 0;
+-}
+-
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ struct iscsi_cls_session *session =
+@@ -362,8 +349,6 @@ void iscsi_remove_session(struct iscsi_c
+ list_del(&session->host_list);
+ mutex_unlock(&ihost->mutex);
+
+- scsi_remove_target(&session->dev);
+-
+ transport_unregister_device(&session->dev);
+ device_del(&session->dev);
+ }
+@@ -1269,24 +1254,6 @@ static int iscsi_conn_match(struct attri
+ return &priv->conn_cont.ac == cont;
+ }
+
+-static int iscsi_host_match(struct attribute_container *cont,
+- struct device *dev)
+-{
+- struct Scsi_Host *shost;
+- struct iscsi_internal *priv;
+-
+- if (!scsi_is_host_device(dev))
+- return 0;
+-
+- shost = dev_to_shost(dev);
+- if (!shost->transportt ||
+- shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+- return 0;
+-
+- priv = to_iscsi_internal(shost->transportt);
+- return &priv->t.host_attrs.ac == cont;
+-}
+-
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1306,7 +1273,6 @@ iscsi_register_transport(struct iscsi_tr
+ INIT_LIST_HEAD(&priv->list);
+ priv->daemon_pid = -1;
+ priv->iscsi_transport = tt;
+- priv->t.user_scan = iscsi_user_scan;
+
+ priv->cdev.class = &iscsi_transport_class;
+ snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1319,12 +1285,11 @@ iscsi_register_transport(struct iscsi_tr
+ goto unregister_cdev;
+
+ /* host parameters */
+- priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+- priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+- priv->t.host_attrs.ac.match = iscsi_host_match;
++
++ priv->t.host_attrs = &priv->host_attrs[0];
++ priv->t.host_class = &iscsi_host_class;
++ priv->t.host_setup = iscsi_setup_host;
+ priv->t.host_size = sizeof(struct iscsi_host);
+- priv->host_attrs[0] = NULL;
+- transport_container_register(&priv->t.host_attrs);
+
+ /* connection parameters */
+ priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+@@ -1402,7 +1367,6 @@ int iscsi_unregister_transport(struct is
+
+ transport_container_unregister(&priv->conn_cont);
+ transport_container_unregister(&priv->session_cont);
+- transport_container_unregister(&priv->t.host_attrs);
+
+ sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ class_device_unregister(&priv->cdev);
+@@ -1419,6 +1383,8 @@ static __init int iscsi_transport_init(v
+ printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ ISCSI_TRANSPORT_VERSION);
+
++ attribute_container_init();
++
+ err = class_register(&iscsi_transport_class);
+ if (err)
+ return err;
diff --git a/kernel_patches/backport/2.6.9_U5/add_open_iscsi_h.patch b/kernel_patches/backport/2.6.9_U5/add_open_iscsi_h.patch
new file mode 100644
index 0000000..21715fd
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/add_open_iscsi_h.patch
@@ -0,0 +1,35 @@
+diff -rup linux-2.6.20/include/scsi/iscsi_if.h linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h
+--- linux-2.6.20/include/scsi/iscsi_if.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h 2007-05-15 08:49:53.000000000 +0300
+@@ -277,7 +277,6 @@ enum iscsi_param {
+ * These flags describes reason of stop_conn() call
+ */
+ #define STOP_CONN_TERM 0x1
+-#define STOP_CONN_SUSPEND 0x2
+ #define STOP_CONN_RECOVER 0x3
+
+ #define ISCSI_STATS_CUSTOM_MAX 32
+diff -rup linux-2.6.20/include/scsi/libiscsi.h linux-2.6.20-rh4-backport/include/scsi/libiscsi.h
+--- linux-2.6.20/include/scsi/libiscsi.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/libiscsi.h 2007-05-15 08:54:49.000000000 +0300
+@@ -25,8 +25,6 @@
+
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+-#include <linux/timer.h>
+-#include <linux/workqueue.h>
+ #include <scsi/iscsi_proto.h>
+ #include <scsi/iscsi_if.h>
+
+diff -rup linux-2.6.20/include/scsi/scsi_transport_iscsi.h linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.20/include/scsi/scsi_transport_iscsi.h 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h 2007-05-15 08:54:24.000000000 +0300
+@@ -24,7 +24,7 @@
+ #define SCSI_TRANSPORT_ISCSI_H
+
+ #include <linux/device.h>
+-#include <scsi/iscsi_if.h>
++#include "iscsi_if.h"
+
+ struct scsi_transport_template;
+ struct iscsi_transport;
diff --git a/kernel_patches/backport/2.6.9_U5/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U5/fix_inclusion_order_iscsi_iser.patch
new file mode 100644
index 0000000..3c2a969
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/fix_inclusion_order_iscsi_iser.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:13:43.000000000 +0200
++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-02-08 09:14:31.000000000 +0200
+@@ -70,9 +70,8 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+-#include <scsi/scsi_transport_iscsi.h>
+-
+ #include "iscsi_iser.h"
++#include <scsi/scsi_transport_iscsi.h>
+
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
diff --git a/kernel_patches/backport/2.6.9_U5/iscsi_scsi_addons.patch b/kernel_patches/backport/2.6.9_U5/iscsi_scsi_addons.patch
new file mode 100644
index 0000000..ffa0598
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/iscsi_scsi_addons.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/scsi/init.c b/drivers/scsi/init.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/init.c
+@@ -0,0 +1 @@
++#include "src/init.c"
+diff --git a/drivers/scsi/attribute_container.c b/drivers/scsi/attribute_container.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/attribute_container.c
+@@ -0,0 +1 @@
++#include "src/attribute_container.c"
+diff --git a/drivers/scsi/transport_class.c b/drivers/scsi/transport_class.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/transport_class.c
+@@ -0,0 +1 @@
++#include "src/transport_class.c"
+diff --git a/drivers/scsi/klist.c b/drivers/scsi/klist.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/klist.c
+@@ -0,0 +1 @@
++#include "src/klist.c"
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi.c
+@@ -0,0 +1 @@
++#include "src/scsi.c"
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_lib.c
+@@ -0,0 +1 @@
++#include "src/scsi_lib.c"
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_scan.c
+@@ -0,0 +1 @@
++#include "src/scsi_scan.c"
+diff --git a/drivers/scsi/kref_new.c b/drivers/scsi/kref_new.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/kref_new.c
+@@ -0,0 +1 @@
++#include "src/kref_new.c"
+diff -rupN ofa_kernel-1.2/drivers/scsi/Makefile ofa_kernel-1.2-iscsi/drivers/scsi/Makefile
+--- ofa_kernel-1.2/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ ofa_kernel-1.2-iscsi/drivers/scsi/Makefile 2007-05-16 14:12:22.000000000 +0300
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o scsi.o scsi_lib.o init.o kref_new.o klist.o attribute_container.o transport_class.o
++libiscsi-y := libiscsi_f.o scsi_scan.o
diff --git a/kernel_patches/fixes/iscsi_scsi_makefile.patch b/kernel_patches/fixes/iscsi_scsi_makefile.patch
deleted file mode 100644
index 9c4fd01..0000000
--- a/kernel_patches/fixes/iscsi_scsi_makefile.patch
+++ /dev/null
@@ -1,10 +0,0 @@
-Add a Makefile based on the kernel's drivers/scsi/Makefile in order to build open-iscsi.
-
-Signed-off-by: Erez Zilber <erezz at voltaire.com>
-
-diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
---- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile 2006-12-28 17:01:22.000000000 +0200
-@@ -0,0 +1,2 @@
-+obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
-+obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o
diff --git a/ofed_scripts/makefile b/ofed_scripts/makefile
index 34a8996..62abe2c 100644
--- a/ofed_scripts/makefile
+++ b/ofed_scripts/makefile
@@ -60,6 +60,12 @@ kernel:
@echo "Kernel version: $(KVERSION)"
@echo "Modules directory: $(DESTDIR)/$(MODULES_DIR)"
@echo "Kernel sources: $(KSRC)"
+ if [ -e $(CWD)/drivers/scsi/libiscsi.c ]; then \
+ mv $(CWD)/drivers/scsi/libiscsi.c $(CWD)/drivers/scsi/libiscsi_f.c; \
+ fi
+ if [ -e $(CWD)/drivers/scsi/scsi_transport_iscsi.c ]; then \
+ mv $(CWD)/drivers/scsi/scsi_transport_iscsi.c $(CWD)/drivers/scsi/scsi_transport_iscsi_f.c; \
+ fi
env EXTRA_CFLAGS="$(OPENIB_KERNEL_EXTRA_CFLAGS) $(KERNEL_MEMTRACK_CFLAGS) -I$(CWD)/include -I$(CWD)/drivers/infiniband/include \
-I$(CWD)/drivers/infiniband/ulp/ipoib \
-I$(CWD)/drivers/infiniband/debug \
More information about the ewg
mailing list