From: Adheer Chandravanshi <[email protected]>

This patch allows iscsiadm to manage iSCSI target information stored on
adapter flash on per host basis.

The sysfs entries will look as cited below:
    /sys/class/iscsi_flash_tgt/tgt-<host_no>-<target_no>/

Signed-off-by: Adheer Chandravanshi <[email protected]>
Signed-off-by: Vikas Chaudhary <[email protected]>
---
 drivers/scsi/scsi_transport_iscsi.c |  690 ++++++++++++++++++++++++++++++++++-
 include/scsi/iscsi_if.h             |  106 ++++++
 include/scsi/scsi_transport_iscsi.h |   35 ++
 3 files changed, 830 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index dac7f8d..028f2c3 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/bsg-lib.h>
 #include <linux/idr.h>
+#include <linux/list.h>
 #include <net/tcp.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -460,6 +461,431 @@ void iscsi_destroy_iface(struct iscsi_iface *iface)
 EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
 
 /*
+ * Interface to display flash tgt params to sysfs
+ */
+
+static void iscsi_flash_tgt_release(struct device *dev)
+{
+       struct iscsi_flash_tgt *tgt = iscsi_dev_to_flash_tgt(dev);
+       struct device *parent = tgt->dev.parent;
+
+       kfree(tgt);
+       put_device(parent);
+}
+
+
+static struct class iscsi_flash_tgt_class = {
+       .name = "iscsi_flash_tgt",
+       .dev_release = iscsi_flash_tgt_release,
+};
+
+#define ISCSI_FLASHTGT_ATTR(_prefix, _name, _mode, _show, _store)      \
+struct device_attribute dev_attr_##_prefix##_##_name =                 \
+       __ATTR(_name, _mode, _show, _store)
+
+/* flash tgt attrs show */
+#define iscsi_flash_tgt_attr_show(type, name, param)                   \
+static ssize_t                                                         \
+show_##type##_##name(struct device *dev, struct device_attribute *attr,        
\
+                    char *buf)                                         \
+{                                                                      \
+       struct iscsi_flash_tgt *tgt = iscsi_dev_to_flash_tgt(dev);      \
+       struct iscsi_transport *t = tgt->transport;                     \
+       return t->get_flash_tgt_param(tgt, param, buf);                 \
+}                                                                      \
+
+
+#define iscsi_flash_tgt_attr(type, name, param)                                
\
+       iscsi_flash_tgt_attr_show(type, name, param)                    \
+static ISCSI_FLASHTGT_ATTR(type, name, S_IRUGO,                                
\
+                           show_##type##_##name, NULL);
+
+/* Target attributes */
+
+iscsi_flash_tgt_attr(tgt, is_fw_assigned_ipv6,
+                    ISCSI_FLASHTGT_IS_FW_ASSIGNED_IPV6);
+iscsi_flash_tgt_attr(tgt, dev_type, ISCSI_FLASHTGT_DEV_TYPE);
+iscsi_flash_tgt_attr(tgt, dif, ISCSI_FLASHTGT_DIF_EN);
+iscsi_flash_tgt_attr(tgt, auto_snd_tgt_disable,
+                    ISCSI_FLASHTGT_AUTO_SND_TGT_DISABLE);
+iscsi_flash_tgt_attr(tgt, discovery_session, ISCSI_FLASHTGT_DISCOVERY_SESS);
+iscsi_flash_tgt_attr(tgt, entry_enable, ISCSI_FLASHTGT_ENTRY_EN);
+iscsi_flash_tgt_attr(tgt, dev_assoc_target, ISCSI_FLASHTGT_DEV_ASSOC_TARGET);
+iscsi_flash_tgt_attr(tgt, dev_assoc_initiator,
+                    ISCSI_FLASHTGT_DEV_ASSOC_INITIATOR);
+iscsi_flash_tgt_attr(tgt, exec_throttle, ISCSI_FLASHTGT_EXEC_THROTTLE);
+iscsi_flash_tgt_attr(tgt, exec_count, ISCSI_FLASHTGT_EXEC_COUNT);
+iscsi_flash_tgt_attr(tgt, retry_count, ISCSI_FLASHTGT_RETRY_COUNT);
+iscsi_flash_tgt_attr(tgt, retry_delay, ISCSI_FLASHTGT_RETRY_DELAY);
+iscsi_flash_tgt_attr(tgt, header_digest, ISCSI_FLASHTGT_HDR_DGST_EN);
+iscsi_flash_tgt_attr(tgt, data_digest, ISCSI_FLASHTGT_DATA_DGST_EN);
+iscsi_flash_tgt_attr(tgt, immediate_data, ISCSI_FLASHTGT_IMM_DATA_EN);
+iscsi_flash_tgt_attr(tgt, initial_r2t, ISCSI_FLASHTGT_INITIAL_R2T_EN);
+iscsi_flash_tgt_attr(tgt, data_seq_in_order, ISCSI_FLASHTGT_DATASEQ_INORDER);
+iscsi_flash_tgt_attr(tgt, data_pdu_in_order, ISCSI_FLASHTGT_PDU_INORDER);
+iscsi_flash_tgt_attr(tgt, chap_auth, ISCSI_FLASHTGT_CHAP_AUTH_EN);
+iscsi_flash_tgt_attr(tgt, snack_req, ISCSI_FLASHTGT_SNACK_REQ_EN);
+iscsi_flash_tgt_attr(tgt, discovery_logout,
+                    ISCSI_FLASHTGT_DISCOVERY_LOGOUT_EN);
+iscsi_flash_tgt_attr(tgt, bidi_chap, ISCSI_FLASHTGT_BIDI_CHAP_EN);
+iscsi_flash_tgt_attr(tgt, discovery_auth_optional,
+                    ISCSI_FLASHTGT_DISCOVERY_AUTH_OPTIONAL);
+iscsi_flash_tgt_attr(tgt, erl, ISCSI_FLASHTGT_ERL);
+iscsi_flash_tgt_attr(tgt, tcp_timestamp_stat,
+                    ISCSI_FLASHTGT_TCP_TIMESTAMP_STAT);
+iscsi_flash_tgt_attr(tgt, tcp_nagle_disable, ISCSI_FLASHTGT_TCP_NAGLE_DISABLE);
+iscsi_flash_tgt_attr(tgt, tcp_wsf_disable, ISCSI_FLASHTGT_TCP_WSF_DISABLE);
+iscsi_flash_tgt_attr(tgt, tcp_timer_scale, ISCSI_FLASHTGT_TCP_TIMER_SCALE);
+iscsi_flash_tgt_attr(tgt, tcp_timestamp_enable,
+                    ISCSI_FLASHTGT_TCP_TIMESTAMP_EN);
+iscsi_flash_tgt_attr(tgt, ip_frag_disable, ISCSI_FLASHTGT_IP_FRAG_DISABLE);
+iscsi_flash_tgt_attr(tgt, max_recv_dlength, ISCSI_FLASHTGT_MAX_RECV_DLENGTH);
+iscsi_flash_tgt_attr(tgt, max_xmit_dlength, ISCSI_FLASHTGT_MAX_XMIT_DLENGTH);
+iscsi_flash_tgt_attr(tgt, first_burst, ISCSI_FLASHTGT_FIRST_BURST);
+iscsi_flash_tgt_attr(tgt, default_time2wait, ISCSI_FLASHTGT_DEF_TIME2WAIT);
+iscsi_flash_tgt_attr(tgt, default_time2retain, ISCSI_FLASHTGT_DEF_TIME2RETAIN);
+iscsi_flash_tgt_attr(tgt, max_r2t, ISCSI_FLASHTGT_MAX_R2T);
+iscsi_flash_tgt_attr(tgt, keepalive_timeout, ISCSI_FLASHTGT_KEEPALIVE_TMO);
+iscsi_flash_tgt_attr(tgt, isid, ISCSI_FLASHTGT_ISID);
+iscsi_flash_tgt_attr(tgt, tsid, ISCSI_FLASHTGT_TSID);
+iscsi_flash_tgt_attr(tgt, port, ISCSI_FLASHTGT_PORT);
+iscsi_flash_tgt_attr(tgt, max_burst, ISCSI_FLASHTGT_MAX_BURST);
+iscsi_flash_tgt_attr(tgt, def_tmf_timeout, ISCSI_FLASHTGT_DEF_TMF_TMO);
+iscsi_flash_tgt_attr(tgt, ipaddress, ISCSI_FLASHTGT_IPADDR);
+iscsi_flash_tgt_attr(tgt, targetalias, ISCSI_FLASHTGT_ALIAS);
+iscsi_flash_tgt_attr(tgt, redirect_ipaddr, ISCSI_FLASHTGT_REDIRECT_IPADDR);
+iscsi_flash_tgt_attr(tgt, max_segment_size, ISCSI_FLASHTGT_MAX_SEGMENT_SIZE);
+iscsi_flash_tgt_attr(tgt, local_port, ISCSI_FLASHTGT_LOCAL_PORT);
+iscsi_flash_tgt_attr(tgt, ipv4_tos, ISCSI_FLASHTGT_IPV4_TOS);
+iscsi_flash_tgt_attr(tgt, ipv6_flow_label, ISCSI_FLASHTGT_IPV6_FLOW_LABEL);
+iscsi_flash_tgt_attr(tgt, name, ISCSI_FLASHTGT_NAME);
+iscsi_flash_tgt_attr(tgt, tpgt, ISCSI_FLASHTGT_TPGT);
+iscsi_flash_tgt_attr(tgt, link_local_ipv6, ISCSI_FLASHTGT_LINK_LOCAL_IPV6);
+iscsi_flash_tgt_attr(tgt, discovery_parent, ISCSI_FLASHTGT_DISCOVERY_PARENT);
+iscsi_flash_tgt_attr(tgt, tcp_xmit_wsf, ISCSI_FLASHTGT_TCP_XMIT_WSF);
+iscsi_flash_tgt_attr(tgt, tcp_recv_wsf, ISCSI_FLASHTGT_TCP_RECV_WSF);
+iscsi_flash_tgt_attr(tgt, username, ISCSI_FLASHTGT_USERNAME);
+iscsi_flash_tgt_attr(tgt, password, ISCSI_FLASHTGT_PASSWORD);
+iscsi_flash_tgt_attr(tgt, statsn, ISCSI_FLASHTGT_STATSN);
+iscsi_flash_tgt_attr(tgt, exp_statsn, ISCSI_FLASHTGT_EXP_STATSN);
+
+static umode_t iscsi_flash_tgt_attr_is_visible(struct kobject *kobj,
+                                         struct attribute *attr, int i)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct iscsi_flash_tgt *tgt = iscsi_dev_to_flash_tgt(dev);
+       struct iscsi_transport *t = tgt->transport;
+       int param;
+
+       if (attr == &dev_attr_tgt_is_fw_assigned_ipv6.attr) {
+               param = ISCSI_FLASHTGT_IS_FW_ASSIGNED_IPV6;
+       } else if (attr == &dev_attr_tgt_dev_type.attr) {
+               param = ISCSI_FLASHTGT_DEV_TYPE;
+       } else if (attr == &dev_attr_tgt_dif.attr) {
+               param = ISCSI_FLASHTGT_DIF_EN;
+       } else if (attr == &dev_attr_tgt_auto_snd_tgt_disable.attr) {
+               param = ISCSI_FLASHTGT_AUTO_SND_TGT_DISABLE;
+       } else if (attr == &dev_attr_tgt_discovery_session.attr) {
+               param = ISCSI_FLASHTGT_DISCOVERY_SESS;
+       } else if (attr == &dev_attr_tgt_entry_enable.attr) {
+               param = ISCSI_FLASHTGT_ENTRY_EN;
+       } else if (attr == &dev_attr_tgt_dev_assoc_target.attr) {
+               param = ISCSI_FLASHTGT_DEV_ASSOC_TARGET;
+       } else if (attr == &dev_attr_tgt_dev_assoc_initiator.attr) {
+               param = ISCSI_FLASHTGT_DEV_ASSOC_INITIATOR;
+       } else if (attr == &dev_attr_tgt_exec_throttle.attr) {
+               param = ISCSI_FLASHTGT_EXEC_THROTTLE;
+       } else if (attr == &dev_attr_tgt_exec_count.attr) {
+               param = ISCSI_FLASHTGT_EXEC_COUNT;
+       } else if (attr == &dev_attr_tgt_retry_count.attr) {
+               param = ISCSI_FLASHTGT_RETRY_COUNT;
+       } else if (attr == &dev_attr_tgt_retry_delay.attr) {
+               param = ISCSI_FLASHTGT_RETRY_DELAY;
+       } else if (attr == &dev_attr_tgt_header_digest.attr) {
+               param = ISCSI_FLASHTGT_HDR_DGST_EN;
+       } else if (attr == &dev_attr_tgt_data_digest.attr) {
+               param = ISCSI_FLASHTGT_DATA_DGST_EN;
+       } else if (attr == &dev_attr_tgt_immediate_data.attr) {
+               param = ISCSI_FLASHTGT_IMM_DATA_EN;
+       } else if (attr == &dev_attr_tgt_initial_r2t.attr) {
+               param = ISCSI_FLASHTGT_INITIAL_R2T_EN;
+       } else if (attr == &dev_attr_tgt_data_seq_in_order.attr) {
+               param = ISCSI_FLASHTGT_DATASEQ_INORDER;
+       } else if (attr == &dev_attr_tgt_data_pdu_in_order.attr) {
+               param = ISCSI_FLASHTGT_PDU_INORDER;
+       } else if (attr == &dev_attr_tgt_chap_auth.attr) {
+               param = ISCSI_FLASHTGT_CHAP_AUTH_EN;
+       } else if (attr == &dev_attr_tgt_snack_req.attr) {
+               param = ISCSI_FLASHTGT_SNACK_REQ_EN;
+       } else if (attr == &dev_attr_tgt_discovery_logout.attr) {
+               param = ISCSI_FLASHTGT_DISCOVERY_LOGOUT_EN;
+       } else if (attr == &dev_attr_tgt_bidi_chap.attr) {
+               param = ISCSI_FLASHTGT_BIDI_CHAP_EN;
+       } else if (attr == &dev_attr_tgt_discovery_auth_optional.attr) {
+               param = ISCSI_FLASHTGT_DISCOVERY_AUTH_OPTIONAL;
+       } else if (attr == &dev_attr_tgt_erl.attr) {
+               param = ISCSI_FLASHTGT_ERL;
+       } else if (attr == &dev_attr_tgt_tcp_timestamp_stat.attr) {
+               param = ISCSI_FLASHTGT_TCP_TIMESTAMP_STAT;
+       } else if (attr == &dev_attr_tgt_tcp_nagle_disable.attr) {
+               param = ISCSI_FLASHTGT_TCP_NAGLE_DISABLE;
+       } else if (attr == &dev_attr_tgt_tcp_wsf_disable.attr) {
+               param = ISCSI_FLASHTGT_TCP_WSF_DISABLE;
+       } else if (attr == &dev_attr_tgt_tcp_timer_scale.attr) {
+               param = ISCSI_FLASHTGT_TCP_TIMER_SCALE;
+       } else if (attr == &dev_attr_tgt_tcp_timestamp_enable.attr) {
+               param = ISCSI_FLASHTGT_TCP_TIMESTAMP_EN;
+       } else if (attr == &dev_attr_tgt_ip_frag_disable.attr) {
+               param = ISCSI_FLASHTGT_IP_FRAG_DISABLE;
+       } else if (attr == &dev_attr_tgt_max_recv_dlength.attr) {
+               param = ISCSI_FLASHTGT_MAX_RECV_DLENGTH;
+       } else if (attr == &dev_attr_tgt_max_xmit_dlength.attr) {
+               param = ISCSI_FLASHTGT_MAX_XMIT_DLENGTH;
+       } else if (attr == &dev_attr_tgt_first_burst.attr) {
+               param = ISCSI_FLASHTGT_FIRST_BURST;
+       } else if (attr == &dev_attr_tgt_default_time2wait.attr) {
+               param = ISCSI_FLASHTGT_DEF_TIME2WAIT;
+       } else if (attr == &dev_attr_tgt_default_time2retain.attr) {
+               param = ISCSI_FLASHTGT_DEF_TIME2RETAIN;
+       } else if (attr == &dev_attr_tgt_max_r2t.attr) {
+               param = ISCSI_FLASHTGT_MAX_R2T;
+       } else if (attr == &dev_attr_tgt_keepalive_timeout.attr) {
+               param = ISCSI_FLASHTGT_KEEPALIVE_TMO;
+       } else if (attr == &dev_attr_tgt_isid.attr) {
+               param = ISCSI_FLASHTGT_ISID;
+       } else if (attr == &dev_attr_tgt_tsid.attr) {
+               param = ISCSI_FLASHTGT_TSID;
+       } else if (attr == &dev_attr_tgt_port.attr) {
+               param = ISCSI_FLASHTGT_PORT;
+       } else if (attr == &dev_attr_tgt_max_burst.attr) {
+               param = ISCSI_FLASHTGT_MAX_BURST;
+       } else if (attr == &dev_attr_tgt_def_tmf_timeout.attr) {
+               param = ISCSI_FLASHTGT_DEF_TMF_TMO;
+       } else if (attr == &dev_attr_tgt_ipaddress.attr) {
+               param = ISCSI_FLASHTGT_IPADDR;
+       } else if (attr == &dev_attr_tgt_targetalias.attr) {
+               param = ISCSI_FLASHTGT_ALIAS;
+       } else if (attr == &dev_attr_tgt_redirect_ipaddr.attr) {
+               param = ISCSI_FLASHTGT_REDIRECT_IPADDR;
+       } else if (attr == &dev_attr_tgt_max_segment_size.attr) {
+               param = ISCSI_FLASHTGT_MAX_SEGMENT_SIZE;
+       } else if (attr == &dev_attr_tgt_local_port.attr) {
+               param = ISCSI_FLASHTGT_LOCAL_PORT;
+       } else if (attr == &dev_attr_tgt_ipv4_tos.attr) {
+               param = ISCSI_FLASHTGT_IPV4_TOS;
+       } else if (attr == &dev_attr_tgt_ipv6_flow_label.attr) {
+               param = ISCSI_FLASHTGT_IPV6_FLOW_LABEL;
+       } else if (attr == &dev_attr_tgt_name.attr) {
+               param = ISCSI_FLASHTGT_NAME;
+       } else if (attr == &dev_attr_tgt_tpgt.attr) {
+               param = ISCSI_FLASHTGT_TPGT;
+       } else if (attr == &dev_attr_tgt_link_local_ipv6.attr) {
+               param = ISCSI_FLASHTGT_LINK_LOCAL_IPV6;
+       } else if (attr == &dev_attr_tgt_discovery_parent.attr) {
+               param = ISCSI_FLASHTGT_DISCOVERY_PARENT;
+       } else if (attr == &dev_attr_tgt_tcp_xmit_wsf.attr) {
+               param = ISCSI_FLASHTGT_TCP_XMIT_WSF;
+       } else if (attr == &dev_attr_tgt_tcp_recv_wsf.attr) {
+               param = ISCSI_FLASHTGT_TCP_RECV_WSF;
+       } else if (attr == &dev_attr_tgt_username.attr) {
+               param = ISCSI_FLASHTGT_USERNAME;
+       } else if (attr == &dev_attr_tgt_password.attr) {
+               param = ISCSI_FLASHTGT_PASSWORD;
+       } else if (attr == &dev_attr_tgt_statsn.attr) {
+               param = ISCSI_FLASHTGT_STATSN;
+       } else if (attr == &dev_attr_tgt_exp_statsn.attr) {
+               param = ISCSI_FLASHTGT_EXP_STATSN;
+       } else {
+               WARN_ONCE(1, "Invalid flash tgt attr");
+               return 0;
+       }
+
+       return t->attr_is_visible(ISCSI_FLASHTGT_PARAM, param);
+}
+
+static struct attribute *iscsi_flash_tgt_attrs[] = {
+       &dev_attr_tgt_is_fw_assigned_ipv6.attr,
+       &dev_attr_tgt_dev_type.attr,
+       &dev_attr_tgt_dif.attr,
+       &dev_attr_tgt_auto_snd_tgt_disable.attr,
+       &dev_attr_tgt_discovery_session.attr,
+       &dev_attr_tgt_entry_enable.attr,
+       &dev_attr_tgt_dev_assoc_target.attr,
+       &dev_attr_tgt_dev_assoc_initiator.attr,
+       &dev_attr_tgt_exec_throttle.attr,
+       &dev_attr_tgt_exec_count.attr,
+       &dev_attr_tgt_retry_count.attr,
+       &dev_attr_tgt_retry_delay.attr,
+       &dev_attr_tgt_header_digest.attr,
+       &dev_attr_tgt_data_digest.attr,
+       &dev_attr_tgt_immediate_data.attr,
+       &dev_attr_tgt_initial_r2t.attr,
+       &dev_attr_tgt_data_seq_in_order.attr,
+       &dev_attr_tgt_data_pdu_in_order.attr,
+       &dev_attr_tgt_chap_auth.attr,
+       &dev_attr_tgt_snack_req.attr,
+       &dev_attr_tgt_discovery_logout.attr,
+       &dev_attr_tgt_bidi_chap.attr,
+       &dev_attr_tgt_discovery_auth_optional.attr,
+       &dev_attr_tgt_erl.attr,
+       &dev_attr_tgt_tcp_timestamp_stat.attr,
+       &dev_attr_tgt_tcp_nagle_disable.attr,
+       &dev_attr_tgt_tcp_wsf_disable.attr,
+       &dev_attr_tgt_tcp_timer_scale.attr,
+       &dev_attr_tgt_tcp_timestamp_enable.attr,
+       &dev_attr_tgt_ip_frag_disable.attr,
+       &dev_attr_tgt_max_recv_dlength.attr,
+       &dev_attr_tgt_max_xmit_dlength.attr,
+       &dev_attr_tgt_first_burst.attr,
+       &dev_attr_tgt_default_time2wait.attr,
+       &dev_attr_tgt_default_time2retain.attr,
+       &dev_attr_tgt_max_r2t.attr,
+       &dev_attr_tgt_keepalive_timeout.attr,
+       &dev_attr_tgt_isid.attr,
+       &dev_attr_tgt_tsid.attr,
+       &dev_attr_tgt_port.attr,
+       &dev_attr_tgt_max_burst.attr,
+       &dev_attr_tgt_def_tmf_timeout.attr,
+       &dev_attr_tgt_ipaddress.attr,
+       &dev_attr_tgt_targetalias.attr,
+       &dev_attr_tgt_redirect_ipaddr.attr,
+       &dev_attr_tgt_max_segment_size.attr,
+       &dev_attr_tgt_local_port.attr,
+       &dev_attr_tgt_ipv4_tos.attr,
+       &dev_attr_tgt_ipv6_flow_label.attr,
+       &dev_attr_tgt_name.attr,
+       &dev_attr_tgt_tpgt.attr,
+       &dev_attr_tgt_link_local_ipv6.attr,
+       &dev_attr_tgt_discovery_parent.attr,
+       &dev_attr_tgt_tcp_xmit_wsf.attr,
+       &dev_attr_tgt_tcp_recv_wsf.attr,
+       &dev_attr_tgt_username.attr,
+       &dev_attr_tgt_password.attr,
+       &dev_attr_tgt_statsn.attr,
+       &dev_attr_tgt_exp_statsn.attr,
+       NULL,
+};
+
+static struct attribute_group iscsi_flash_tgt_group = {
+       .attrs = iscsi_flash_tgt_attrs,
+       .is_visible = iscsi_flash_tgt_attr_is_visible,
+};
+
+struct iscsi_flash_tgt *
+iscsi_create_flash_tgt(struct Scsi_Host *shost, int index,
+                      struct iscsi_transport *transport,
+                      int dd_size)
+{
+       struct iscsi_flash_tgt *tgt;
+       int err;
+
+       tgt = kzalloc(sizeof(*tgt) + dd_size, GFP_KERNEL);
+       if (!tgt)
+               return NULL;
+
+       INIT_LIST_HEAD(&tgt->list);
+       tgt->transport = transport;
+       tgt->tgt_idx = index;
+       tgt->dev.release = iscsi_flash_tgt_release;
+       tgt->dev.class = &iscsi_flash_tgt_class;
+       /* parent reference released in iscsi_flash_tgt_release */
+       tgt->dev.parent = get_device(&shost->shost_gendev);
+       dev_set_name(&tgt->dev, "tgt-%u-%u", shost->host_no, index);
+
+       err = device_register(&tgt->dev);
+       if (err)
+               goto free_tgt;
+
+       err = sysfs_create_group(&tgt->dev.kobj, &iscsi_flash_tgt_group);
+       if (err)
+               goto unreg_tgt;
+
+       if (dd_size)
+               tgt->dd_data = &tgt[1];
+
+       return tgt;
+
+unreg_tgt:
+       device_unregister(&tgt->dev);
+       return NULL;
+
+free_tgt:
+       put_device(tgt->dev.parent);
+       kfree(tgt);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_create_flash_tgt);
+
+int iscsi_is_flash_tgt_dev(const struct device *dev)
+{
+       return dev->release == iscsi_flash_tgt_release;
+}
+EXPORT_SYMBOL_GPL(iscsi_is_flash_tgt_dev);
+
+static int flash_tgt_match_index(struct device *dev, void *data)
+{
+       struct iscsi_flash_tgt *tgt;
+       int ret = 0;
+
+       if (!iscsi_is_flash_tgt_dev(dev))
+               goto exit_tgt_match_index;
+
+       tgt = iscsi_dev_to_flash_tgt(dev);
+       ret = (tgt->tgt_idx == *((int *)data)) ? 1 : 0;
+
+exit_tgt_match_index:
+       return ret;
+}
+
+static struct iscsi_flash_tgt *
+iscsi_get_flash_tgt_by_index(struct Scsi_Host *shost, void *data,
+                            int (*fn)(struct device *dev, void *data))
+{
+       struct iscsi_flash_tgt *tgt = NULL;
+       struct device *dev;
+
+       dev = device_find_child(&shost->shost_gendev, data, fn);
+       if (dev)
+               tgt = iscsi_dev_to_flash_tgt(dev);
+
+       return tgt;
+}
+
+struct device *iscsi_find_flash_tgt(struct Scsi_Host *shost, void *data,
+                                   int (*fn)(struct device *dev, void *data))
+{
+       struct device *dev;
+
+       dev = device_find_child(&shost->shost_gendev, data, fn);
+       return dev;
+}
+EXPORT_SYMBOL_GPL(iscsi_find_flash_tgt);
+
+void iscsi_destroy_flash_tgt(struct iscsi_flash_tgt *tgt)
+{
+       list_del(&tgt->list);
+       sysfs_remove_group(&tgt->dev.kobj, &iscsi_flash_tgt_group);
+       device_unregister(&tgt->dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_destroy_flash_tgt);
+
+static int iscsi_iter_destroy_flash_tgt_fn(struct device *dev, void *data)
+{
+       if (!iscsi_is_flash_tgt_dev(dev))
+               return 0;
+
+       iscsi_destroy_flash_tgt(iscsi_dev_to_flash_tgt(dev));
+       return 0;
+}
+
+void iscsi_destroy_all_flash_tgt(struct Scsi_Host *shost)
+{
+       device_for_each_child(&shost->shost_gendev, NULL,
+                             iscsi_iter_destroy_flash_tgt_fn);
+}
+EXPORT_SYMBOL_GPL(iscsi_destroy_all_flash_tgt);
+
+/*
  * BSG support
  */
 /**
@@ -2092,6 +2518,240 @@ static int iscsi_delete_chap(struct iscsi_transport 
*transport,
        return err;
 }
 
+static int iscsi_set_flash_tgt_param(struct iscsi_transport *transport,
+                                    struct iscsi_uevent *ev, uint32_t len)
+{
+       char *data = (char *)ev + sizeof(*ev);
+       struct Scsi_Host *shost;
+       struct iscsi_flash_tgt *tgt;
+       uint32_t *idx;
+       int err = 0;
+
+       if (!transport->set_flash_tgt_param) {
+               err = -ENOSYS;
+               goto exit_set_flash_tgt;
+       }
+
+       shost = scsi_host_lookup(ev->u.set_flash_tgt.host_no);
+       if (!shost) {
+               printk(KERN_ERR "%s could not find host no %u\n",
+                      __func__, ev->u.set_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_set_flash_tgt;
+       }
+
+       idx = &ev->u.set_flash_tgt.tgt_idx;
+       tgt = iscsi_get_flash_tgt_by_index(shost, idx,
+                                          flash_tgt_match_index);
+       if (!tgt) {
+               printk(KERN_ERR "%s could not find tgt %u for host no %u\n",
+                      __func__, *idx, ev->u.set_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_set_flash_tgt;
+       }
+
+       err = transport->set_flash_tgt_param(tgt,
+                                            ev->u.set_flash_tgt.param,
+                                            data, len);
+put_exit_set_flash_tgt:
+       scsi_host_put(shost);
+
+exit_set_flash_tgt:
+       return err;
+}
+
+static int iscsi_new_flash_tgt(struct iscsi_transport *transport,
+                              struct iscsi_uevent *ev, uint32_t len)
+{
+       char *data = (char *)ev + sizeof(*ev);
+       struct Scsi_Host *shost;
+       struct iscsi_flash_tgt *tgt = NULL;
+       int err = 0;
+
+       if (!transport->new_flash_tgt) {
+               err = -ENOSYS;
+               goto exit_new_flash_tgt;
+       }
+
+       shost = scsi_host_lookup(ev->u.new_flash_tgt.host_no);
+       if (!shost) {
+               printk(KERN_ERR "%s could not find host no %u\n",
+                      __func__, ev->u.new_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_new_flash_tgt;
+       }
+
+       tgt = transport->new_flash_tgt(shost, data, len);
+
+       if (tgt)
+               ev->r.new_flash_tgt_ret.tgt_idx = tgt->tgt_idx;
+       else
+               err = -EIO;
+
+put_exit_new_flash_tgt:
+       scsi_host_put(shost);
+
+exit_new_flash_tgt:
+       return err;
+}
+
+static int iscsi_del_flash_tgt(struct iscsi_transport *transport,
+                              struct iscsi_uevent *ev)
+{
+       struct Scsi_Host *shost;
+       struct iscsi_flash_tgt *tgt;
+       uint32_t *idx;
+       int err = 0;
+
+       if (!transport->del_flash_tgt) {
+               err = -ENOSYS;
+               goto exit_del_flash_tgt;
+       }
+
+       shost = scsi_host_lookup(ev->u.del_flash_tgt.host_no);
+       if (!shost) {
+               printk(KERN_ERR "%s could not find host no %u\n",
+                      __func__, ev->u.del_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_del_flash_tgt;
+       }
+
+       idx = &ev->u.del_flash_tgt.tgt_idx;
+       tgt = iscsi_get_flash_tgt_by_index(shost, idx,
+                                          flash_tgt_match_index);
+       if (!tgt) {
+               printk(KERN_ERR "%s could not find tgt %u for host no %u\n",
+                      __func__, *idx, ev->u.del_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_del_flash_tgt;
+       }
+
+       transport->del_flash_tgt(tgt);
+
+put_exit_del_flash_tgt:
+       scsi_host_put(shost);
+
+exit_del_flash_tgt:
+       return err;
+}
+
+static int iscsi_apply_flash_tgt(struct iscsi_transport *transport,
+                                 struct iscsi_uevent *ev)
+{
+       struct Scsi_Host *shost;
+       struct iscsi_flash_tgt *tgt;
+       uint32_t *idx;
+       int err = 0;
+
+       if (!transport->apply_flash_tgt) {
+               err = -ENOSYS;
+               goto exit_apply_flash_tgt;
+       }
+
+       shost = scsi_host_lookup(ev->u.apply_flash_tgt.host_no);
+       if (!shost) {
+               printk(KERN_ERR "%s could not find host no %u\n",
+                      __func__, ev->u.apply_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_apply_flash_tgt;
+       }
+
+       idx = &ev->u.apply_flash_tgt.tgt_idx;
+       tgt = iscsi_get_flash_tgt_by_index(shost, idx,
+                                          flash_tgt_match_index);
+       if (!tgt) {
+               printk(KERN_ERR "%s could not find tgt %u for host no %u\n",
+                      __func__, *idx, ev->u.apply_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_apply_flash_tgt;
+       }
+
+       err = transport->apply_flash_tgt(tgt);
+
+put_exit_apply_flash_tgt:
+       scsi_host_put(shost);
+
+exit_apply_flash_tgt:
+       return err;
+}
+
+static int iscsi_login_flash_tgt(struct iscsi_transport *transport,
+                                struct iscsi_uevent *ev)
+{
+       struct Scsi_Host *shost;
+       struct iscsi_flash_tgt *tgt;
+       uint32_t *idx;
+       int err = 0;
+
+       if (!transport->login_flash_tgt) {
+               err = -ENOSYS;
+               goto exit_login_flash_tgt;
+       }
+
+       shost = scsi_host_lookup(ev->u.login_flash_tgt.host_no);
+       if (!shost) {
+               printk(KERN_ERR "%s could not find host no %u\n",
+                      __func__, ev->u.login_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_login_flash_tgt;
+       }
+
+       idx = &ev->u.login_flash_tgt.tgt_idx;
+       tgt = iscsi_get_flash_tgt_by_index(shost, idx,
+                                          flash_tgt_match_index);
+       if (!tgt) {
+               printk(KERN_ERR "%s could not find tgt %u for host no %u\n",
+                      __func__, *idx, ev->u.login_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_login_flash_tgt;
+       }
+
+       err = transport->login_flash_tgt(tgt);
+
+put_exit_login_flash_tgt:
+       scsi_host_put(shost);
+
+exit_login_flash_tgt:
+       return err;
+}
+
+static int iscsi_logout_flash_tgt(struct iscsi_transport *transport,
+                                 struct iscsi_uevent *ev)
+{
+       struct Scsi_Host *shost;
+       struct iscsi_cls_session *session;
+       int err = 0;
+
+       if (!transport->logout_flash_tgt) {
+               err = -ENOSYS;
+               goto exit_logout_flash_tgt;
+       }
+
+       shost = scsi_host_lookup(ev->u.logout_flash_tgt.host_no);
+       if (!shost) {
+               printk(KERN_ERR "%s could not find host no %u\n",
+                      __func__, ev->u.logout_flash_tgt.host_no);
+               err = -ENODEV;
+               goto put_exit_logout_flash_tgt;
+       }
+
+       session = iscsi_session_lookup(ev->u.logout_flash_tgt.sid);
+       if (!session) {
+               printk(KERN_ERR "%s could not find session id %u\n",
+                      __func__, ev->u.logout_flash_tgt.sid);
+               err = -EINVAL;
+               goto put_exit_logout_flash_tgt;
+       }
+
+       err = transport->logout_flash_tgt(session);
+
+put_exit_logout_flash_tgt:
+       scsi_host_put(shost);
+
+exit_logout_flash_tgt:
+       return err;
+}
+
 static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 {
@@ -2246,6 +2906,27 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr 
*nlh, uint32_t *group)
        case ISCSI_UEVENT_DELETE_CHAP:
                err = iscsi_delete_chap(transport, ev);
                break;
+       case ISCSI_UEVENT_SET_FLASHTGT_PARAM:
+               err = iscsi_set_flash_tgt_param(transport, ev,
+                                               nlmsg_attrlen(nlh,
+                                                             sizeof(*ev)));
+               break;
+       case ISCSI_UEVENT_NEW_FLASHTGT:
+               err = iscsi_new_flash_tgt(transport, ev,
+                                         nlmsg_attrlen(nlh, sizeof(*ev)));
+               break;
+       case ISCSI_UEVENT_DEL_FLASHTGT:
+               err = iscsi_del_flash_tgt(transport, ev);
+               break;
+       case ISCSI_UEVENT_APPLY_FLASHTGT:
+               err = iscsi_apply_flash_tgt(transport, ev);
+               break;
+       case ISCSI_UEVENT_LOGIN_FLASHTGT:
+               err = iscsi_login_flash_tgt(transport, ev);
+               break;
+       case ISCSI_UEVENT_LOGOUT_FLASHTGT:
+               err = iscsi_logout_flash_tgt(transport, ev);
+               break;
        default:
                err = -ENOSYS;
                break;
@@ -2965,10 +3646,14 @@ static __init int iscsi_transport_init(void)
        if (err)
                goto unregister_transport_class;
 
-       err = class_register(&iscsi_iface_class);
+       err = class_register(&iscsi_flash_tgt_class);
        if (err)
                goto unregister_endpoint_class;
 
+       err = class_register(&iscsi_iface_class);
+       if (err)
+               goto unregister_flash_tgt_class;
+
        err = transport_class_register(&iscsi_host_class);
        if (err)
                goto unregister_iface_class;
@@ -3003,6 +3688,8 @@ unregister_host_class:
        transport_class_unregister(&iscsi_host_class);
 unregister_iface_class:
        class_unregister(&iscsi_iface_class);
+unregister_flash_tgt_class:
+       class_unregister(&iscsi_flash_tgt_class);
 unregister_endpoint_class:
        class_unregister(&iscsi_endpoint_class);
 unregister_transport_class:
@@ -3019,6 +3706,7 @@ static void __exit iscsi_transport_exit(void)
        transport_class_unregister(&iscsi_host_class);
        class_unregister(&iscsi_endpoint_class);
        class_unregister(&iscsi_iface_class);
+       class_unregister(&iscsi_flash_tgt_class);
        class_unregister(&iscsi_transport_class);
 }
 
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 917741b..90ea755 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -63,6 +63,12 @@ enum iscsi_uevent_e {
        ISCSI_UEVENT_PING               = UEVENT_BASE + 22,
        ISCSI_UEVENT_GET_CHAP           = UEVENT_BASE + 23,
        ISCSI_UEVENT_DELETE_CHAP        = UEVENT_BASE + 24,
+       ISCSI_UEVENT_SET_FLASHTGT_PARAM = UEVENT_BASE + 25,
+       ISCSI_UEVENT_NEW_FLASHTGT       = UEVENT_BASE + 26,
+       ISCSI_UEVENT_DEL_FLASHTGT       = UEVENT_BASE + 27,
+       ISCSI_UEVENT_APPLY_FLASHTGT     = UEVENT_BASE + 28,
+       ISCSI_UEVENT_LOGIN_FLASHTGT     = UEVENT_BASE + 29,
+       ISCSI_UEVENT_LOGOUT_FLASHTGT    = UEVENT_BASE + 30,
 
        /* up events */
        ISCSI_KEVENT_RECV_PDU           = KEVENT_BASE + 1,
@@ -210,6 +216,32 @@ struct iscsi_uevent {
                       uint32_t        host_no;
                       uint16_t        chap_tbl_idx;
                } delete_chap;
+               struct msg_set_flash_tgt_param {
+                       uint32_t        host_no;
+                       uint32_t        tgt_idx;
+                       uint32_t        param; /* enum iscsi_flash_tgt_param */
+                       uint32_t        len;
+               } set_flash_tgt;
+               struct msg_new_flash_tgt {
+                       uint32_t        host_no;
+                       uint32_t        len;
+               } new_flash_tgt;
+               struct msg_del_flash_tgt {
+                       uint32_t        host_no;
+                       uint32_t        tgt_idx;
+               } del_flash_tgt;
+               struct msg_apply_flash_tgt {
+                       uint32_t        host_no;
+                       uint32_t        tgt_idx;
+               } apply_flash_tgt;
+               struct msg_login_flash_tgt {
+                       uint32_t        host_no;
+                       uint32_t        tgt_idx;
+               } login_flash_tgt;
+               struct msg_logout_flash_tgt {
+                       uint32_t        host_no;
+                       uint32_t        sid;
+               } logout_flash_tgt;
        } u;
        union {
                /* messages k -> u */
@@ -267,6 +299,9 @@ struct iscsi_uevent {
                                                   with each ping request */
                        uint32_t        data_size;
                } ping_comp;
+               struct msg_new_flash_tgt_ret {
+                       uint32_t        tgt_idx;
+               } new_flash_tgt_ret;
        } r;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
@@ -274,6 +309,7 @@ enum iscsi_param_type {
        ISCSI_PARAM,            /* iscsi_param (session, conn, target, LU) */
        ISCSI_HOST_PARAM,       /* iscsi_host_param */
        ISCSI_NET_PARAM,        /* iscsi_net_param */
+       ISCSI_FLASHTGT_PARAM,   /* iscsi_flash_tgt_param */
 };
 
 struct iscsi_iface_param_info {
@@ -469,6 +505,76 @@ enum iscsi_host_param {
        ISCSI_HOST_PARAM_MAX,
 };
 
+/* iSCSI Flash Target params */
+enum iscsi_flash_tgt_param {
+       ISCSI_FLASHTGT_IS_FW_ASSIGNED_IPV6,
+       ISCSI_FLASHTGT_DEV_TYPE,
+       ISCSI_FLASHTGT_DIF_EN,
+       ISCSI_FLASHTGT_AUTO_SND_TGT_DISABLE,
+       ISCSI_FLASHTGT_DISCOVERY_SESS,
+       ISCSI_FLASHTGT_ENTRY_EN,
+       ISCSI_FLASHTGT_DEV_ASSOC_TARGET,
+       ISCSI_FLASHTGT_DEV_ASSOC_INITIATOR,
+       /* number of commands that can execute concurrently */
+       ISCSI_FLASHTGT_EXEC_THROTTLE,
+       /* number of commands that are executing */
+       ISCSI_FLASHTGT_EXEC_COUNT,
+       /* number of retry attempts for retryable events */
+       ISCSI_FLASHTGT_RETRY_COUNT,
+       /* interval between attempts for retryable events */
+       ISCSI_FLASHTGT_RETRY_DELAY,
+       ISCSI_FLASHTGT_HDR_DGST_EN,
+       ISCSI_FLASHTGT_DATA_DGST_EN,
+       ISCSI_FLASHTGT_IMM_DATA_EN,
+       ISCSI_FLASHTGT_INITIAL_R2T_EN,
+       ISCSI_FLASHTGT_DATASEQ_INORDER,
+       ISCSI_FLASHTGT_PDU_INORDER,
+       ISCSI_FLASHTGT_CHAP_AUTH_EN,
+       ISCSI_FLASHTGT_SNACK_REQ_EN,
+       ISCSI_FLASHTGT_DISCOVERY_LOGOUT_EN,
+       ISCSI_FLASHTGT_BIDI_CHAP_EN,
+       /* make authentication for discovery sessions optional */
+       ISCSI_FLASHTGT_DISCOVERY_AUTH_OPTIONAL,
+       ISCSI_FLASHTGT_ERL,
+       ISCSI_FLASHTGT_TCP_TIMESTAMP_STAT,
+       ISCSI_FLASHTGT_TCP_NAGLE_DISABLE,
+       ISCSI_FLASHTGT_TCP_WSF_DISABLE,
+       ISCSI_FLASHTGT_TCP_TIMER_SCALE,
+       ISCSI_FLASHTGT_TCP_TIMESTAMP_EN,
+       ISCSI_FLASHTGT_IP_FRAG_DISABLE,
+       ISCSI_FLASHTGT_MAX_RECV_DLENGTH,
+       ISCSI_FLASHTGT_MAX_XMIT_DLENGTH,
+       ISCSI_FLASHTGT_FIRST_BURST,
+       ISCSI_FLASHTGT_DEF_TIME2WAIT,
+       ISCSI_FLASHTGT_DEF_TIME2RETAIN,
+       ISCSI_FLASHTGT_MAX_R2T,
+       ISCSI_FLASHTGT_KEEPALIVE_TMO,
+       ISCSI_FLASHTGT_ISID,
+       ISCSI_FLASHTGT_TSID,
+       ISCSI_FLASHTGT_PORT,
+       ISCSI_FLASHTGT_MAX_BURST,
+       ISCSI_FLASHTGT_DEF_TMF_TMO,
+       ISCSI_FLASHTGT_IPADDR,
+       ISCSI_FLASHTGT_ALIAS,
+       ISCSI_FLASHTGT_REDIRECT_IPADDR,
+       ISCSI_FLASHTGT_MAX_SEGMENT_SIZE,
+       ISCSI_FLASHTGT_LOCAL_PORT,
+       ISCSI_FLASHTGT_IPV4_TOS,
+       ISCSI_FLASHTGT_IPV6_FLOW_LABEL,
+       ISCSI_FLASHTGT_NAME,
+       ISCSI_FLASHTGT_TPGT,
+       ISCSI_FLASHTGT_LINK_LOCAL_IPV6,
+       ISCSI_FLASHTGT_DISCOVERY_PARENT,
+       ISCSI_FLASHTGT_TCP_XMIT_WSF,
+       ISCSI_FLASHTGT_TCP_RECV_WSF,
+       ISCSI_FLASHTGT_USERNAME,
+       ISCSI_FLASHTGT_PASSWORD,
+       ISCSI_FLASHTGT_STATSN,
+       ISCSI_FLASHTGT_EXP_STATSN,
+
+       ISCSI_FLASHTGT_MAX,
+};
+
 /* iSCSI port Speed */
 enum iscsi_port_speed {
        ISCSI_PORT_SPEED_UNKNOWN        = 0x1,
diff --git a/include/scsi/scsi_transport_iscsi.h 
b/include/scsi/scsi_transport_iscsi.h
index 53f0b36..60e8839 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -39,6 +39,7 @@ struct iscsi_task;
 struct sockaddr;
 struct iscsi_iface;
 struct bsg_job;
+struct iscsi_flash_tgt;
 
 /**
  * struct iscsi_transport - iSCSI Transport template
@@ -150,6 +151,16 @@ struct iscsi_transport {
        int (*get_chap) (struct Scsi_Host *shost, uint16_t chap_tbl_idx,
                         uint32_t *num_entries, char *buf);
        int (*delete_chap) (struct Scsi_Host *shost, uint16_t chap_tbl_idx);
+       int (*get_flash_tgt_param) (struct iscsi_flash_tgt *tgt, int param,
+                                   char *buf);
+       int (*set_flash_tgt_param) (struct iscsi_flash_tgt *tgt, int param,
+                                   const char *buf, int len);
+       struct iscsi_flash_tgt *(*new_flash_tgt) (struct Scsi_Host *shost,
+                                                 const char *buf, int len);
+       void (*del_flash_tgt) (struct iscsi_flash_tgt *tgt);
+       int (*apply_flash_tgt) (struct iscsi_flash_tgt *tgt);
+       int (*login_flash_tgt) (struct iscsi_flash_tgt *tgt);
+       int (*logout_flash_tgt) (struct iscsi_cls_session *cls_sess);
 };
 
 /*
@@ -286,6 +297,20 @@ struct iscsi_iface {
 #define iscsi_iface_to_shost(_iface) \
        dev_to_shost(_iface->dev.parent)
 
+struct iscsi_flash_tgt {
+       struct list_head list;
+       struct device dev;
+       struct iscsi_transport *transport;
+       int tgt_idx;
+       void *dd_data;  /* LLD private data */
+};
+
+#define iscsi_dev_to_flash_tgt(_dev) \
+       container_of(_dev, struct iscsi_flash_tgt, dev)
+
+#define iscsi_flash_tgt_to_shost(_tgt) \
+       dev_to_shost(_tgt->dev.parent)
+
 /*
  * session and connection functions that can be used by HW iSCSI LLDs
  */
@@ -330,4 +355,14 @@ extern char *iscsi_get_port_speed_name(struct Scsi_Host 
*shost);
 extern char *iscsi_get_port_state_name(struct Scsi_Host *shost);
 extern int iscsi_is_session_dev(const struct device *dev);
 
+extern struct device *
+iscsi_find_flash_tgt(struct Scsi_Host *shost, void *data,
+                    int (*fn)(struct device *dev, void *data));
+extern struct iscsi_flash_tgt *iscsi_create_flash_tgt(struct Scsi_Host *shost,
+                                                     int index,
+                                                     struct iscsi_transport *t,
+                                                     int dd_size);
+extern void iscsi_destroy_flash_tgt(struct iscsi_flash_tgt *tgt);
+extern void iscsi_destroy_all_flash_tgt(struct Scsi_Host *shost);
+extern int iscsi_is_flash_tgt_dev(const struct device *dev);
 #endif
-- 
1.7.8.GIT

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/open-iscsi?hl=en.

Reply via email to