aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_iscsi.c
diff options
context:
space:
mode:
authorAdheer Chandravanshi <adheer.chandravanshi@qlogic.com>2013-03-22 07:41:29 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-04-11 18:19:35 -0400
commitc6a4bb2ef596d0bfe0d885ef6807b263ac83e47a (patch)
tree317560eb93ab800b72a8a33762a1228b3dc40e94 /drivers/scsi/scsi_transport_iscsi.c
parent9060f6bfc389edb195548d7357e588430c32ab77 (diff)
[SCSI] scsi_transport_iscsi: Add flash node mgmt support
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/bus/iscsi_flashnode/devices/flashnode_sess-<host_no>:<flashnode_id>/<session attrs> /sys/bus/iscsi_flashnode/devices/flashnode_conn-<host_no>:<flashnode_id>:<conn_id>/<conn attrs> Signed-off-by: Adheer Chandravanshi <adheer.chandravanshi@qlogic.com> Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c1002
1 files changed, 1001 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 0a74b975efdf..ce06e8772f3a 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -25,6 +25,7 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/bsg-lib.h> 26#include <linux/bsg-lib.h>
27#include <linux/idr.h> 27#include <linux/idr.h>
28#include <linux/list.h>
28#include <net/tcp.h> 29#include <net/tcp.h>
29#include <scsi/scsi.h> 30#include <scsi/scsi.h>
30#include <scsi/scsi_host.h> 31#include <scsi/scsi_host.h>
@@ -460,6 +461,689 @@ void iscsi_destroy_iface(struct iscsi_iface *iface)
460EXPORT_SYMBOL_GPL(iscsi_destroy_iface); 461EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
461 462
462/* 463/*
464 * Interface to display flash node params to sysfs
465 */
466
467#define ISCSI_FLASHNODE_ATTR(_prefix, _name, _mode, _show, _store) \
468struct device_attribute dev_attr_##_prefix##_##_name = \
469 __ATTR(_name, _mode, _show, _store)
470
471/* flash node session attrs show */
472#define iscsi_flashnode_sess_attr_show(type, name, param) \
473static ssize_t \
474show_##type##_##name(struct device *dev, struct device_attribute *attr, \
475 char *buf) \
476{ \
477 struct iscsi_bus_flash_session *fnode_sess = \
478 iscsi_dev_to_flash_session(dev);\
479 struct iscsi_transport *t = fnode_sess->transport; \
480 return t->get_flashnode_param(fnode_sess, param, buf); \
481} \
482
483
484#define iscsi_flashnode_sess_attr(type, name, param) \
485 iscsi_flashnode_sess_attr_show(type, name, param) \
486static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
487 show_##type##_##name, NULL);
488
489/* Flash node session attributes */
490
491iscsi_flashnode_sess_attr(fnode, auto_snd_tgt_disable,
492 ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE);
493iscsi_flashnode_sess_attr(fnode, discovery_session,
494 ISCSI_FLASHNODE_DISCOVERY_SESS);
495iscsi_flashnode_sess_attr(fnode, portal_type, ISCSI_FLASHNODE_PORTAL_TYPE);
496iscsi_flashnode_sess_attr(fnode, entry_enable, ISCSI_FLASHNODE_ENTRY_EN);
497iscsi_flashnode_sess_attr(fnode, immediate_data, ISCSI_FLASHNODE_IMM_DATA_EN);
498iscsi_flashnode_sess_attr(fnode, initial_r2t, ISCSI_FLASHNODE_INITIAL_R2T_EN);
499iscsi_flashnode_sess_attr(fnode, data_seq_in_order,
500 ISCSI_FLASHNODE_DATASEQ_INORDER);
501iscsi_flashnode_sess_attr(fnode, data_pdu_in_order,
502 ISCSI_FLASHNODE_PDU_INORDER);
503iscsi_flashnode_sess_attr(fnode, chap_auth, ISCSI_FLASHNODE_CHAP_AUTH_EN);
504iscsi_flashnode_sess_attr(fnode, discovery_logout,
505 ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN);
506iscsi_flashnode_sess_attr(fnode, bidi_chap, ISCSI_FLASHNODE_BIDI_CHAP_EN);
507iscsi_flashnode_sess_attr(fnode, discovery_auth_optional,
508 ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL);
509iscsi_flashnode_sess_attr(fnode, erl, ISCSI_FLASHNODE_ERL);
510iscsi_flashnode_sess_attr(fnode, first_burst_len, ISCSI_FLASHNODE_FIRST_BURST);
511iscsi_flashnode_sess_attr(fnode, def_time2wait, ISCSI_FLASHNODE_DEF_TIME2WAIT);
512iscsi_flashnode_sess_attr(fnode, def_time2retain,
513 ISCSI_FLASHNODE_DEF_TIME2RETAIN);
514iscsi_flashnode_sess_attr(fnode, max_outstanding_r2t, ISCSI_FLASHNODE_MAX_R2T);
515iscsi_flashnode_sess_attr(fnode, isid, ISCSI_FLASHNODE_ISID);
516iscsi_flashnode_sess_attr(fnode, tsid, ISCSI_FLASHNODE_TSID);
517iscsi_flashnode_sess_attr(fnode, max_burst_len, ISCSI_FLASHNODE_MAX_BURST);
518iscsi_flashnode_sess_attr(fnode, def_taskmgmt_tmo,
519 ISCSI_FLASHNODE_DEF_TASKMGMT_TMO);
520iscsi_flashnode_sess_attr(fnode, targetalias, ISCSI_FLASHNODE_ALIAS);
521iscsi_flashnode_sess_attr(fnode, targetname, ISCSI_FLASHNODE_NAME);
522iscsi_flashnode_sess_attr(fnode, tpgt, ISCSI_FLASHNODE_TPGT);
523iscsi_flashnode_sess_attr(fnode, discovery_parent_idx,
524 ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX);
525iscsi_flashnode_sess_attr(fnode, discovery_parent_type,
526 ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE);
527iscsi_flashnode_sess_attr(fnode, chap_in_idx, ISCSI_FLASHNODE_CHAP_IN_IDX);
528iscsi_flashnode_sess_attr(fnode, chap_out_idx, ISCSI_FLASHNODE_CHAP_OUT_IDX);
529iscsi_flashnode_sess_attr(fnode, username, ISCSI_FLASHNODE_USERNAME);
530iscsi_flashnode_sess_attr(fnode, username_in, ISCSI_FLASHNODE_USERNAME_IN);
531iscsi_flashnode_sess_attr(fnode, password, ISCSI_FLASHNODE_PASSWORD);
532iscsi_flashnode_sess_attr(fnode, password_in, ISCSI_FLASHNODE_PASSWORD_IN);
533iscsi_flashnode_sess_attr(fnode, is_boot_target, ISCSI_FLASHNODE_IS_BOOT_TGT);
534
535static struct attribute *iscsi_flashnode_sess_attrs[] = {
536 &dev_attr_fnode_auto_snd_tgt_disable.attr,
537 &dev_attr_fnode_discovery_session.attr,
538 &dev_attr_fnode_portal_type.attr,
539 &dev_attr_fnode_entry_enable.attr,
540 &dev_attr_fnode_immediate_data.attr,
541 &dev_attr_fnode_initial_r2t.attr,
542 &dev_attr_fnode_data_seq_in_order.attr,
543 &dev_attr_fnode_data_pdu_in_order.attr,
544 &dev_attr_fnode_chap_auth.attr,
545 &dev_attr_fnode_discovery_logout.attr,
546 &dev_attr_fnode_bidi_chap.attr,
547 &dev_attr_fnode_discovery_auth_optional.attr,
548 &dev_attr_fnode_erl.attr,
549 &dev_attr_fnode_first_burst_len.attr,
550 &dev_attr_fnode_def_time2wait.attr,
551 &dev_attr_fnode_def_time2retain.attr,
552 &dev_attr_fnode_max_outstanding_r2t.attr,
553 &dev_attr_fnode_isid.attr,
554 &dev_attr_fnode_tsid.attr,
555 &dev_attr_fnode_max_burst_len.attr,
556 &dev_attr_fnode_def_taskmgmt_tmo.attr,
557 &dev_attr_fnode_targetalias.attr,
558 &dev_attr_fnode_targetname.attr,
559 &dev_attr_fnode_tpgt.attr,
560 &dev_attr_fnode_discovery_parent_idx.attr,
561 &dev_attr_fnode_discovery_parent_type.attr,
562 &dev_attr_fnode_chap_in_idx.attr,
563 &dev_attr_fnode_chap_out_idx.attr,
564 &dev_attr_fnode_username.attr,
565 &dev_attr_fnode_username_in.attr,
566 &dev_attr_fnode_password.attr,
567 &dev_attr_fnode_password_in.attr,
568 &dev_attr_fnode_is_boot_target.attr,
569 NULL,
570};
571
572static umode_t iscsi_flashnode_sess_attr_is_visible(struct kobject *kobj,
573 struct attribute *attr,
574 int i)
575{
576 struct device *dev = container_of(kobj, struct device, kobj);
577 struct iscsi_bus_flash_session *fnode_sess =
578 iscsi_dev_to_flash_session(dev);
579 struct iscsi_transport *t = fnode_sess->transport;
580 int param;
581
582 if (attr == &dev_attr_fnode_auto_snd_tgt_disable.attr) {
583 param = ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE;
584 } else if (attr == &dev_attr_fnode_discovery_session.attr) {
585 param = ISCSI_FLASHNODE_DISCOVERY_SESS;
586 } else if (attr == &dev_attr_fnode_portal_type.attr) {
587 param = ISCSI_FLASHNODE_PORTAL_TYPE;
588 } else if (attr == &dev_attr_fnode_entry_enable.attr) {
589 param = ISCSI_FLASHNODE_ENTRY_EN;
590 } else if (attr == &dev_attr_fnode_immediate_data.attr) {
591 param = ISCSI_FLASHNODE_IMM_DATA_EN;
592 } else if (attr == &dev_attr_fnode_initial_r2t.attr) {
593 param = ISCSI_FLASHNODE_INITIAL_R2T_EN;
594 } else if (attr == &dev_attr_fnode_data_seq_in_order.attr) {
595 param = ISCSI_FLASHNODE_DATASEQ_INORDER;
596 } else if (attr == &dev_attr_fnode_data_pdu_in_order.attr) {
597 param = ISCSI_FLASHNODE_PDU_INORDER;
598 } else if (attr == &dev_attr_fnode_chap_auth.attr) {
599 param = ISCSI_FLASHNODE_CHAP_AUTH_EN;
600 } else if (attr == &dev_attr_fnode_discovery_logout.attr) {
601 param = ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN;
602 } else if (attr == &dev_attr_fnode_bidi_chap.attr) {
603 param = ISCSI_FLASHNODE_BIDI_CHAP_EN;
604 } else if (attr == &dev_attr_fnode_discovery_auth_optional.attr) {
605 param = ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL;
606 } else if (attr == &dev_attr_fnode_erl.attr) {
607 param = ISCSI_FLASHNODE_ERL;
608 } else if (attr == &dev_attr_fnode_first_burst_len.attr) {
609 param = ISCSI_FLASHNODE_FIRST_BURST;
610 } else if (attr == &dev_attr_fnode_def_time2wait.attr) {
611 param = ISCSI_FLASHNODE_DEF_TIME2WAIT;
612 } else if (attr == &dev_attr_fnode_def_time2retain.attr) {
613 param = ISCSI_FLASHNODE_DEF_TIME2RETAIN;
614 } else if (attr == &dev_attr_fnode_max_outstanding_r2t.attr) {
615 param = ISCSI_FLASHNODE_MAX_R2T;
616 } else if (attr == &dev_attr_fnode_isid.attr) {
617 param = ISCSI_FLASHNODE_ISID;
618 } else if (attr == &dev_attr_fnode_tsid.attr) {
619 param = ISCSI_FLASHNODE_TSID;
620 } else if (attr == &dev_attr_fnode_max_burst_len.attr) {
621 param = ISCSI_FLASHNODE_MAX_BURST;
622 } else if (attr == &dev_attr_fnode_def_taskmgmt_tmo.attr) {
623 param = ISCSI_FLASHNODE_DEF_TASKMGMT_TMO;
624 } else if (attr == &dev_attr_fnode_targetalias.attr) {
625 param = ISCSI_FLASHNODE_ALIAS;
626 } else if (attr == &dev_attr_fnode_targetname.attr) {
627 param = ISCSI_FLASHNODE_NAME;
628 } else if (attr == &dev_attr_fnode_tpgt.attr) {
629 param = ISCSI_FLASHNODE_TPGT;
630 } else if (attr == &dev_attr_fnode_discovery_parent_idx.attr) {
631 param = ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX;
632 } else if (attr == &dev_attr_fnode_discovery_parent_type.attr) {
633 param = ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE;
634 } else if (attr == &dev_attr_fnode_chap_in_idx.attr) {
635 param = ISCSI_FLASHNODE_CHAP_IN_IDX;
636 } else if (attr == &dev_attr_fnode_chap_out_idx.attr) {
637 param = ISCSI_FLASHNODE_CHAP_OUT_IDX;
638 } else if (attr == &dev_attr_fnode_username.attr) {
639 param = ISCSI_FLASHNODE_USERNAME;
640 } else if (attr == &dev_attr_fnode_username_in.attr) {
641 param = ISCSI_FLASHNODE_USERNAME_IN;
642 } else if (attr == &dev_attr_fnode_password.attr) {
643 param = ISCSI_FLASHNODE_PASSWORD;
644 } else if (attr == &dev_attr_fnode_password_in.attr) {
645 param = ISCSI_FLASHNODE_PASSWORD_IN;
646 } else if (attr == &dev_attr_fnode_is_boot_target.attr) {
647 param = ISCSI_FLASHNODE_IS_BOOT_TGT;
648 } else {
649 WARN_ONCE(1, "Invalid flashnode session attr");
650 return 0;
651 }
652
653 return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
654}
655
656static struct attribute_group iscsi_flashnode_sess_attr_group = {
657 .attrs = iscsi_flashnode_sess_attrs,
658 .is_visible = iscsi_flashnode_sess_attr_is_visible,
659};
660
661static const struct attribute_group *iscsi_flashnode_sess_attr_groups[] = {
662 &iscsi_flashnode_sess_attr_group,
663 NULL,
664};
665
666static void iscsi_flashnode_sess_release(struct device *dev)
667{
668 struct iscsi_bus_flash_session *fnode_sess =
669 iscsi_dev_to_flash_session(dev);
670
671 kfree(fnode_sess->targetname);
672 kfree(fnode_sess->targetalias);
673 kfree(fnode_sess->portal_type);
674 kfree(fnode_sess);
675}
676
677struct device_type iscsi_flashnode_sess_dev_type = {
678 .name = "iscsi_flashnode_sess_dev_type",
679 .groups = iscsi_flashnode_sess_attr_groups,
680 .release = iscsi_flashnode_sess_release,
681};
682
683/* flash node connection attrs show */
684#define iscsi_flashnode_conn_attr_show(type, name, param) \
685static ssize_t \
686show_##type##_##name(struct device *dev, struct device_attribute *attr, \
687 char *buf) \
688{ \
689 struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);\
690 struct iscsi_bus_flash_session *fnode_sess = \
691 iscsi_flash_conn_to_flash_session(fnode_conn);\
692 struct iscsi_transport *t = fnode_conn->transport; \
693 return t->get_flashnode_param(fnode_sess, param, buf); \
694} \
695
696
697#define iscsi_flashnode_conn_attr(type, name, param) \
698 iscsi_flashnode_conn_attr_show(type, name, param) \
699static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
700 show_##type##_##name, NULL);
701
702/* Flash node connection attributes */
703
704iscsi_flashnode_conn_attr(fnode, is_fw_assigned_ipv6,
705 ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6);
706iscsi_flashnode_conn_attr(fnode, header_digest, ISCSI_FLASHNODE_HDR_DGST_EN);
707iscsi_flashnode_conn_attr(fnode, data_digest, ISCSI_FLASHNODE_DATA_DGST_EN);
708iscsi_flashnode_conn_attr(fnode, snack_req, ISCSI_FLASHNODE_SNACK_REQ_EN);
709iscsi_flashnode_conn_attr(fnode, tcp_timestamp_stat,
710 ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT);
711iscsi_flashnode_conn_attr(fnode, tcp_nagle_disable,
712 ISCSI_FLASHNODE_TCP_NAGLE_DISABLE);
713iscsi_flashnode_conn_attr(fnode, tcp_wsf_disable,
714 ISCSI_FLASHNODE_TCP_WSF_DISABLE);
715iscsi_flashnode_conn_attr(fnode, tcp_timer_scale,
716 ISCSI_FLASHNODE_TCP_TIMER_SCALE);
717iscsi_flashnode_conn_attr(fnode, tcp_timestamp_enable,
718 ISCSI_FLASHNODE_TCP_TIMESTAMP_EN);
719iscsi_flashnode_conn_attr(fnode, fragment_disable,
720 ISCSI_FLASHNODE_IP_FRAG_DISABLE);
721iscsi_flashnode_conn_attr(fnode, keepalive_tmo, ISCSI_FLASHNODE_KEEPALIVE_TMO);
722iscsi_flashnode_conn_attr(fnode, port, ISCSI_FLASHNODE_PORT);
723iscsi_flashnode_conn_attr(fnode, ipaddress, ISCSI_FLASHNODE_IPADDR);
724iscsi_flashnode_conn_attr(fnode, max_recv_dlength,
725 ISCSI_FLASHNODE_MAX_RECV_DLENGTH);
726iscsi_flashnode_conn_attr(fnode, max_xmit_dlength,
727 ISCSI_FLASHNODE_MAX_XMIT_DLENGTH);
728iscsi_flashnode_conn_attr(fnode, local_port, ISCSI_FLASHNODE_LOCAL_PORT);
729iscsi_flashnode_conn_attr(fnode, ipv4_tos, ISCSI_FLASHNODE_IPV4_TOS);
730iscsi_flashnode_conn_attr(fnode, ipv6_traffic_class, ISCSI_FLASHNODE_IPV6_TC);
731iscsi_flashnode_conn_attr(fnode, ipv6_flow_label,
732 ISCSI_FLASHNODE_IPV6_FLOW_LABEL);
733iscsi_flashnode_conn_attr(fnode, redirect_ipaddr,
734 ISCSI_FLASHNODE_REDIRECT_IPADDR);
735iscsi_flashnode_conn_attr(fnode, max_segment_size,
736 ISCSI_FLASHNODE_MAX_SEGMENT_SIZE);
737iscsi_flashnode_conn_attr(fnode, link_local_ipv6,
738 ISCSI_FLASHNODE_LINK_LOCAL_IPV6);
739iscsi_flashnode_conn_attr(fnode, tcp_xmit_wsf, ISCSI_FLASHNODE_TCP_XMIT_WSF);
740iscsi_flashnode_conn_attr(fnode, tcp_recv_wsf, ISCSI_FLASHNODE_TCP_RECV_WSF);
741iscsi_flashnode_conn_attr(fnode, statsn, ISCSI_FLASHNODE_STATSN);
742iscsi_flashnode_conn_attr(fnode, exp_statsn, ISCSI_FLASHNODE_EXP_STATSN);
743
744static struct attribute *iscsi_flashnode_conn_attrs[] = {
745 &dev_attr_fnode_is_fw_assigned_ipv6.attr,
746 &dev_attr_fnode_header_digest.attr,
747 &dev_attr_fnode_data_digest.attr,
748 &dev_attr_fnode_snack_req.attr,
749 &dev_attr_fnode_tcp_timestamp_stat.attr,
750 &dev_attr_fnode_tcp_nagle_disable.attr,
751 &dev_attr_fnode_tcp_wsf_disable.attr,
752 &dev_attr_fnode_tcp_timer_scale.attr,
753 &dev_attr_fnode_tcp_timestamp_enable.attr,
754 &dev_attr_fnode_fragment_disable.attr,
755 &dev_attr_fnode_max_recv_dlength.attr,
756 &dev_attr_fnode_max_xmit_dlength.attr,
757 &dev_attr_fnode_keepalive_tmo.attr,
758 &dev_attr_fnode_port.attr,
759 &dev_attr_fnode_ipaddress.attr,
760 &dev_attr_fnode_redirect_ipaddr.attr,
761 &dev_attr_fnode_max_segment_size.attr,
762 &dev_attr_fnode_local_port.attr,
763 &dev_attr_fnode_ipv4_tos.attr,
764 &dev_attr_fnode_ipv6_traffic_class.attr,
765 &dev_attr_fnode_ipv6_flow_label.attr,
766 &dev_attr_fnode_link_local_ipv6.attr,
767 &dev_attr_fnode_tcp_xmit_wsf.attr,
768 &dev_attr_fnode_tcp_recv_wsf.attr,
769 &dev_attr_fnode_statsn.attr,
770 &dev_attr_fnode_exp_statsn.attr,
771 NULL,
772};
773
774static umode_t iscsi_flashnode_conn_attr_is_visible(struct kobject *kobj,
775 struct attribute *attr,
776 int i)
777{
778 struct device *dev = container_of(kobj, struct device, kobj);
779 struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
780 struct iscsi_transport *t = fnode_conn->transport;
781 int param;
782
783 if (attr == &dev_attr_fnode_is_fw_assigned_ipv6.attr) {
784 param = ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6;
785 } else if (attr == &dev_attr_fnode_header_digest.attr) {
786 param = ISCSI_FLASHNODE_HDR_DGST_EN;
787 } else if (attr == &dev_attr_fnode_data_digest.attr) {
788 param = ISCSI_FLASHNODE_DATA_DGST_EN;
789 } else if (attr == &dev_attr_fnode_snack_req.attr) {
790 param = ISCSI_FLASHNODE_SNACK_REQ_EN;
791 } else if (attr == &dev_attr_fnode_tcp_timestamp_stat.attr) {
792 param = ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT;
793 } else if (attr == &dev_attr_fnode_tcp_nagle_disable.attr) {
794 param = ISCSI_FLASHNODE_TCP_NAGLE_DISABLE;
795 } else if (attr == &dev_attr_fnode_tcp_wsf_disable.attr) {
796 param = ISCSI_FLASHNODE_TCP_WSF_DISABLE;
797 } else if (attr == &dev_attr_fnode_tcp_timer_scale.attr) {
798 param = ISCSI_FLASHNODE_TCP_TIMER_SCALE;
799 } else if (attr == &dev_attr_fnode_tcp_timestamp_enable.attr) {
800 param = ISCSI_FLASHNODE_TCP_TIMESTAMP_EN;
801 } else if (attr == &dev_attr_fnode_fragment_disable.attr) {
802 param = ISCSI_FLASHNODE_IP_FRAG_DISABLE;
803 } else if (attr == &dev_attr_fnode_max_recv_dlength.attr) {
804 param = ISCSI_FLASHNODE_MAX_RECV_DLENGTH;
805 } else if (attr == &dev_attr_fnode_max_xmit_dlength.attr) {
806 param = ISCSI_FLASHNODE_MAX_XMIT_DLENGTH;
807 } else if (attr == &dev_attr_fnode_keepalive_tmo.attr) {
808 param = ISCSI_FLASHNODE_KEEPALIVE_TMO;
809 } else if (attr == &dev_attr_fnode_port.attr) {
810 param = ISCSI_FLASHNODE_PORT;
811 } else if (attr == &dev_attr_fnode_ipaddress.attr) {
812 param = ISCSI_FLASHNODE_IPADDR;
813 } else if (attr == &dev_attr_fnode_redirect_ipaddr.attr) {
814 param = ISCSI_FLASHNODE_REDIRECT_IPADDR;
815 } else if (attr == &dev_attr_fnode_max_segment_size.attr) {
816 param = ISCSI_FLASHNODE_MAX_SEGMENT_SIZE;
817 } else if (attr == &dev_attr_fnode_local_port.attr) {
818 param = ISCSI_FLASHNODE_LOCAL_PORT;
819 } else if (attr == &dev_attr_fnode_ipv4_tos.attr) {
820 param = ISCSI_FLASHNODE_IPV4_TOS;
821 } else if (attr == &dev_attr_fnode_ipv6_traffic_class.attr) {
822 param = ISCSI_FLASHNODE_IPV6_TC;
823 } else if (attr == &dev_attr_fnode_ipv6_flow_label.attr) {
824 param = ISCSI_FLASHNODE_IPV6_FLOW_LABEL;
825 } else if (attr == &dev_attr_fnode_link_local_ipv6.attr) {
826 param = ISCSI_FLASHNODE_LINK_LOCAL_IPV6;
827 } else if (attr == &dev_attr_fnode_tcp_xmit_wsf.attr) {
828 param = ISCSI_FLASHNODE_TCP_XMIT_WSF;
829 } else if (attr == &dev_attr_fnode_tcp_recv_wsf.attr) {
830 param = ISCSI_FLASHNODE_TCP_RECV_WSF;
831 } else if (attr == &dev_attr_fnode_statsn.attr) {
832 param = ISCSI_FLASHNODE_STATSN;
833 } else if (attr == &dev_attr_fnode_exp_statsn.attr) {
834 param = ISCSI_FLASHNODE_EXP_STATSN;
835 } else {
836 WARN_ONCE(1, "Invalid flashnode connection attr");
837 return 0;
838 }
839
840 return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
841}
842
843static struct attribute_group iscsi_flashnode_conn_attr_group = {
844 .attrs = iscsi_flashnode_conn_attrs,
845 .is_visible = iscsi_flashnode_conn_attr_is_visible,
846};
847
848static const struct attribute_group *iscsi_flashnode_conn_attr_groups[] = {
849 &iscsi_flashnode_conn_attr_group,
850 NULL,
851};
852
853static void iscsi_flashnode_conn_release(struct device *dev)
854{
855 struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
856
857 kfree(fnode_conn->ipaddress);
858 kfree(fnode_conn->redirect_ipaddr);
859 kfree(fnode_conn->link_local_ipv6_addr);
860 kfree(fnode_conn);
861}
862
863struct device_type iscsi_flashnode_conn_dev_type = {
864 .name = "iscsi_flashnode_conn_dev_type",
865 .groups = iscsi_flashnode_conn_attr_groups,
866 .release = iscsi_flashnode_conn_release,
867};
868
869struct bus_type iscsi_flashnode_bus;
870
871int iscsi_flashnode_bus_match(struct device *dev,
872 struct device_driver *drv)
873{
874 if (dev->bus == &iscsi_flashnode_bus)
875 return 1;
876 return 0;
877}
878EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match);
879
880struct bus_type iscsi_flashnode_bus = {
881 .name = "iscsi_flashnode",
882 .match = &iscsi_flashnode_bus_match,
883};
884
885/**
886 * iscsi_create_flashnode_sess - Add flashnode session entry in sysfs
887 * @shost: pointer to host data
888 * @index: index of flashnode to add in sysfs
889 * @transport: pointer to transport data
890 * @dd_size: total size to allocate
891 *
892 * Adds a sysfs entry for the flashnode session attributes
893 *
894 * Returns:
895 * pointer to allocated flashnode sess on sucess
896 * %NULL on failure
897 */
898struct iscsi_bus_flash_session *
899iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index,
900 struct iscsi_transport *transport,
901 int dd_size)
902{
903 struct iscsi_bus_flash_session *fnode_sess;
904 int err;
905
906 fnode_sess = kzalloc(sizeof(*fnode_sess) + dd_size, GFP_KERNEL);
907 if (!fnode_sess)
908 return NULL;
909
910 fnode_sess->transport = transport;
911 fnode_sess->target_id = index;
912 fnode_sess->dev.type = &iscsi_flashnode_sess_dev_type;
913 fnode_sess->dev.bus = &iscsi_flashnode_bus;
914 fnode_sess->dev.parent = &shost->shost_gendev;
915 dev_set_name(&fnode_sess->dev, "flashnode_sess-%u:%u",
916 shost->host_no, index);
917
918 err = device_register(&fnode_sess->dev);
919 if (err)
920 goto free_fnode_sess;
921
922 if (dd_size)
923 fnode_sess->dd_data = &fnode_sess[1];
924
925 return fnode_sess;
926
927free_fnode_sess:
928 kfree(fnode_sess);
929 return NULL;
930}
931EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess);
932
933/**
934 * iscsi_create_flashnode_conn - Add flashnode conn entry in sysfs
935 * @shost: pointer to host data
936 * @fnode_sess: pointer to the parent flashnode session entry
937 * @transport: pointer to transport data
938 * @dd_size: total size to allocate
939 *
940 * Adds a sysfs entry for the flashnode connection attributes
941 *
942 * Returns:
943 * pointer to allocated flashnode conn on success
944 * %NULL on failure
945 */
946struct iscsi_bus_flash_conn *
947iscsi_create_flashnode_conn(struct Scsi_Host *shost,
948 struct iscsi_bus_flash_session *fnode_sess,
949 struct iscsi_transport *transport,
950 int dd_size)
951{
952 struct iscsi_bus_flash_conn *fnode_conn;
953 int err;
954
955 fnode_conn = kzalloc(sizeof(*fnode_conn) + dd_size, GFP_KERNEL);
956 if (!fnode_conn)
957 return NULL;
958
959 fnode_conn->transport = transport;
960 fnode_conn->dev.type = &iscsi_flashnode_conn_dev_type;
961 fnode_conn->dev.bus = &iscsi_flashnode_bus;
962 fnode_conn->dev.parent = &fnode_sess->dev;
963 dev_set_name(&fnode_conn->dev, "flashnode_conn-%u:%u:0",
964 shost->host_no, fnode_sess->target_id);
965
966 err = device_register(&fnode_conn->dev);
967 if (err)
968 goto free_fnode_conn;
969
970 if (dd_size)
971 fnode_conn->dd_data = &fnode_conn[1];
972
973 return fnode_conn;
974
975free_fnode_conn:
976 kfree(fnode_conn);
977 return NULL;
978}
979EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn);
980
981/**
982 * iscsi_is_flashnode_conn_dev - verify passed device is to be flashnode conn
983 * @dev: device to verify
984 * @data: pointer to data containing value to use for verification
985 *
986 * Verifies if the passed device is flashnode conn device
987 *
988 * Returns:
989 * 1 on success
990 * 0 on failure
991 */
992int iscsi_is_flashnode_conn_dev(struct device *dev, void *data)
993{
994 return dev->bus == &iscsi_flashnode_bus;
995}
996EXPORT_SYMBOL_GPL(iscsi_is_flashnode_conn_dev);
997
998static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn)
999{
1000 device_unregister(&fnode_conn->dev);
1001 return 0;
1002}
1003
1004static int flashnode_match_index(struct device *dev, void *data)
1005{
1006 struct iscsi_bus_flash_session *fnode_sess = NULL;
1007 int ret = 0;
1008
1009 if (!iscsi_flashnode_bus_match(dev, NULL))
1010 goto exit_match_index;
1011
1012 fnode_sess = iscsi_dev_to_flash_session(dev);
1013 ret = (fnode_sess->target_id == *((int *)data)) ? 1 : 0;
1014
1015exit_match_index:
1016 return ret;
1017}
1018
1019/**
1020 * iscsi_get_flashnode_by_index -finds flashnode session entry by index
1021 * @shost: pointer to host data
1022 * @data: pointer to data containing value to use for comparison
1023 * @fn: function pointer that does actual comparison
1024 *
1025 * Finds the flashnode session object for the passed index
1026 *
1027 * Returns:
1028 * pointer to found flashnode session object on success
1029 * %NULL on failure
1030 */
1031static struct iscsi_bus_flash_session *
1032iscsi_get_flashnode_by_index(struct Scsi_Host *shost, void *data,
1033 int (*fn)(struct device *dev, void *data))
1034{
1035 struct iscsi_bus_flash_session *fnode_sess = NULL;
1036 struct device *dev;
1037
1038 dev = device_find_child(&shost->shost_gendev, data, fn);
1039 if (dev)
1040 fnode_sess = iscsi_dev_to_flash_session(dev);
1041
1042 return fnode_sess;
1043}
1044
1045/**
1046 * iscsi_find_flashnode_sess - finds flashnode session entry
1047 * @shost: pointer to host data
1048 * @data: pointer to data containing value to use for comparison
1049 * @fn: function pointer that does actual comparison
1050 *
1051 * Finds the flashnode session object comparing the data passed using logic
1052 * defined in passed function pointer
1053 *
1054 * Returns:
1055 * pointer to found flashnode session device object on success
1056 * %NULL on failure
1057 */
1058struct device *
1059iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
1060 int (*fn)(struct device *dev, void *data))
1061{
1062 struct device *dev;
1063
1064 dev = device_find_child(&shost->shost_gendev, data, fn);
1065 return dev;
1066}
1067EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
1068
1069/**
1070 * iscsi_find_flashnode_conn - finds flashnode connection entry
1071 * @fnode_sess: pointer to parent flashnode session entry
1072 * @data: pointer to data containing value to use for comparison
1073 * @fn: function pointer that does actual comparison
1074 *
1075 * Finds the flashnode connection object comparing the data passed using logic
1076 * defined in passed function pointer
1077 *
1078 * Returns:
1079 * pointer to found flashnode connection device object on success
1080 * %NULL on failure
1081 */
1082struct device *
1083iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
1084 void *data,
1085 int (*fn)(struct device *dev, void *data))
1086{
1087 struct device *dev;
1088
1089 dev = device_find_child(&fnode_sess->dev, data, fn);
1090 return dev;
1091}
1092EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
1093
1094static int iscsi_iter_destroy_flashnode_conn_fn(struct device *dev, void *data)
1095{
1096 if (!iscsi_is_flashnode_conn_dev(dev, NULL))
1097 return 0;
1098
1099 return iscsi_destroy_flashnode_conn(iscsi_dev_to_flash_conn(dev));
1100}
1101
1102/**
1103 * iscsi_destroy_flashnode_sess - destory flashnode session entry
1104 * @fnode_sess: pointer to flashnode session entry to be destroyed
1105 *
1106 * Deletes the flashnode session entry and all children flashnode connection
1107 * entries from sysfs
1108 */
1109void iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess)
1110{
1111 int err;
1112
1113 err = device_for_each_child(&fnode_sess->dev, NULL,
1114 iscsi_iter_destroy_flashnode_conn_fn);
1115 if (err)
1116 pr_err("Could not delete all connections for %s. Error %d.\n",
1117 fnode_sess->dev.kobj.name, err);
1118
1119 device_unregister(&fnode_sess->dev);
1120}
1121EXPORT_SYMBOL_GPL(iscsi_destroy_flashnode_sess);
1122
1123static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data)
1124{
1125 if (!iscsi_flashnode_bus_match(dev, NULL))
1126 return 0;
1127
1128 iscsi_destroy_flashnode_sess(iscsi_dev_to_flash_session(dev));
1129 return 0;
1130}
1131
1132/**
1133 * iscsi_destroy_all_flashnode - destory all flashnode session entries
1134 * @shost: pointer to host data
1135 *
1136 * Destroys all the flashnode session entries and all corresponding children
1137 * flashnode connection entries from sysfs
1138 */
1139void iscsi_destroy_all_flashnode(struct Scsi_Host *shost)
1140{
1141 device_for_each_child(&shost->shost_gendev, NULL,
1142 iscsi_iter_destroy_flashnode_fn);
1143}
1144EXPORT_SYMBOL_GPL(iscsi_destroy_all_flashnode);
1145
1146/*
463 * BSG support 1147 * BSG support
464 */ 1148 */
465/** 1149/**
@@ -2092,6 +2776,294 @@ static int iscsi_delete_chap(struct iscsi_transport *transport,
2092 return err; 2776 return err;
2093} 2777}
2094 2778
2779static const struct {
2780 enum iscsi_discovery_parent_type value;
2781 char *name;
2782} iscsi_discovery_parent_names[] = {
2783 {ISCSI_DISC_PARENT_UNKNOWN, "Unknown" },
2784 {ISCSI_DISC_PARENT_SENDTGT, "Sendtarget" },
2785 {ISCSI_DISC_PARENT_ISNS, "isns" },
2786};
2787
2788char *iscsi_get_discovery_parent_name(int parent_type)
2789{
2790 int i;
2791 char *state = "Unknown!";
2792
2793 for (i = 0; i < ARRAY_SIZE(iscsi_discovery_parent_names); i++) {
2794 if (iscsi_discovery_parent_names[i].value & parent_type) {
2795 state = iscsi_discovery_parent_names[i].name;
2796 break;
2797 }
2798 }
2799 return state;
2800}
2801EXPORT_SYMBOL_GPL(iscsi_get_discovery_parent_name);
2802
2803static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
2804 struct iscsi_uevent *ev, uint32_t len)
2805{
2806 char *data = (char *)ev + sizeof(*ev);
2807 struct Scsi_Host *shost;
2808 struct iscsi_bus_flash_session *fnode_sess;
2809 struct iscsi_bus_flash_conn *fnode_conn;
2810 struct device *dev;
2811 uint32_t *idx;
2812 int err = 0;
2813
2814 if (!transport->set_flashnode_param) {
2815 err = -ENOSYS;
2816 goto exit_set_fnode;
2817 }
2818
2819 shost = scsi_host_lookup(ev->u.set_flashnode.host_no);
2820 if (!shost) {
2821 pr_err("%s could not find host no %u\n",
2822 __func__, ev->u.set_flashnode.host_no);
2823 err = -ENODEV;
2824 goto put_host;
2825 }
2826
2827 idx = &ev->u.set_flashnode.flashnode_idx;
2828 fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
2829 flashnode_match_index);
2830 if (!fnode_sess) {
2831 pr_err("%s could not find flashnode %u for host no %u\n",
2832 __func__, *idx, ev->u.set_flashnode.host_no);
2833 err = -ENODEV;
2834 goto put_host;
2835 }
2836
2837 dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
2838 iscsi_is_flashnode_conn_dev);
2839 if (!dev) {
2840 err = -ENODEV;
2841 goto put_host;
2842 }
2843
2844 fnode_conn = iscsi_dev_to_flash_conn(dev);
2845 err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
2846
2847put_host:
2848 scsi_host_put(shost);
2849
2850exit_set_fnode:
2851 return err;
2852}
2853
2854static int iscsi_new_flashnode(struct iscsi_transport *transport,
2855 struct iscsi_uevent *ev, uint32_t len)
2856{
2857 char *data = (char *)ev + sizeof(*ev);
2858 struct Scsi_Host *shost;
2859 int index;
2860 int err = 0;
2861
2862 if (!transport->new_flashnode) {
2863 err = -ENOSYS;
2864 goto exit_new_fnode;
2865 }
2866
2867 shost = scsi_host_lookup(ev->u.new_flashnode.host_no);
2868 if (!shost) {
2869 pr_err("%s could not find host no %u\n",
2870 __func__, ev->u.new_flashnode.host_no);
2871 err = -ENODEV;
2872 goto put_host;
2873 }
2874
2875 index = transport->new_flashnode(shost, data, len);
2876
2877 if (index >= 0)
2878 ev->r.new_flashnode_ret.flashnode_idx = index;
2879 else
2880 err = -EIO;
2881
2882put_host:
2883 scsi_host_put(shost);
2884
2885exit_new_fnode:
2886 return err;
2887}
2888
2889static int iscsi_del_flashnode(struct iscsi_transport *transport,
2890 struct iscsi_uevent *ev)
2891{
2892 struct Scsi_Host *shost;
2893 struct iscsi_bus_flash_session *fnode_sess;
2894 uint32_t *idx;
2895 int err = 0;
2896
2897 if (!transport->del_flashnode) {
2898 err = -ENOSYS;
2899 goto exit_del_fnode;
2900 }
2901
2902 shost = scsi_host_lookup(ev->u.del_flashnode.host_no);
2903 if (!shost) {
2904 pr_err("%s could not find host no %u\n",
2905 __func__, ev->u.del_flashnode.host_no);
2906 err = -ENODEV;
2907 goto put_host;
2908 }
2909
2910 idx = &ev->u.del_flashnode.flashnode_idx;
2911 fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
2912 flashnode_match_index);
2913 if (!fnode_sess) {
2914 pr_err("%s could not find flashnode %u for host no %u\n",
2915 __func__, *idx, ev->u.del_flashnode.host_no);
2916 err = -ENODEV;
2917 goto put_host;
2918 }
2919
2920 err = transport->del_flashnode(fnode_sess);
2921
2922put_host:
2923 scsi_host_put(shost);
2924
2925exit_del_fnode:
2926 return err;
2927}
2928
2929static int iscsi_login_flashnode(struct iscsi_transport *transport,
2930 struct iscsi_uevent *ev)
2931{
2932 struct Scsi_Host *shost;
2933 struct iscsi_bus_flash_session *fnode_sess;
2934 struct iscsi_bus_flash_conn *fnode_conn;
2935 struct device *dev;
2936 uint32_t *idx;
2937 int err = 0;
2938
2939 if (!transport->login_flashnode) {
2940 err = -ENOSYS;
2941 goto exit_login_fnode;
2942 }
2943
2944 shost = scsi_host_lookup(ev->u.login_flashnode.host_no);
2945 if (!shost) {
2946 pr_err("%s could not find host no %u\n",
2947 __func__, ev->u.login_flashnode.host_no);
2948 err = -ENODEV;
2949 goto put_host;
2950 }
2951
2952 idx = &ev->u.login_flashnode.flashnode_idx;
2953 fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
2954 flashnode_match_index);
2955 if (!fnode_sess) {
2956 pr_err("%s could not find flashnode %u for host no %u\n",
2957 __func__, *idx, ev->u.login_flashnode.host_no);
2958 err = -ENODEV;
2959 goto put_host;
2960 }
2961
2962 dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
2963 iscsi_is_flashnode_conn_dev);
2964 if (!dev) {
2965 err = -ENODEV;
2966 goto put_host;
2967 }
2968
2969 fnode_conn = iscsi_dev_to_flash_conn(dev);
2970 err = transport->login_flashnode(fnode_sess, fnode_conn);
2971
2972put_host:
2973 scsi_host_put(shost);
2974
2975exit_login_fnode:
2976 return err;
2977}
2978
2979static int iscsi_logout_flashnode(struct iscsi_transport *transport,
2980 struct iscsi_uevent *ev)
2981{
2982 struct Scsi_Host *shost;
2983 struct iscsi_bus_flash_session *fnode_sess;
2984 struct iscsi_bus_flash_conn *fnode_conn;
2985 struct device *dev;
2986 uint32_t *idx;
2987 int err = 0;
2988
2989 if (!transport->logout_flashnode) {
2990 err = -ENOSYS;
2991 goto exit_logout_fnode;
2992 }
2993
2994 shost = scsi_host_lookup(ev->u.logout_flashnode.host_no);
2995 if (!shost) {
2996 pr_err("%s could not find host no %u\n",
2997 __func__, ev->u.logout_flashnode.host_no);
2998 err = -ENODEV;
2999 goto put_host;
3000 }
3001
3002 idx = &ev->u.logout_flashnode.flashnode_idx;
3003 fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
3004 flashnode_match_index);
3005 if (!fnode_sess) {
3006 pr_err("%s could not find flashnode %u for host no %u\n",
3007 __func__, *idx, ev->u.logout_flashnode.host_no);
3008 err = -ENODEV;
3009 goto put_host;
3010 }
3011
3012 dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
3013 iscsi_is_flashnode_conn_dev);
3014 if (!dev) {
3015 err = -ENODEV;
3016 goto put_host;
3017 }
3018
3019 fnode_conn = iscsi_dev_to_flash_conn(dev);
3020
3021 err = transport->logout_flashnode(fnode_sess, fnode_conn);
3022
3023put_host:
3024 scsi_host_put(shost);
3025
3026exit_logout_fnode:
3027 return err;
3028}
3029
3030static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
3031 struct iscsi_uevent *ev)
3032{
3033 struct Scsi_Host *shost;
3034 struct iscsi_cls_session *session;
3035 int err = 0;
3036
3037 if (!transport->logout_flashnode_sid) {
3038 err = -ENOSYS;
3039 goto exit_logout_sid;
3040 }
3041
3042 shost = scsi_host_lookup(ev->u.logout_flashnode_sid.host_no);
3043 if (!shost) {
3044 pr_err("%s could not find host no %u\n",
3045 __func__, ev->u.logout_flashnode.host_no);
3046 err = -ENODEV;
3047 goto put_host;
3048 }
3049
3050 session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid);
3051 if (!session) {
3052 pr_err("%s could not find session id %u\n",
3053 __func__, ev->u.logout_flashnode_sid.sid);
3054 err = -EINVAL;
3055 goto put_host;
3056 }
3057
3058 err = transport->logout_flashnode_sid(session);
3059
3060put_host:
3061 scsi_host_put(shost);
3062
3063exit_logout_sid:
3064 return err;
3065}
3066
2095static int 3067static int
2096iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) 3068iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
2097{ 3069{
@@ -2246,6 +3218,27 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
2246 case ISCSI_UEVENT_DELETE_CHAP: 3218 case ISCSI_UEVENT_DELETE_CHAP:
2247 err = iscsi_delete_chap(transport, ev); 3219 err = iscsi_delete_chap(transport, ev);
2248 break; 3220 break;
3221 case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
3222 err = iscsi_set_flashnode_param(transport, ev,
3223 nlmsg_attrlen(nlh,
3224 sizeof(*ev)));
3225 break;
3226 case ISCSI_UEVENT_NEW_FLASHNODE:
3227 err = iscsi_new_flashnode(transport, ev,
3228 nlmsg_attrlen(nlh, sizeof(*ev)));
3229 break;
3230 case ISCSI_UEVENT_DEL_FLASHNODE:
3231 err = iscsi_del_flashnode(transport, ev);
3232 break;
3233 case ISCSI_UEVENT_LOGIN_FLASHNODE:
3234 err = iscsi_login_flashnode(transport, ev);
3235 break;
3236 case ISCSI_UEVENT_LOGOUT_FLASHNODE:
3237 err = iscsi_logout_flashnode(transport, ev);
3238 break;
3239 case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID:
3240 err = iscsi_logout_flashnode_sid(transport, ev);
3241 break;
2249 default: 3242 default:
2250 err = -ENOSYS; 3243 err = -ENOSYS;
2251 break; 3244 break;
@@ -2981,10 +3974,14 @@ static __init int iscsi_transport_init(void)
2981 if (err) 3974 if (err)
2982 goto unregister_conn_class; 3975 goto unregister_conn_class;
2983 3976
3977 err = bus_register(&iscsi_flashnode_bus);
3978 if (err)
3979 goto unregister_session_class;
3980
2984 nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg); 3981 nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg);
2985 if (!nls) { 3982 if (!nls) {
2986 err = -ENOBUFS; 3983 err = -ENOBUFS;
2987 goto unregister_session_class; 3984 goto unregister_flashnode_bus;
2988 } 3985 }
2989 3986
2990 iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh"); 3987 iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
@@ -2995,6 +3992,8 @@ static __init int iscsi_transport_init(void)
2995 3992
2996release_nls: 3993release_nls:
2997 netlink_kernel_release(nls); 3994 netlink_kernel_release(nls);
3995unregister_flashnode_bus:
3996 bus_unregister(&iscsi_flashnode_bus);
2998unregister_session_class: 3997unregister_session_class:
2999 transport_class_unregister(&iscsi_session_class); 3998 transport_class_unregister(&iscsi_session_class);
3000unregister_conn_class: 3999unregister_conn_class:
@@ -3014,6 +4013,7 @@ static void __exit iscsi_transport_exit(void)
3014{ 4013{
3015 destroy_workqueue(iscsi_eh_timer_workq); 4014 destroy_workqueue(iscsi_eh_timer_workq);
3016 netlink_kernel_release(nls); 4015 netlink_kernel_release(nls);
4016 bus_unregister(&iscsi_flashnode_bus);
3017 transport_class_unregister(&iscsi_connection_class); 4017 transport_class_unregister(&iscsi_connection_class);
3018 transport_class_unregister(&iscsi_session_class); 4018 transport_class_unregister(&iscsi_session_class);
3019 transport_class_unregister(&iscsi_host_class); 4019 transport_class_unregister(&iscsi_host_class);