aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2011-02-22 13:54:48 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-25 12:02:21 -0500
commit038d9446a9e601d7972926ca69fee10eeda6f3c7 (patch)
treece0833dd6c69bf45d53968412c3596432ebf21c1
parent22fd411ac9853f4becb3db9860f6d0b8398cac44 (diff)
[SCSI] zfcp: Add information to symbolic port name when running in NPIV mode
Query the FC symbolic port name for reporting in the fc_host sysfs and enable the symbolic_name attribute in the fc_host sysfs. When running in NPIV mode, extend the symbolic port name with the devno and the hostname. This allows better identification of Linux systems for SAN and storage administrators. Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_def.h1
-rw-r--r--drivers/s390/scsi/zfcp_erp.c2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fc.c120
-rw-r--r--drivers/s390/scsi/zfcp_fc.h42
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c1
7 files changed, 169 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 88691adc128..645b0fcbb37 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -362,6 +362,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
362 362
363 INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); 363 INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
364 INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports); 364 INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
365 INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
365 366
366 if (zfcp_qdio_setup(adapter)) 367 if (zfcp_qdio_setup(adapter))
367 goto failed; 368 goto failed;
@@ -427,6 +428,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
427 428
428 cancel_work_sync(&adapter->scan_work); 429 cancel_work_sync(&adapter->scan_work);
429 cancel_work_sync(&adapter->stat_work); 430 cancel_work_sync(&adapter->stat_work);
431 cancel_work_sync(&adapter->ns_up_work);
430 zfcp_destroy_adapter_work_queue(adapter); 432 zfcp_destroy_adapter_work_queue(adapter);
431 433
432 zfcp_fc_wka_ports_force_offline(adapter->gs); 434 zfcp_fc_wka_ports_force_offline(adapter->gs);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 1566208997b..527ba48eea5 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -189,6 +189,7 @@ struct zfcp_adapter {
189 struct fsf_qtcb_bottom_port *stats_reset_data; 189 struct fsf_qtcb_bottom_port *stats_reset_data;
190 unsigned long stats_reset; 190 unsigned long stats_reset;
191 struct work_struct scan_work; 191 struct work_struct scan_work;
192 struct work_struct ns_up_work;
192 struct service_level service_level; 193 struct service_level service_level;
193 struct workqueue_struct *work_queue; 194 struct workqueue_struct *work_queue;
194 struct device_dma_parameters dma_parms; 195 struct device_dma_parameters dma_parms;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 6c1cddf0d0a..e1b4f800e22 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1231,8 +1231,10 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1231 if (result == ZFCP_ERP_SUCCEEDED) { 1231 if (result == ZFCP_ERP_SUCCEEDED) {
1232 register_service_level(&adapter->service_level); 1232 register_service_level(&adapter->service_level);
1233 queue_work(adapter->work_queue, &adapter->scan_work); 1233 queue_work(adapter->work_queue, &adapter->scan_work);
1234 queue_work(adapter->work_queue, &adapter->ns_up_work);
1234 } else 1235 } else
1235 unregister_service_level(&adapter->service_level); 1236 unregister_service_level(&adapter->service_level);
1237
1236 kref_put(&adapter->ref, zfcp_adapter_release); 1238 kref_put(&adapter->ref, zfcp_adapter_release);
1237 break; 1239 break;
1238 } 1240 }
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 410d9ddc175..03627cfd81c 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -96,6 +96,7 @@ extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
96extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); 96extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
97extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); 97extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
98extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *); 98extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
99extern void zfcp_fc_sym_name_update(struct work_struct *);
99 100
100/* zfcp_fsf.c */ 101/* zfcp_fsf.c */
101extern struct kmem_cache *zfcp_fsf_qtcb_cache; 102extern struct kmem_cache *zfcp_fsf_qtcb_cache;
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index c839a3b6879..297e6b71ce9 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -11,6 +11,7 @@
11 11
12#include <linux/types.h> 12#include <linux/types.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/utsname.h>
14#include <scsi/fc/fc_els.h> 15#include <scsi/fc/fc_els.h>
15#include <scsi/libfc.h> 16#include <scsi/libfc.h>
16#include "zfcp_ext.h" 17#include "zfcp_ext.h"
@@ -696,6 +697,125 @@ out:
696 zfcp_fc_wka_port_put(&adapter->gs->ds); 697 zfcp_fc_wka_port_put(&adapter->gs->ds);
697} 698}
698 699
700static int zfcp_fc_gspn(struct zfcp_adapter *adapter,
701 struct zfcp_fc_req *fc_req)
702{
703 DECLARE_COMPLETION_ONSTACK(completion);
704 char devno[] = "DEVNO:";
705 struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
706 struct zfcp_fc_gspn_req *gspn_req = &fc_req->u.gspn.req;
707 struct zfcp_fc_gspn_rsp *gspn_rsp = &fc_req->u.gspn.rsp;
708 int ret;
709
710 zfcp_fc_ct_ns_init(&gspn_req->ct_hdr, FC_NS_GSPN_ID,
711 FC_SYMBOLIC_NAME_SIZE);
712 hton24(gspn_req->gspn.fp_fid, fc_host_port_id(adapter->scsi_host));
713
714 sg_init_one(&fc_req->sg_req, gspn_req, sizeof(*gspn_req));
715 sg_init_one(&fc_req->sg_rsp, gspn_rsp, sizeof(*gspn_rsp));
716
717 ct_els->handler = zfcp_fc_complete;
718 ct_els->handler_data = &completion;
719 ct_els->req = &fc_req->sg_req;
720 ct_els->resp = &fc_req->sg_rsp;
721
722 ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
723 ZFCP_FC_CTELS_TMO);
724 if (ret)
725 return ret;
726
727 wait_for_completion(&completion);
728 if (ct_els->status)
729 return ct_els->status;
730
731 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_NPIV &&
732 !(strstr(gspn_rsp->gspn.fp_name, devno)))
733 snprintf(fc_host_symbolic_name(adapter->scsi_host),
734 FC_SYMBOLIC_NAME_SIZE, "%s%s %s NAME: %s",
735 gspn_rsp->gspn.fp_name, devno,
736 dev_name(&adapter->ccw_device->dev),
737 init_utsname()->nodename);
738 else
739 strlcpy(fc_host_symbolic_name(adapter->scsi_host),
740 gspn_rsp->gspn.fp_name, FC_SYMBOLIC_NAME_SIZE);
741
742 return 0;
743}
744
745static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
746 struct zfcp_fc_req *fc_req)
747{
748 DECLARE_COMPLETION_ONSTACK(completion);
749 struct Scsi_Host *shost = adapter->scsi_host;
750 struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
751 struct zfcp_fc_rspn_req *rspn_req = &fc_req->u.rspn.req;
752 struct fc_ct_hdr *rspn_rsp = &fc_req->u.rspn.rsp;
753 int ret, len;
754
755 zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID,
756 FC_SYMBOLIC_NAME_SIZE);
757 hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost));
758 len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
759 FC_SYMBOLIC_NAME_SIZE);
760 rspn_req->rspn.fr_name_len = len;
761
762 sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req));
763 sg_init_one(&fc_req->sg_rsp, rspn_rsp, sizeof(*rspn_rsp));
764
765 ct_els->handler = zfcp_fc_complete;
766 ct_els->handler_data = &completion;
767 ct_els->req = &fc_req->sg_req;
768 ct_els->resp = &fc_req->sg_rsp;
769
770 ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
771 ZFCP_FC_CTELS_TMO);
772 if (!ret)
773 wait_for_completion(&completion);
774}
775
776/**
777 * zfcp_fc_sym_name_update - Retrieve and update the symbolic port name
778 * @work: ns_up_work of the adapter where to update the symbolic port name
779 *
780 * Retrieve the current symbolic port name that may have been set by
781 * the hardware using the GSPN request and update the fc_host
782 * symbolic_name sysfs attribute. When running in NPIV mode (and hence
783 * the port name is unique for this system), update the symbolic port
784 * name to add Linux specific information and update the FC nameserver
785 * using the RSPN request.
786 */
787void zfcp_fc_sym_name_update(struct work_struct *work)
788{
789 struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
790 ns_up_work);
791 int ret;
792 struct zfcp_fc_req *fc_req;
793
794 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT &&
795 fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
796 return;
797
798 fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL);
799 if (!fc_req)
800 return;
801
802 ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
803 if (ret)
804 goto out_free;
805
806 ret = zfcp_fc_gspn(adapter, fc_req);
807 if (ret || fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
808 goto out_ds_put;
809
810 memset(fc_req, 0, sizeof(*fc_req));
811 zfcp_fc_rspn(adapter, fc_req);
812
813out_ds_put:
814 zfcp_fc_wka_port_put(&adapter->gs->ds);
815out_free:
816 kmem_cache_free(zfcp_fc_req_cache, fc_req);
817}
818
699static void zfcp_fc_ct_els_job_handler(void *data) 819static void zfcp_fc_ct_els_job_handler(void *data)
700{ 820{
701 struct fc_bsg_job *job = data; 821 struct fc_bsg_job *job = data;
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h
index 5243ce44aa4..4561f3bf730 100644
--- a/drivers/s390/scsi/zfcp_fc.h
+++ b/drivers/s390/scsi/zfcp_fc.h
@@ -84,6 +84,40 @@ struct zfcp_fc_gpn_ft_req {
84} __packed; 84} __packed;
85 85
86/** 86/**
87 * struct zfcp_fc_gspn_req - container for ct header plus GSPN_ID request
88 * @ct_hdr: FC GS common transport header
89 * @gspn: GSPN_ID request
90 */
91struct zfcp_fc_gspn_req {
92 struct fc_ct_hdr ct_hdr;
93 struct fc_gid_pn_resp gspn;
94} __packed;
95
96/**
97 * struct zfcp_fc_gspn_rsp - container for ct header plus GSPN_ID response
98 * @ct_hdr: FC GS common transport header
99 * @gspn: GSPN_ID response
100 * @name: The name string of the GSPN_ID response
101 */
102struct zfcp_fc_gspn_rsp {
103 struct fc_ct_hdr ct_hdr;
104 struct fc_gspn_resp gspn;
105 char name[FC_SYMBOLIC_NAME_SIZE];
106} __packed;
107
108/**
109 * struct zfcp_fc_rspn_req - container for ct header plus RSPN_ID request
110 * @ct_hdr: FC GS common transport header
111 * @rspn: RSPN_ID request
112 * @name: The name string of the RSPN_ID request
113 */
114struct zfcp_fc_rspn_req {
115 struct fc_ct_hdr ct_hdr;
116 struct fc_ns_rspn rspn;
117 char name[FC_SYMBOLIC_NAME_SIZE];
118} __packed;
119
120/**
87 * struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp 121 * struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp
88 * @ct_els: data required for issuing fsf command 122 * @ct_els: data required for issuing fsf command
89 * @sg_req: scatterlist entry for request data 123 * @sg_req: scatterlist entry for request data
@@ -107,6 +141,14 @@ struct zfcp_fc_req {
107 struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1]; 141 struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1];
108 struct zfcp_fc_gpn_ft_req req; 142 struct zfcp_fc_gpn_ft_req req;
109 } gpn_ft; 143 } gpn_ft;
144 struct {
145 struct zfcp_fc_gspn_req req;
146 struct zfcp_fc_gspn_rsp rsp;
147 } gspn;
148 struct {
149 struct zfcp_fc_rspn_req req;
150 struct fc_ct_hdr rsp;
151 } rspn;
110 } u; 152 } u;
111}; 153};
112 154
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index dbba0827127..2a4991d6d4d 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -720,6 +720,7 @@ struct fc_function_template zfcp_transport_functions = {
720 /* no functions registered for following dynamic attributes but 720 /* no functions registered for following dynamic attributes but
721 directly set by LLDD */ 721 directly set by LLDD */
722 .show_host_port_type = 1, 722 .show_host_port_type = 1,
723 .show_host_symbolic_name = 1,
723 .show_host_speed = 1, 724 .show_host_speed = 1,
724 .show_host_port_id = 1, 725 .show_host_port_id = 1,
725 .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), 726 .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),