diff options
author | FUJITA Tomonori <tomof@acm.org> | 2007-08-31 13:02:27 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:46:58 -0400 |
commit | 7525236d0bc7ad17eb5e0733417896cab745d6c8 (patch) | |
tree | 677fd3adae67e7f100c366955832e266f1515632 | |
parent | 5dc2b89e124251662f580f4ba3c9f6195d1eaff6 (diff) |
[SCSI] fc_transport: add target driver support
This adds minimum target driver support like the srp transport does:
- fc_remote_port_{rolechg,delete} calls
scsi_tgt_it_nexus_{create,destroy} for target drivers.
- add callbacks to notify target drivers of the nexus and tmf
operation results to fc_function_template.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/Kconfig | 7 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 29 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_fc_internal.h | 26 | ||||
-rw-r--r-- | include/scsi/scsi_transport_fc.h | 4 |
4 files changed, 66 insertions, 0 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7877dfdd2322..e1efa0eac4ff 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -272,6 +272,13 @@ config SCSI_FC_ATTRS | |||
272 | each attached FiberChannel device to sysfs, say Y. | 272 | each attached FiberChannel device to sysfs, say Y. |
273 | Otherwise, say N. | 273 | Otherwise, say N. |
274 | 274 | ||
275 | config SCSI_FC_TGT_ATTRS | ||
276 | bool "SCSI target support for FiberChannel Transport Attributes" | ||
277 | depends on SCSI_FC_ATTRS | ||
278 | depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS | ||
279 | help | ||
280 | If you want to use SCSI target mode drivers enable this option. | ||
281 | |||
275 | config SCSI_ISCSI_ATTRS | 282 | config SCSI_ISCSI_ATTRS |
276 | tristate "iSCSI Transport Attributes" | 283 | tristate "iSCSI Transport Attributes" |
277 | depends on SCSI && NET | 284 | depends on SCSI && NET |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index dd97f2652508..8df0f080997f 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <net/netlink.h> | 36 | #include <net/netlink.h> |
37 | #include <scsi/scsi_netlink_fc.h> | 37 | #include <scsi/scsi_netlink_fc.h> |
38 | #include "scsi_priv.h" | 38 | #include "scsi_priv.h" |
39 | #include "scsi_transport_fc_internal.h" | ||
39 | 40 | ||
40 | static int fc_queue_work(struct Scsi_Host *, struct work_struct *); | 41 | static int fc_queue_work(struct Scsi_Host *, struct work_struct *); |
41 | static void fc_vport_sched_delete(struct work_struct *work); | 42 | static void fc_vport_sched_delete(struct work_struct *work); |
@@ -1956,6 +1957,19 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel, | |||
1956 | return 0; | 1957 | return 0; |
1957 | } | 1958 | } |
1958 | 1959 | ||
1960 | static int fc_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, | ||
1961 | int result) | ||
1962 | { | ||
1963 | struct fc_internal *i = to_fc_internal(shost->transportt); | ||
1964 | return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); | ||
1965 | } | ||
1966 | |||
1967 | static int fc_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) | ||
1968 | { | ||
1969 | struct fc_internal *i = to_fc_internal(shost->transportt); | ||
1970 | return i->f->it_nexus_response(shost, nexus, result); | ||
1971 | } | ||
1972 | |||
1959 | struct scsi_transport_template * | 1973 | struct scsi_transport_template * |
1960 | fc_attach_transport(struct fc_function_template *ft) | 1974 | fc_attach_transport(struct fc_function_template *ft) |
1961 | { | 1975 | { |
@@ -1999,6 +2013,10 @@ fc_attach_transport(struct fc_function_template *ft) | |||
1999 | 2013 | ||
2000 | i->t.user_scan = fc_user_scan; | 2014 | i->t.user_scan = fc_user_scan; |
2001 | 2015 | ||
2016 | /* target-mode drivers' functions */ | ||
2017 | i->t.tsk_mgmt_response = fc_tsk_mgmt_response; | ||
2018 | i->t.it_nexus_response = fc_it_nexus_response; | ||
2019 | |||
2002 | /* | 2020 | /* |
2003 | * Setup SCSI Target Attributes. | 2021 | * Setup SCSI Target Attributes. |
2004 | */ | 2022 | */ |
@@ -2756,6 +2774,10 @@ fc_remote_port_delete(struct fc_rport *rport) | |||
2756 | 2774 | ||
2757 | spin_unlock_irqrestore(shost->host_lock, flags); | 2775 | spin_unlock_irqrestore(shost->host_lock, flags); |
2758 | 2776 | ||
2777 | if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR && | ||
2778 | shost->active_mode & MODE_TARGET) | ||
2779 | fc_tgt_it_nexus_destroy(shost, (unsigned long)rport); | ||
2780 | |||
2759 | scsi_target_block(&rport->dev); | 2781 | scsi_target_block(&rport->dev); |
2760 | 2782 | ||
2761 | /* see if we need to kill io faster than waiting for device loss */ | 2783 | /* see if we need to kill io faster than waiting for device loss */ |
@@ -2796,6 +2818,7 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) | |||
2796 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | 2818 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); |
2797 | unsigned long flags; | 2819 | unsigned long flags; |
2798 | int create = 0; | 2820 | int create = 0; |
2821 | int ret; | ||
2799 | 2822 | ||
2800 | spin_lock_irqsave(shost->host_lock, flags); | 2823 | spin_lock_irqsave(shost->host_lock, flags); |
2801 | if (roles & FC_PORT_ROLE_FCP_TARGET) { | 2824 | if (roles & FC_PORT_ROLE_FCP_TARGET) { |
@@ -2804,6 +2827,12 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) | |||
2804 | create = 1; | 2827 | create = 1; |
2805 | } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) | 2828 | } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) |
2806 | create = 1; | 2829 | create = 1; |
2830 | } else if (shost->active_mode & MODE_TARGET) { | ||
2831 | ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport, | ||
2832 | (char *)&rport->node_name); | ||
2833 | if (ret) | ||
2834 | printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n", | ||
2835 | ret); | ||
2807 | } | 2836 | } |
2808 | 2837 | ||
2809 | rport->roles = roles; | 2838 | rport->roles = roles; |
diff --git a/drivers/scsi/scsi_transport_fc_internal.h b/drivers/scsi/scsi_transport_fc_internal.h new file mode 100644 index 000000000000..e7bfbe751c1f --- /dev/null +++ b/drivers/scsi/scsi_transport_fc_internal.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #include <scsi/scsi_tgt.h> | ||
2 | |||
3 | #ifdef CONFIG_SCSI_FC_TGT_ATTRS | ||
4 | static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, | ||
5 | char *initiator) | ||
6 | { | ||
7 | return scsi_tgt_it_nexus_create(shost, itn_id, initiator); | ||
8 | } | ||
9 | |||
10 | static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) | ||
11 | { | ||
12 | return scsi_tgt_it_nexus_destroy(shost, itn_id); | ||
13 | } | ||
14 | #else | ||
15 | static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, | ||
16 | char *initiator) | ||
17 | { | ||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) | ||
22 | { | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | #endif | ||
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 616a96a3ab81..e466d886e192 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
@@ -589,6 +589,10 @@ struct fc_function_template { | |||
589 | int (*vport_disable)(struct fc_vport *, bool); | 589 | int (*vport_disable)(struct fc_vport *, bool); |
590 | int (*vport_delete)(struct fc_vport *); | 590 | int (*vport_delete)(struct fc_vport *); |
591 | 591 | ||
592 | /* target-mode drivers' functions */ | ||
593 | int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); | ||
594 | int (* it_nexus_response)(struct Scsi_Host *, u64, int); | ||
595 | |||
592 | /* allocation lengths for host-specific data */ | 596 | /* allocation lengths for host-specific data */ |
593 | u32 dd_fcrport_size; | 597 | u32 dd_fcrport_size; |
594 | u32 dd_fcvport_size; | 598 | u32 dd_fcvport_size; |