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>/

Eg:
    /sys/class/iscsi_flash_tgt/tgt-1-0/apply
    /sys/class/iscsi_flash_tgt/tgt-1-0/login
    /sys/class/iscsi_flash_tgt/tgt-1-0/logout
    /sys/class/iscsi_flash_tgt/tgt-1-0/<Target attributes>

    Here: apply, login and logout are the operations which iscsiadm can
          perform on each flash target entry.

Operation to add a new flast target or delete a flash target can be performed
using two new sysfs attributes as given below:

    /sys/class/iscsi_host/host1/add_flash_tgt
    /sys/class/iscsi_host/host1/del_flash_tgt

Signed-off-by: Adheer Chandravanshi <[email protected]>
Signed-off-by: Vikas Chaudhary <[email protected]>
---
 drivers/scsi/scsi_transport_iscsi.c |  469 ++++++++++++++++++++++++++++++++++-
 include/scsi/iscsi_if.h             |   67 +++++
 include/scsi/scsi_transport_iscsi.h |   28 ++
 3 files changed, 551 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 31969f2..6d92331 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,417 @@ 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_FLASH_TGT_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);                 \
+}                                                                      \
+
+/* flash tgt attrs store */
+#define iscsi_flash_tgt_attr_store(type, name, param)                  \
+static ssize_t                                                         \
+store_##type##_##name(struct device *dev, struct device_attribute *attr,\
+                     const char *buf, size_t len)                      \
+{                                                                      \
+       struct iscsi_flash_tgt *tgt = iscsi_dev_to_flash_tgt(dev);      \
+       struct iscsi_transport *t = tgt->transport;                     \
+       return t->set_flash_tgt_param(tgt, param, buf, len);            \
+}                                                                      \
+
+#define iscsi_flash_tgt_attr(type, name, param)                                
\
+       iscsi_flash_tgt_attr_show(type, name, param)                    \
+       iscsi_flash_tgt_attr_store(type, name, param)                   \
+static ISCSI_FLASH_TGT_ATTR(type, name, S_IRUGO | S_IWUSR,             \
+                           show_##type##_##name, store_##type##_##name);
+
+/* Target attributes */
+
+iscsi_flash_tgt_attr(tgt, ipaddress, ISCSI_FLASH_TGT_IP_ADDR);
+iscsi_flash_tgt_attr(tgt, port, ISCSI_FLASH_TGT_PORT);
+iscsi_flash_tgt_attr(tgt, opt_auto_send_tgt_disable,
+                    ISCSI_FLASH_TGT_OPT_AUTO_SND_TGT_DISABLE);
+iscsi_flash_tgt_attr(tgt, opt_discovery_session,
+                    ISCSI_FLASH_TGT_OPT_DISCOVERY_SESS);
+iscsi_flash_tgt_attr(tgt, opt_entry_enable, ISCSI_FLASH_TGT_OPT_ENTRY_ENABLE);
+iscsi_flash_tgt_attr(tgt, opt_dev_assoc_target,
+                    ISCSI_FLASH_TGT_OPT_DEV_ASSOC_TARGET);
+iscsi_flash_tgt_attr(tgt, opt_dev_assoc_initiator,
+                    ISCSI_FLASH_TGT_OPT_DEV_ASSOC_INITIATOR);
+iscsi_flash_tgt_attr(tgt, exec_throttle, ISCSI_FLASH_TGT_EXEC_THROTTLE);
+iscsi_flash_tgt_attr(tgt, exec_count, ISCSI_FLASH_TGT_EXEC_COUNT);
+iscsi_flash_tgt_attr(tgt, retry_count, ISCSI_FLASH_TGT_RETRY_COUNT);
+iscsi_flash_tgt_attr(tgt, retry_delay, ISCSI_FLASH_TGT_RETRY_DELAY);
+iscsi_flash_tgt_attr(tgt, iscsiopt_enable_hdr_digest,
+                    ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_HDR_DIGEST);
+iscsi_flash_tgt_attr(tgt, iscsiopt_enable_data_digest,
+                    ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_DATA_DIGEST);
+iscsi_flash_tgt_attr(tgt, iscsiopt_enable_immediate_data,
+                    ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_IMMEDIATE_DATA);
+iscsi_flash_tgt_attr(tgt, iscsiopt_enable_initial_r2t,
+                    ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_INITIAL_R2T);
+iscsi_flash_tgt_attr(tgt, iscsiopt_data_seq_in_order,
+                    ISCSI_FLASH_TGT_ISCSIOPT_DATA_SEQ_IN_ORDER);
+iscsi_flash_tgt_attr(tgt, iscsiopt_data_pdu_in_order,
+                    ISCSI_FLASH_TGT_ISCSIOPT_DATA_PDU_IN_ORDER);
+iscsi_flash_tgt_attr(tgt, iscsiopt_chap_auth_enable,
+                    ISCSI_FLASH_TGT_ISCSIOPT_CHAP_AUTH_ENABLE);
+iscsi_flash_tgt_attr(tgt, iscsiopt_snack_req_enable,
+                    ISCSI_FLASH_TGT_ISCSIOPT_SNACK_REQ_ENABLE);
+iscsi_flash_tgt_attr(tgt, iscsiopt_discovery_logout_enable,
+                    ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_LOGOUT_ENABLE);
+iscsi_flash_tgt_attr(tgt, iscsiopt_bidi_chap_challenge_enable,
+                    ISCSI_FLASH_TGT_ISCSIOPT_BIDI_CHAP_CHALLENGE_ENABLE);
+iscsi_flash_tgt_attr(tgt, iscsiopt_discovery_auth_optional,
+                    ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_AUTH_OPTIONAL);
+iscsi_flash_tgt_attr(tgt, tcpopt_nagle_disable,
+                    ISCSI_FLASH_TGT_TCPOPT_NAGLE_DISABLE);
+iscsi_flash_tgt_attr(tgt, tcpopt_timer_scale,
+                    ISCSI_FLASH_TGT_TCPOPT_TIMER_SCALE);
+iscsi_flash_tgt_attr(tgt, tcpopt_timestamp_enable,
+                    ISCSI_FLASH_TGT_TCPOPT_TIMESTAMP_ENABLE);
+iscsi_flash_tgt_attr(tgt, ipopt_frag_disable,
+                    ISCSI_FLASH_TGT_IPOPT_FRAG_DISABLE);
+iscsi_flash_tgt_attr(tgt, max_recv_data_segment_length,
+                    ISCSI_FLASH_TGT_MAX_RECV_DATA_SEGMENT_LEN);
+iscsi_flash_tgt_attr(tgt, max_xmit_data_segment_length,
+                    ISCSI_FLASH_TGT_MAX_XMIT_DATA_SEGMENT_LEN);
+iscsi_flash_tgt_attr(tgt, first_burst_length,
+                    ISCSI_FLASH_TGT_FIRST_BURST_LEN);
+iscsi_flash_tgt_attr(tgt, default_time2wait,
+                    ISCSI_FLASH_TGT_DEF_TIME2WAIT);
+iscsi_flash_tgt_attr(tgt, default_time2retain,
+                    ISCSI_FLASH_TGT_DEF_TIME2RETAIN);
+iscsi_flash_tgt_attr(tgt, max_outstanding_r2t,
+                    ISCSI_FLASH_TGT_MAX_OUTSTANDING_R2T);
+iscsi_flash_tgt_attr(tgt, noop_out_interval,
+                    ISCSI_FLASH_TGT_NOOP_OUT_INTERVAL);
+iscsi_flash_tgt_attr(tgt, isid, ISCSI_FLASH_TGT_ISID);
+iscsi_flash_tgt_attr(tgt, tsid, ISCSI_FLASH_TGT_TSID);
+iscsi_flash_tgt_attr(tgt, max_burst_length,
+                    ISCSI_FLASH_TGT_MAX_BURST_LEN);
+iscsi_flash_tgt_attr(tgt, firmware_cmd_timeout,
+                    ISCSI_FLASH_TGT_FW_CMD_TIMEOUT);
+iscsi_flash_tgt_attr(tgt, iscsi_alias, ISCSI_FLASH_TGT_ISCSI_ALIAS);
+iscsi_flash_tgt_attr(tgt, target_address, ISCSI_FLASH_TGT_ADDRESS);
+iscsi_flash_tgt_attr(tgt, max_segment_size, ISCSI_FLASH_TGT_MAX_SEGMENT_SIZE);
+iscsi_flash_tgt_attr(tgt, local_port, ISCSI_FLASH_TGT_LOCAL_PORT);
+iscsi_flash_tgt_attr(tgt, ipv4_tos, ISCSI_FLASH_TGT_IPV4_TOS);
+iscsi_flash_tgt_attr(tgt, ipv6_flow_label, ISCSI_FLASH_TGT_IPV6_FLOW_LABEL);
+iscsi_flash_tgt_attr(tgt, name, ISCSI_FLASH_TGT_NAME);
+iscsi_flash_tgt_attr(tgt, tpgt, ISCSI_FLASH_TGT_TPGT);
+iscsi_flash_tgt_attr(tgt, tcp_xmit_wsf, ISCSI_FLASH_TGT_TCP_XMIT_WIN_SCALE);
+iscsi_flash_tgt_attr(tgt, tcp_recv_wsf, ISCSI_FLASH_TGT_TCP_RECV_WIN_SCALE);
+iscsi_flash_tgt_attr(tgt, chap_user, ISCSI_FLASH_TGT_CHAP_USER);
+iscsi_flash_tgt_attr(tgt, chap_passwd, ISCSI_FLASH_TGT_CHAP_PASSWD);
+iscsi_flash_tgt_attr(tgt, chap_user_in, ISCSI_FLASH_TGT_CHAP_USER_IN);
+iscsi_flash_tgt_attr(tgt, chap_passwd_in, ISCSI_FLASH_TGT_CHAP_PASSWD_IN);
+iscsi_flash_tgt_attr(tgt, login, ISCSI_FLASH_TGT_LOGIN);
+iscsi_flash_tgt_attr(tgt, logout, ISCSI_FLASH_TGT_LOGOUT);
+iscsi_flash_tgt_attr(tgt, apply, ISCSI_FLASH_TGT_APPLY);
+
+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_ipaddress.attr) {
+               param = ISCSI_FLASH_TGT_IP_ADDR;
+       } else if (attr == &dev_attr_tgt_port.attr) {
+               param = ISCSI_FLASH_TGT_PORT;
+       } else if (attr == &dev_attr_tgt_opt_auto_send_tgt_disable.attr) {
+               param = ISCSI_FLASH_TGT_OPT_AUTO_SND_TGT_DISABLE;
+       } else if (attr == &dev_attr_tgt_opt_discovery_session.attr) {
+               param = ISCSI_FLASH_TGT_OPT_DISCOVERY_SESS;
+       } else if (attr == &dev_attr_tgt_opt_entry_enable.attr) {
+               param = ISCSI_FLASH_TGT_OPT_ENTRY_ENABLE;
+       } else if (attr == &dev_attr_tgt_opt_dev_assoc_target.attr) {
+               param = ISCSI_FLASH_TGT_OPT_DEV_ASSOC_TARGET;
+       } else if (attr == &dev_attr_tgt_opt_dev_assoc_initiator.attr) {
+               param = ISCSI_FLASH_TGT_OPT_DEV_ASSOC_INITIATOR;
+       } else if (attr == &dev_attr_tgt_exec_throttle.attr) {
+               param = ISCSI_FLASH_TGT_EXEC_THROTTLE;
+       } else if (attr == &dev_attr_tgt_exec_count.attr) {
+               param = ISCSI_FLASH_TGT_EXEC_COUNT;
+       } else if (attr == &dev_attr_tgt_retry_count.attr) {
+               param = ISCSI_FLASH_TGT_RETRY_COUNT;
+       } else if (attr == &dev_attr_tgt_retry_delay.attr) {
+               param = ISCSI_FLASH_TGT_RETRY_DELAY;
+       } else if (attr == &dev_attr_tgt_iscsiopt_enable_hdr_digest.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_HDR_DIGEST;
+       } else if (attr == &dev_attr_tgt_iscsiopt_enable_data_digest.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_DATA_DIGEST;
+       } else if (attr == &dev_attr_tgt_iscsiopt_enable_immediate_data.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_IMMEDIATE_DATA;
+       } else if (attr == &dev_attr_tgt_iscsiopt_enable_initial_r2t.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_INITIAL_R2T;
+       } else if (attr == &dev_attr_tgt_iscsiopt_data_seq_in_order.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_DATA_SEQ_IN_ORDER;
+       } else if (attr == &dev_attr_tgt_iscsiopt_data_pdu_in_order.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_DATA_PDU_IN_ORDER;
+       } else if (attr == &dev_attr_tgt_iscsiopt_chap_auth_enable.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_CHAP_AUTH_ENABLE;
+       } else if (attr == &dev_attr_tgt_iscsiopt_snack_req_enable.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_SNACK_REQ_ENABLE;
+       } else if (attr ==
+                  &dev_attr_tgt_iscsiopt_discovery_logout_enable.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_LOGOUT_ENABLE;
+       } else if (attr ==
+                  &dev_attr_tgt_iscsiopt_bidi_chap_challenge_enable.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_BIDI_CHAP_CHALLENGE_ENABLE;
+       } else if (attr ==
+                  &dev_attr_tgt_iscsiopt_discovery_auth_optional.attr) {
+               param = ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_AUTH_OPTIONAL;
+       } else if (attr == &dev_attr_tgt_tcpopt_nagle_disable.attr) {
+               param = ISCSI_FLASH_TGT_TCPOPT_NAGLE_DISABLE;
+       } else if (attr == &dev_attr_tgt_tcpopt_timer_scale.attr) {
+               param = ISCSI_FLASH_TGT_TCPOPT_TIMER_SCALE;
+       } else if (attr == &dev_attr_tgt_tcpopt_timestamp_enable.attr) {
+               param = ISCSI_FLASH_TGT_TCPOPT_TIMESTAMP_ENABLE;
+       } else if (attr == &dev_attr_tgt_ipopt_frag_disable.attr) {
+               param = ISCSI_FLASH_TGT_IPOPT_FRAG_DISABLE;
+       } else if (attr == &dev_attr_tgt_max_recv_data_segment_length.attr) {
+               param = ISCSI_FLASH_TGT_MAX_RECV_DATA_SEGMENT_LEN;
+       } else if (attr == &dev_attr_tgt_max_xmit_data_segment_length.attr) {
+               param = ISCSI_FLASH_TGT_MAX_XMIT_DATA_SEGMENT_LEN;
+       } else if (attr == &dev_attr_tgt_first_burst_length.attr) {
+               param = ISCSI_FLASH_TGT_FIRST_BURST_LEN;
+       } else if (attr == &dev_attr_tgt_default_time2wait.attr) {
+               param = ISCSI_FLASH_TGT_DEF_TIME2WAIT;
+       } else if (attr == &dev_attr_tgt_default_time2retain.attr) {
+               param = ISCSI_FLASH_TGT_DEF_TIME2RETAIN;
+       } else if (attr == &dev_attr_tgt_max_outstanding_r2t.attr) {
+               param = ISCSI_FLASH_TGT_MAX_OUTSTANDING_R2T;
+       } else if (attr == &dev_attr_tgt_noop_out_interval.attr) {
+               param = ISCSI_FLASH_TGT_NOOP_OUT_INTERVAL;
+       } else if (attr == &dev_attr_tgt_isid.attr) {
+               param = ISCSI_FLASH_TGT_ISID;
+       } else if (attr == &dev_attr_tgt_tsid.attr) {
+               param = ISCSI_FLASH_TGT_TSID;
+       } else if (attr == &dev_attr_tgt_max_burst_length.attr) {
+               param = ISCSI_FLASH_TGT_MAX_BURST_LEN;
+       } else if (attr == &dev_attr_tgt_firmware_cmd_timeout.attr) {
+               param = ISCSI_FLASH_TGT_FW_CMD_TIMEOUT;
+       } else if (attr == &dev_attr_tgt_iscsi_alias.attr) {
+               param = ISCSI_FLASH_TGT_ISCSI_ALIAS;
+       } else if (attr == &dev_attr_tgt_target_address.attr) {
+               param = ISCSI_FLASH_TGT_ADDRESS;
+       } else if (attr == &dev_attr_tgt_max_segment_size.attr) {
+               param = ISCSI_FLASH_TGT_MAX_SEGMENT_SIZE;
+       } else if (attr == &dev_attr_tgt_local_port.attr) {
+               param = ISCSI_FLASH_TGT_LOCAL_PORT;
+       } else if (attr == &dev_attr_tgt_ipv4_tos.attr) {
+               param = ISCSI_FLASH_TGT_IPV4_TOS;
+       } else if (attr == &dev_attr_tgt_ipv6_flow_label.attr) {
+               param = ISCSI_FLASH_TGT_IPV6_FLOW_LABEL;
+       } else if (attr == &dev_attr_tgt_name.attr) {
+               param = ISCSI_FLASH_TGT_NAME;
+       } else if (attr == &dev_attr_tgt_tpgt.attr) {
+               param = ISCSI_FLASH_TGT_TPGT;
+       } else if (attr == &dev_attr_tgt_tcp_xmit_wsf.attr) {
+               param = ISCSI_FLASH_TGT_TCP_XMIT_WIN_SCALE;
+       } else if (attr == &dev_attr_tgt_tcp_recv_wsf.attr) {
+               param = ISCSI_FLASH_TGT_TCP_RECV_WIN_SCALE;
+       } else if (attr == &dev_attr_tgt_chap_user.attr) {
+               param = ISCSI_FLASH_TGT_CHAP_USER;
+       } else if (attr == &dev_attr_tgt_chap_passwd.attr) {
+               param = ISCSI_FLASH_TGT_CHAP_PASSWD;
+       } else if (attr == &dev_attr_tgt_chap_user_in.attr) {
+               param = ISCSI_FLASH_TGT_CHAP_USER_IN;
+       } else if (attr == &dev_attr_tgt_chap_passwd_in.attr) {
+               param = ISCSI_FLASH_TGT_CHAP_PASSWD_IN;
+       } else if (attr == &dev_attr_tgt_login.attr) {
+               param = ISCSI_FLASH_TGT_LOGIN;
+       } else if (attr == &dev_attr_tgt_logout.attr) {
+               param = ISCSI_FLASH_TGT_LOGOUT;
+       } else if (attr == &dev_attr_tgt_apply.attr) {
+               param = ISCSI_FLASH_TGT_APPLY;
+       } else {
+               WARN_ONCE(1, "Invalid flash tgt attr");
+               return 0;
+       }
+
+       return t->attr_is_visible(ISCSI_FLASH_TGT_PARAM, param);
+}
+
+static struct attribute *iscsi_flash_tgt_attrs[] = {
+       &dev_attr_tgt_ipaddress.attr,
+       &dev_attr_tgt_port.attr,
+       &dev_attr_tgt_opt_auto_send_tgt_disable.attr,
+       &dev_attr_tgt_opt_discovery_session.attr,
+       &dev_attr_tgt_opt_entry_enable.attr,
+       &dev_attr_tgt_opt_dev_assoc_target.attr,
+       &dev_attr_tgt_opt_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_iscsiopt_enable_hdr_digest.attr,
+       &dev_attr_tgt_iscsiopt_enable_data_digest.attr,
+       &dev_attr_tgt_iscsiopt_enable_immediate_data.attr,
+       &dev_attr_tgt_iscsiopt_enable_initial_r2t.attr,
+       &dev_attr_tgt_iscsiopt_data_seq_in_order.attr,
+       &dev_attr_tgt_iscsiopt_data_pdu_in_order.attr,
+       &dev_attr_tgt_iscsiopt_chap_auth_enable.attr,
+       &dev_attr_tgt_iscsiopt_snack_req_enable.attr,
+       &dev_attr_tgt_iscsiopt_discovery_logout_enable.attr,
+       &dev_attr_tgt_iscsiopt_bidi_chap_challenge_enable.attr,
+       &dev_attr_tgt_iscsiopt_discovery_auth_optional.attr,
+       &dev_attr_tgt_tcpopt_nagle_disable.attr,
+       &dev_attr_tgt_tcpopt_timer_scale.attr,
+       &dev_attr_tgt_tcpopt_timestamp_enable.attr,
+       &dev_attr_tgt_ipopt_frag_disable.attr,
+       &dev_attr_tgt_max_recv_data_segment_length.attr,
+       &dev_attr_tgt_max_xmit_data_segment_length.attr,
+       &dev_attr_tgt_first_burst_length.attr,
+       &dev_attr_tgt_default_time2wait.attr,
+       &dev_attr_tgt_default_time2retain.attr,
+       &dev_attr_tgt_max_outstanding_r2t.attr,
+       &dev_attr_tgt_noop_out_interval.attr,
+       &dev_attr_tgt_isid.attr,
+       &dev_attr_tgt_tsid.attr,
+       &dev_attr_tgt_max_burst_length.attr,
+       &dev_attr_tgt_firmware_cmd_timeout.attr,
+       &dev_attr_tgt_iscsi_alias.attr,
+       &dev_attr_tgt_target_address.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_tcp_xmit_wsf.attr,
+       &dev_attr_tgt_tcp_recv_wsf.attr,
+       &dev_attr_tgt_chap_user.attr,
+       &dev_attr_tgt_chap_passwd.attr,
+       &dev_attr_tgt_chap_user_in.attr,
+       &dev_attr_tgt_chap_passwd_in.attr,
+       &dev_attr_tgt_login.attr,
+       &dev_attr_tgt_logout.attr,
+       &dev_attr_tgt_apply.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->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);
+
+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
  */
 /**
@@ -2654,20 +3066,36 @@ static struct attribute_group iscsi_session_group = {
 /*
  * iSCSI host attrs
  */
-#define iscsi_host_attr_show(param)                                    \
-static ssize_t                                                         \
-show_host_param_##param(struct device *dev,                            \
-                       struct device_attribute *attr, char *buf)       \
-{                                                                      \
-       struct Scsi_Host *shost = transport_class_to_shost(dev);        \
+#define iscsi_host_attr_show(param)                                        \
+static ssize_t                                                             \
+show_host_param_##param(struct device *dev,                                \
+                       struct device_attribute *attr, char *buf)           \
+{                                                                          \
+       struct Scsi_Host *shost = transport_class_to_shost(dev);            \
        struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
-       return priv->iscsi_transport->get_host_param(shost, param, buf); \
-}
+       return priv->iscsi_transport->get_host_param(shost, param, buf);    \
+}                                                                          \
+
+#define iscsi_host_flash_tgt_attr_store(param)                             \
+static ssize_t                                                             \
+store_host_flash_tgt_param_##param(struct device *dev,                     \
+                                  struct device_attribute *attr,           \
+                                  const char *buf, size_t len)             \
+{                                                                          \
+       struct Scsi_Host *shost = transport_class_to_shost(dev);            \
+       struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
+       return priv->iscsi_transport->set_host_flash_tgt_param(shost, param,\
+                                                              buf, len);   \
+}                                                                          \
 
-#define iscsi_host_attr(field, param)                                  \
-       iscsi_host_attr_show(param)                                     \
-static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \
-                       NULL);
+#define iscsi_host_attr(field, param)                                       \
+       iscsi_host_attr_show(param)                                          \
+static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, NULL);
+
+#define iscsi_host_flash_tgt_attr(field, param)                        \
+       iscsi_host_flash_tgt_attr_store(param)                  \
+static ISCSI_CLASS_ATTR(host, field, S_IWUSR, NULL,            \
+                       store_host_flash_tgt_param_##param);
 
 iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
 iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
@@ -2675,6 +3103,8 @@ iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
 iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
 iscsi_host_attr(port_state, ISCSI_HOST_PARAM_PORT_STATE);
 iscsi_host_attr(port_speed, ISCSI_HOST_PARAM_PORT_SPEED);
+iscsi_host_flash_tgt_attr(add_flash_tgt, ISCSI_HOST_PARAM_ADD_FLASH_TGT);
+iscsi_host_flash_tgt_attr(del_flash_tgt, ISCSI_HOST_PARAM_DEL_FLASH_TGT);
 
 static struct attribute *iscsi_host_attrs[] = {
        &dev_attr_host_netdev.attr,
@@ -2683,6 +3113,8 @@ static struct attribute *iscsi_host_attrs[] = {
        &dev_attr_host_initiatorname.attr,
        &dev_attr_host_port_state.attr,
        &dev_attr_host_port_speed.attr,
+       &dev_attr_host_add_flash_tgt.attr,
+       &dev_attr_host_del_flash_tgt.attr,
        NULL,
 };
 
@@ -2706,6 +3138,10 @@ static umode_t iscsi_host_attr_is_visible(struct kobject 
*kobj,
                param = ISCSI_HOST_PARAM_PORT_STATE;
        else if (attr == &dev_attr_host_port_speed.attr)
                param = ISCSI_HOST_PARAM_PORT_SPEED;
+       else if (attr == &dev_attr_host_add_flash_tgt.attr)
+               param = ISCSI_HOST_PARAM_ADD_FLASH_TGT;
+       else if (attr == &dev_attr_host_del_flash_tgt.attr)
+               param = ISCSI_HOST_PARAM_DEL_FLASH_TGT;
        else {
                WARN_ONCE(1, "Invalid host attr");
                return 0;
@@ -2953,10 +3389,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;
@@ -2991,6 +3431,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:
@@ -3007,6 +3449,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..2ab7eb2 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -274,6 +274,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_FLASH_TGT_PARAM,  /* iscsi_flash_tgt_param */
 };
 
 struct iscsi_iface_param_info {
@@ -466,9 +467,75 @@ enum iscsi_host_param {
        ISCSI_HOST_PARAM_IPADDRESS,
        ISCSI_HOST_PARAM_PORT_STATE,
        ISCSI_HOST_PARAM_PORT_SPEED,
+       ISCSI_HOST_PARAM_ADD_FLASH_TGT,
+       ISCSI_HOST_PARAM_DEL_FLASH_TGT,
        ISCSI_HOST_PARAM_MAX,
 };
 
+/* iSCSI Flash Target params */
+enum iscsi_flash_tgt_param {
+       ISCSI_FLASH_TGT_OPT_AUTO_SND_TGT_DISABLE,
+       ISCSI_FLASH_TGT_OPT_DISCOVERY_SESS,
+       ISCSI_FLASH_TGT_OPT_ENTRY_ENABLE,
+       ISCSI_FLASH_TGT_OPT_DEV_ASSOC_TARGET,
+       ISCSI_FLASH_TGT_OPT_DEV_ASSOC_INITIATOR,
+       /* number of commands that can execute concurrently */
+       ISCSI_FLASH_TGT_EXEC_THROTTLE,
+       /* number of commands that are executing */
+       ISCSI_FLASH_TGT_EXEC_COUNT,
+       /* number of retry attempts for retryable events */
+       ISCSI_FLASH_TGT_RETRY_COUNT,
+       /* interval between attempts for retryable events */
+       ISCSI_FLASH_TGT_RETRY_DELAY,
+       ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_HDR_DIGEST,
+       ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_DATA_DIGEST,
+       ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_IMMEDIATE_DATA,
+       ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_INITIAL_R2T,
+       ISCSI_FLASH_TGT_ISCSIOPT_DATA_SEQ_IN_ORDER,
+       ISCSI_FLASH_TGT_ISCSIOPT_DATA_PDU_IN_ORDER,
+       ISCSI_FLASH_TGT_ISCSIOPT_CHAP_AUTH_ENABLE,
+       ISCSI_FLASH_TGT_ISCSIOPT_SNACK_REQ_ENABLE,
+       ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_LOGOUT_ENABLE,
+       ISCSI_FLASH_TGT_ISCSIOPT_BIDI_CHAP_CHALLENGE_ENABLE,
+       /* make authentication for discovery sessions optional */
+       ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_AUTH_OPTIONAL,
+       ISCSI_FLASH_TGT_TCPOPT_NAGLE_DISABLE,
+       ISCSI_FLASH_TGT_TCPOPT_TIMER_SCALE,
+       ISCSI_FLASH_TGT_TCPOPT_TIMESTAMP_ENABLE,
+       ISCSI_FLASH_TGT_IPOPT_FRAG_DISABLE,
+       ISCSI_FLASH_TGT_MAX_RECV_DATA_SEGMENT_LEN,
+       ISCSI_FLASH_TGT_MAX_XMIT_DATA_SEGMENT_LEN,
+       ISCSI_FLASH_TGT_FIRST_BURST_LEN,
+       ISCSI_FLASH_TGT_DEF_TIME2WAIT,
+       ISCSI_FLASH_TGT_DEF_TIME2RETAIN,
+       ISCSI_FLASH_TGT_MAX_OUTSTANDING_R2T,
+       ISCSI_FLASH_TGT_NOOP_OUT_INTERVAL,
+       ISCSI_FLASH_TGT_ISID,
+       ISCSI_FLASH_TGT_TSID,
+       ISCSI_FLASH_TGT_PORT,
+       ISCSI_FLASH_TGT_MAX_BURST_LEN,
+       ISCSI_FLASH_TGT_FW_CMD_TIMEOUT,
+       ISCSI_FLASH_TGT_IP_ADDR,
+       ISCSI_FLASH_TGT_ISCSI_ALIAS,
+       ISCSI_FLASH_TGT_ADDRESS,
+       ISCSI_FLASH_TGT_MAX_SEGMENT_SIZE,
+       ISCSI_FLASH_TGT_LOCAL_PORT,
+       ISCSI_FLASH_TGT_IPV4_TOS,
+       ISCSI_FLASH_TGT_IPV6_FLOW_LABEL,
+       ISCSI_FLASH_TGT_NAME,
+       ISCSI_FLASH_TGT_TPGT,
+       ISCSI_FLASH_TGT_TCP_XMIT_WIN_SCALE,
+       ISCSI_FLASH_TGT_TCP_RECV_WIN_SCALE,
+       ISCSI_FLASH_TGT_CHAP_USER,
+       ISCSI_FLASH_TGT_CHAP_PASSWD,
+       ISCSI_FLASH_TGT_CHAP_USER_IN,
+       ISCSI_FLASH_TGT_CHAP_PASSWD_IN,
+       ISCSI_FLASH_TGT_LOGIN,
+       ISCSI_FLASH_TGT_LOGOUT,
+       ISCSI_FLASH_TGT_APPLY,
+       ISCSI_FLASH_TGT_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..630abf8 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
@@ -112,6 +113,9 @@ struct iscsi_transport {
        int (*set_host_param) (struct Scsi_Host *shost,
                               enum iscsi_host_param param, char *buf,
                               int buflen);
+       int (*set_host_flash_tgt_param) (struct Scsi_Host *shost,
+                                        enum iscsi_host_param param,
+                                        const char *buf, int buflen);
        int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
                         char *data, uint32_t data_size);
        void (*get_stats) (struct iscsi_cls_conn *conn,
@@ -150,6 +154,10 @@ 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);
 };
 
 /*
@@ -286,6 +294,16 @@ 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;
+       void *dd_data;  /* LLD private data */
+};
+
+#define iscsi_dev_to_flash_tgt(_dev) \
+       container_of(_dev, struct iscsi_flash_tgt, dev)
+
 /*
  * session and connection functions that can be used by HW iSCSI LLDs
  */
@@ -330,4 +348,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.1

-- 
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