* [patch 0/2] FC pass-through support for zfcp
@ 2009-04-06 16:31 Christof Schmitt
2009-04-06 16:31 ` [patch 1/2] zfcp: Set WKA-port to offline on adapter deactivation Christof Schmitt
2009-04-06 16:31 ` [patch 2/2] zfcp: Add FC pass-through support Christof Schmitt
0 siblings, 2 replies; 7+ messages in thread
From: Christof Schmitt @ 2009-04-06 16:31 UTC (permalink / raw)
To: linux-scsi; +Cc: Sven Schuetz, James.Smart
Here is the implementation of the FC pass-through support for zfcp.
The first patch is a fix required on top of the current linux-2.6
kernel and the second the actual implementation of the pass-through
support. This requires the FC pass-through patch from James Smart.
As soon as the common FC pass-through supports gets integrated, i
would like to add support for zfcp as well.
--
Christof Schmitt
^ permalink raw reply [flat|nested] 7+ messages in thread
* [patch 1/2] zfcp: Set WKA-port to offline on adapter deactivation
2009-04-06 16:31 [patch 0/2] FC pass-through support for zfcp Christof Schmitt
@ 2009-04-06 16:31 ` Christof Schmitt
2009-04-06 16:31 ` [patch 2/2] zfcp: Add FC pass-through support Christof Schmitt
1 sibling, 0 replies; 7+ messages in thread
From: Christof Schmitt @ 2009-04-06 16:31 UTC (permalink / raw)
To: linux-scsi; +Cc: Sven Schuetz, James.Smart, Swen Schillig, Christof Schmitt
[-- Attachment #1: 704-zfcp-wka-port.diff --]
[-- Type: text/plain, Size: 4027 bytes --]
From: Swen Schillig <swen@vnet.ibm.com>
The nameserver port might be in state online when the adapter is
offlined. On adapter reactivation the nameserver port is not
re-opened due to the PORT_ONLINE status. This results in an
unsuccessful recovery. In forcing the nameserver port status
to offline on all adapter offline events this issue is prevented.
Signed-off-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
---
drivers/s390/scsi/zfcp_aux.c | 3 ++-
drivers/s390/scsi/zfcp_ccw.c | 1 -
drivers/s390/scsi/zfcp_erp.c | 1 +
drivers/s390/scsi/zfcp_ext.h | 1 +
drivers/s390/scsi/zfcp_fc.c | 16 ++++++++++------
5 files changed, 14 insertions(+), 8 deletions(-)
--- a/drivers/s390/scsi/zfcp_aux.c 2009-04-06 17:20:50.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_aux.c 2009-04-06 17:22:14.000000000 +0200
@@ -525,6 +525,8 @@ int zfcp_adapter_enqueue(struct ccw_devi
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
+ zfcp_fc_nameserver_init(adapter);
+
if (!zfcp_adapter_scsi_register(adapter))
return 0;
@@ -553,7 +555,6 @@ void zfcp_adapter_dequeue(struct zfcp_ad
cancel_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
- cancel_delayed_work_sync(&adapter->nsp.work);
zfcp_adapter_scsi_unregister(adapter);
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_adapter_attrs);
--- a/drivers/s390/scsi/zfcp_ccw.c 2009-04-06 17:20:50.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_ccw.c 2009-04-06 17:22:14.000000000 +0200
@@ -108,7 +108,6 @@ static int zfcp_ccw_set_online(struct cc
/* initialize request counter */
BUG_ON(!zfcp_reqlist_isempty(adapter));
adapter->req_no = 0;
- zfcp_fc_nameserver_init(adapter);
zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
--- a/drivers/s390/scsi/zfcp_erp.c 2009-04-06 17:07:10.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_erp.c 2009-04-06 17:22:14.000000000 +0200
@@ -719,6 +719,7 @@ static void zfcp_erp_adapter_strategy_cl
zfcp_qdio_close(adapter);
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
+ zfcp_fc_wka_port_force_offline(&adapter->nsp);
/* all ports and units are closed */
zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
--- a/drivers/s390/scsi/zfcp_ext.h 2009-04-06 17:20:50.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_ext.h 2009-04-06 17:22:14.000000000 +0200
@@ -106,6 +106,7 @@ extern void zfcp_fc_plogi_evaluate(struc
extern void zfcp_test_link(struct zfcp_port *);
extern void zfcp_fc_link_test_work(struct work_struct *);
extern void zfcp_fc_nameserver_init(struct zfcp_adapter *);
+extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
--- a/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:20:50.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:22:14.000000000 +0200
@@ -98,12 +98,8 @@ static void zfcp_wka_port_offline(struct
struct zfcp_wka_port *wka_port =
container_of(dw, struct zfcp_wka_port, work);
- /* Don't wait forvever. If the wka_port is too busy take it offline
- through a new call later */
- if (!wait_event_timeout(wka_port->completion_wq,
- atomic_read(&wka_port->refcount) == 0,
- HZ >> 1))
- return;
+ wait_event(wka_port->completion_wq,
+ atomic_read(&wka_port->refcount) == 0);
mutex_lock(&wka_port->mutex);
if ((atomic_read(&wka_port->refcount) != 0) ||
@@ -142,6 +138,14 @@ void zfcp_fc_nameserver_init(struct zfcp
INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
}
+void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
+{
+ cancel_delayed_work_sync(&wka->work);
+ mutex_lock(&wka->mutex);
+ wka->status = ZFCP_WKA_PORT_OFFLINE;
+ mutex_unlock(&wka->mutex);
+}
+
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
struct fcp_rscn_element *elem)
{
^ permalink raw reply [flat|nested] 7+ messages in thread
* [patch 2/2] zfcp: Add FC pass-through support
2009-04-06 16:31 [patch 0/2] FC pass-through support for zfcp Christof Schmitt
2009-04-06 16:31 ` [patch 1/2] zfcp: Set WKA-port to offline on adapter deactivation Christof Schmitt
@ 2009-04-06 16:31 ` Christof Schmitt
2009-04-07 23:17 ` James Smart
2009-04-08 11:29 ` Heiko Carstens
1 sibling, 2 replies; 7+ messages in thread
From: Christof Schmitt @ 2009-04-06 16:31 UTC (permalink / raw)
To: linux-scsi; +Cc: Sven Schuetz, James.Smart, Christof Schmitt
[-- Attachment #1: fc_passthrough.diff --]
[-- Type: text/plain, Size: 13405 bytes --]
From: Sven Schuetz <sven@linux.vnet.ibm.com>
Provide the ability to do fibre channel requests from the userspace to
our zfcp driver. Patch builds upon extension to the fibre channel
tranport class by James Smart and Seokmann Ju. See here
http://marc.info/?l=linux-scsi&m=123808882309133&w=2
Signed-off-by: Sven Schuetz <sven@linux.vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
---
drivers/s390/scsi/zfcp_aux.c | 10 +-
drivers/s390/scsi/zfcp_def.h | 18 ++--
drivers/s390/scsi/zfcp_erp.c | 2
drivers/s390/scsi/zfcp_ext.h | 6 +
drivers/s390/scsi/zfcp_fc.c | 188 +++++++++++++++++++++++++++++++++++++++---
drivers/s390/scsi/zfcp_scsi.c | 15 +++
6 files changed, 219 insertions(+), 20 deletions(-)
--- a/drivers/s390/scsi/zfcp_aux.c 2009-04-06 17:23:25.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_aux.c 2009-04-06 17:23:29.000000000 +0200
@@ -471,6 +471,12 @@ int zfcp_adapter_enqueue(struct ccw_devi
if (!adapter)
return -ENOMEM;
+ adapter->gs = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL);
+ if (!adapter->gs) {
+ kfree(adapter);
+ return -ENOMEM;
+ }
+
ccw_device->handler = NULL;
adapter->ccw_device = ccw_device;
atomic_set(&adapter->refcount, 0);
@@ -524,8 +530,7 @@ int zfcp_adapter_enqueue(struct ccw_devi
goto sysfs_failed;
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
-
- zfcp_fc_nameserver_init(adapter);
+ zfcp_fc_wka_ports_init(adapter);
if (!zfcp_adapter_scsi_register(adapter))
return 0;
@@ -572,6 +577,7 @@ void zfcp_adapter_dequeue(struct zfcp_ad
kfree(adapter->req_list);
kfree(adapter->fc_stats);
kfree(adapter->stats_reset_data);
+ kfree(adapter->gs);
kfree(adapter);
}
--- a/drivers/s390/scsi/zfcp_def.h 2009-04-06 17:23:23.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_def.h 2009-04-06 17:23:29.000000000 +0200
@@ -22,6 +22,8 @@
#include <linux/syscalls.h>
#include <linux/scatterlist.h>
#include <linux/ioctl.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_gs.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h>
@@ -29,6 +31,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_bsg_fc.h>
#include <asm/ccwdev.h>
#include <asm/qdio.h>
#include <asm/debug.h>
@@ -235,11 +238,6 @@ struct zfcp_ls_adisc {
/* FC-PH/FC-GS well-known address identifiers for generic services */
#define ZFCP_DID_WKA 0xFFFFF0
-#define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA
-#define ZFCP_DID_TIME_SERVICE 0xFFFFFB
-#define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC
-#define ZFCP_DID_ALIAS_SERVICE 0xFFFFF8
-#define ZFCP_DID_KEY_DISTRIBUTION_SERVICE 0xFFFFF7
/* remote port status */
#define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001
@@ -384,6 +382,14 @@ struct zfcp_wka_port {
struct delayed_work work;
};
+struct zfcp_wka_ports {
+ struct zfcp_wka_port ms; /* management service */
+ struct zfcp_wka_port ts; /* time service */
+ struct zfcp_wka_port ds; /* directory service */
+ struct zfcp_wka_port as; /* alias service */
+ struct zfcp_wka_port ks; /* key distribution service */
+};
+
struct zfcp_qdio_queue {
struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
u8 first; /* index of next free bfr in queue */
@@ -469,7 +475,7 @@ struct zfcp_adapter {
actions */
u32 erp_low_mem_count; /* nr of erp actions waiting
for memory */
- struct zfcp_wka_port nsp; /* adapter's nameserver */
+ struct zfcp_wka_ports *gs; /* generic services */
debug_info_t *rec_dbf;
debug_info_t *hba_dbf;
debug_info_t *san_dbf; /* debug feature areas */
--- a/drivers/s390/scsi/zfcp_ext.h 2009-04-06 17:23:25.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_ext.h 2009-04-06 17:23:29.000000000 +0200
@@ -105,8 +105,12 @@ extern int zfcp_fc_ns_gid_pn(struct zfcp
extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
extern void zfcp_test_link(struct zfcp_port *);
extern void zfcp_fc_link_test_work(struct work_struct *);
-extern void zfcp_fc_nameserver_init(struct zfcp_adapter *);
extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
+extern void zfcp_fc_wka_ports_init(struct zfcp_adapter *);
+extern int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *);
+extern int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *);
+extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
+
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
--- a/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:23:25.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:24:30.000000000 +0200
@@ -123,14 +123,13 @@ static void zfcp_wka_port_put(struct zfc
schedule_delayed_work(&wka_port->work, HZ / 100);
}
-void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter)
+static void zfcp_fc_wka_port_init(struct zfcp_wka_port *wka_port, u32 d_id,
+ struct zfcp_adapter *adapter)
{
- struct zfcp_wka_port *wka_port = &adapter->nsp;
-
init_waitqueue_head(&wka_port->completion_wq);
wka_port->adapter = adapter;
- wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE;
+ wka_port->d_id = d_id;
wka_port->status = ZFCP_WKA_PORT_OFFLINE;
atomic_set(&wka_port->refcount, 0);
@@ -146,6 +145,17 @@ void zfcp_fc_wka_port_force_offline(stru
mutex_unlock(&wka->mutex);
}
+void zfcp_fc_wka_ports_init(struct zfcp_adapter *adapter)
+{
+ struct zfcp_wka_ports *gs = adapter->gs;
+
+ zfcp_fc_wka_port_init(&gs->ms, FC_FID_MGMT_SERV, adapter);
+ zfcp_fc_wka_port_init(&gs->ts, FC_FID_TIME_SERV, adapter);
+ zfcp_fc_wka_port_init(&gs->ds, FC_FID_DIR_SERV, adapter);
+ zfcp_fc_wka_port_init(&gs->as, FC_FID_ALIASES, adapter);
+ zfcp_fc_wka_port_init(&gs->ks, FC_FID_SEC_KEY, adapter);
+}
+
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
struct fcp_rscn_element *elem)
{
@@ -280,7 +290,7 @@ int static zfcp_fc_ns_gid_pn_request(str
/* setup parameters for send generic command */
gid_pn->port = erp_action->port;
- gid_pn->ct.wka_port = &adapter->nsp;
+ gid_pn->ct.wka_port = &adapter->gs->ds;
gid_pn->ct.handler = zfcp_fc_ns_handler;
gid_pn->ct.handler_data = (unsigned long) &compl_rec;
gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
@@ -327,13 +337,13 @@ int zfcp_fc_ns_gid_pn(struct zfcp_erp_ac
memset(gid_pn, 0, sizeof(*gid_pn));
- ret = zfcp_wka_port_get(&adapter->nsp);
+ ret = zfcp_wka_port_get(&adapter->gs->ds);
if (ret)
goto out;
ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn);
- zfcp_wka_port_put(&adapter->nsp);
+ zfcp_wka_port_put(&adapter->gs->ds);
out:
mempool_free(gid_pn, adapter->pool.data_gid_pn);
return ret;
@@ -527,7 +537,7 @@ static int zfcp_scan_issue_gpn_ft(struct
req->fc4_type = ZFCP_CT_SCSI_FCP;
/* prepare zfcp_send_ct */
- ct->wka_port = &adapter->nsp;
+ ct->wka_port = &adapter->gs->ds;
ct->handler = zfcp_fc_ns_handler;
ct->handler_data = (unsigned long)&compl_rec;
ct->timeout = 10;
@@ -644,7 +654,7 @@ int zfcp_scan_ports(struct zfcp_adapter
if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
return 0;
- ret = zfcp_wka_port_get(&adapter->nsp);
+ ret = zfcp_wka_port_get(&adapter->gs->ds);
if (ret)
return ret;
@@ -666,7 +676,7 @@ int zfcp_scan_ports(struct zfcp_adapter
}
zfcp_free_sg_env(gpn_ft, buf_num);
out:
- zfcp_wka_port_put(&adapter->nsp);
+ zfcp_wka_port_put(&adapter->gs->ds);
return ret;
}
@@ -675,3 +685,161 @@ void _zfcp_scan_ports_later(struct work_
{
zfcp_scan_ports(container_of(work, struct zfcp_adapter, scan_work));
}
+
+struct zfcp_els_fc_job {
+ struct zfcp_send_els els;
+ struct fc_bsg_job *job;
+};
+
+static void zfcp_fc_generic_els_handler(unsigned long data)
+{
+ struct zfcp_els_fc_job *els_fc_job = (struct zfcp_els_fc_job *) data;
+ struct fc_bsg_job *job = els_fc_job->job;
+ struct fc_bsg_reply *reply = job->reply;
+
+ if (els_fc_job->els.status) {
+ /* request rejected or timed out */
+ reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT;
+ goto out;
+ }
+
+ reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+ reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq);
+
+out:
+ job->state_flags = FC_RQST_STATE_DONE;
+ job->job_done(job);
+ kfree(els_fc_job);
+}
+
+int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job)
+{
+ struct zfcp_els_fc_job *els_fc_job;
+ struct fc_rport *rport = job->rport;
+ struct Scsi_Host *shost;
+ struct zfcp_adapter *adapter;
+ struct zfcp_port *port;
+ u8 *port_did;
+
+ shost = rport ? rport_to_shost(rport) : job->shost;
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+
+ if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN))
+ return -EINVAL;
+
+ els_fc_job = kzalloc(sizeof(struct zfcp_els_fc_job), GFP_KERNEL);
+ if (!els_fc_job)
+ return -ENOMEM;
+
+ els_fc_job->els.adapter = adapter;
+ if (rport) {
+ read_lock_irq(&zfcp_data.config_lock);
+ port = rport->dd_data;
+ if (port)
+ zfcp_port_get(port);
+ read_unlock_irq(&zfcp_data.config_lock);
+ if (!port) {
+ kfree(els_fc_job);
+ return -EINVAL;
+ }
+ els_fc_job->els.port = port;
+ els_fc_job->els.d_id = port->d_id;
+ zfcp_port_put(port);
+ } else {
+ port_did = job->request->rqst_data.h_els.port_id;
+ els_fc_job->els.d_id = (port_did[0] << 16) +
+ (port_did[1] << 8) + port_did[2];
+ }
+
+ els_fc_job->els.req = job->request_payload.sg_list;
+ els_fc_job->els.resp = job->reply_payload.sg_list;
+ els_fc_job->els.handler = zfcp_fc_generic_els_handler;
+ els_fc_job->els.handler_data = (unsigned long) els_fc_job;
+ els_fc_job->job = job;
+
+ return zfcp_fsf_send_els(&els_fc_job->els);
+}
+
+struct zfcp_ct_fc_job {
+ struct zfcp_send_ct ct;
+ struct fc_bsg_job *job;
+};
+
+static void zfcp_fc_generic_ct_handler(unsigned long data)
+{
+ struct zfcp_ct_fc_job *ct_fc_job = (struct zfcp_ct_fc_job *) data;
+ struct fc_bsg_job *job = ct_fc_job->job;
+
+ job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ?
+ FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK;
+ job->state_flags = FC_RQST_STATE_DONE;
+ job->reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq);
+ job->job_done(job);
+
+ zfcp_wka_port_put(ct_fc_job->ct.wka_port);
+
+ kfree(ct_fc_job);
+}
+
+int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job)
+{
+ int ret;
+ u8 gs_type;
+ struct fc_rport *rport = job->rport;
+ struct Scsi_Host *shost;
+ struct zfcp_adapter *adapter;
+ struct zfcp_ct_fc_job *ct_fc_job;
+ u32 preamble_word1;
+
+ shost = rport ? rport_to_shost(rport) : job->shost;
+
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN))
+ return -EINVAL;
+
+ ct_fc_job = kzalloc(sizeof(struct zfcp_ct_fc_job), GFP_KERNEL);
+ if (!ct_fc_job)
+ return -ENOMEM;
+
+ preamble_word1 = job->request->rqst_data.r_ct.preamble_word1;
+ gs_type = (preamble_word1 & 0xff000000) >> 24;
+
+ switch (gs_type) {
+ case FC_FST_ALIAS:
+ ct_fc_job->ct.wka_port = &adapter->gs->as;
+ break;
+ case FC_FST_MGMT:
+ ct_fc_job->ct.wka_port = &adapter->gs->ms;
+ break;
+ case FC_FST_TIME:
+ ct_fc_job->ct.wka_port = &adapter->gs->ts;
+ break;
+ case FC_FST_DIR:
+ ct_fc_job->ct.wka_port = &adapter->gs->ds;
+ break;
+ default:
+ kfree(ct_fc_job);
+ return -EINVAL; /* no such service */
+ }
+
+ ret = zfcp_wka_port_get(ct_fc_job->ct.wka_port);
+ if (ret) {
+ kfree(ct_fc_job);
+ return ret;
+ }
+
+ ct_fc_job->ct.req = job->request_payload.sg_list;
+ ct_fc_job->ct.resp = job->reply_payload.sg_list;
+ ct_fc_job->ct.timeout = ZFCP_FSF_REQUEST_TIMEOUT;
+ ct_fc_job->ct.handler = zfcp_fc_generic_ct_handler;
+ ct_fc_job->ct.handler_data = (unsigned long) ct_fc_job;
+ ct_fc_job->ct.completion = NULL;
+ ct_fc_job->job = job;
+
+ ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL, NULL);
+ if (ret) {
+ kfree(ct_fc_job);
+ zfcp_wka_port_put(ct_fc_job->ct.wka_port);
+ }
+ return ret;
+}
--- a/drivers/s390/scsi/zfcp_scsi.c 2009-04-06 17:23:23.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_scsi.c 2009-04-06 17:23:29.000000000 +0200
@@ -583,6 +583,20 @@ void zfcp_scsi_rport_work(struct work_st
}
+static int zfcp_execute_fc_job(struct fc_bsg_job *job)
+{
+ switch (job->request->msgcode) {
+ case FC_BSG_RPT_ELS:
+ case FC_BSG_HST_ELS_NOLOGIN:
+ return zfcp_fc_execute_els_fc_job(job);
+ case FC_BSG_RPT_CT:
+ case FC_BSG_HST_CT:
+ return zfcp_fc_execute_ct_fc_job(job);
+ default:
+ return -EINVAL;
+ }
+}
+
struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
@@ -604,6 +618,7 @@ struct fc_function_template zfcp_transpo
.dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
.terminate_rport_io = zfcp_scsi_terminate_rport_io,
.show_host_port_state = 1,
+ .bsg_request = zfcp_execute_fc_job,
/* no functions registered for following dynamic attributes but
directly set by LLDD */
.show_host_port_type = 1,
--- a/drivers/s390/scsi/zfcp_erp.c 2009-04-06 17:23:25.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_erp.c 2009-04-06 17:23:29.000000000 +0200
@@ -719,7 +719,7 @@ static void zfcp_erp_adapter_strategy_cl
zfcp_qdio_close(adapter);
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
- zfcp_fc_wka_port_force_offline(&adapter->nsp);
+ zfcp_fc_wka_port_force_offline(&adapter->gs->ds);
/* all ports and units are closed */
zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 2/2] zfcp: Add FC pass-through support
2009-04-06 16:31 ` [patch 2/2] zfcp: Add FC pass-through support Christof Schmitt
@ 2009-04-07 23:17 ` James Smart
2009-04-08 7:39 ` Christof Schmitt
2009-04-08 11:29 ` Heiko Carstens
1 sibling, 1 reply; 7+ messages in thread
From: James Smart @ 2009-04-07 23:17 UTC (permalink / raw)
To: Christof Schmitt; +Cc: linux-scsi@vger.kernel.org, Sven Schuetz
Christof Schmitt wrote:
--- a/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:23:25.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:24:30.000000000 +0200
...
> +static void zfcp_fc_generic_els_handler(unsigned long data)
> +{
> + struct zfcp_els_fc_job *els_fc_job = (struct zfcp_els_fc_job *) data;
> + struct fc_bsg_job *job = els_fc_job->job;
> + struct fc_bsg_reply *reply = job->reply;
> +
> + if (els_fc_job->els.status) {
> + /* request rejected or timed out */
> + reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT;
> + goto out;
> + }
> +
> + reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
> + reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq);
My intent was to not have the LLDD reference (or even know about) the
request structures and that bsg exists underneath.
Thus, for the last line above, it should be:
reply->reply_payload_rcv_len = job->reply_payload->data_len;
Although, I'm a little surprised that your els interface doesn't supply the
received data length to you, rather than the global assumption that you sized
the reply buffer for exactly what you always get.
> +struct zfcp_ct_fc_job {
> + struct zfcp_send_ct ct;
> + struct fc_bsg_job *job;
> +};
> +
> +static void zfcp_fc_generic_ct_handler(unsigned long data)
> +{
> + struct zfcp_ct_fc_job *ct_fc_job = (struct zfcp_ct_fc_job *) data;
> + struct fc_bsg_job *job = ct_fc_job->job;
> +
> + job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ?
> + FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK;
> + job->state_flags = FC_RQST_STATE_DONE;
> + job->reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq);
same comment as above.
> + job->job_done(job);
> +
> + zfcp_wka_port_put(ct_fc_job->ct.wka_port);
> +
> + kfree(ct_fc_job);
> +}
Are you going to add support for the ELS/CT request timing out (e.g. for
bsg_timeout callback) ?
Everything else looks good, and looks like it wasn't much effort to support.
Great.
-- james s
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 2/2] zfcp: Add FC pass-through support
2009-04-07 23:17 ` James Smart
@ 2009-04-08 7:39 ` Christof Schmitt
0 siblings, 0 replies; 7+ messages in thread
From: Christof Schmitt @ 2009-04-08 7:39 UTC (permalink / raw)
To: James Smart; +Cc: linux-scsi@vger.kernel.org, Sven Schuetz
On Tue, Apr 07, 2009 at 07:17:58PM -0400, James Smart wrote:
> Christof Schmitt wrote:
> --- a/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:23:25.000000000 +0200
> +++ b/drivers/s390/scsi/zfcp_fc.c 2009-04-06 17:24:30.000000000 +0200
> ...
>> +static void zfcp_fc_generic_els_handler(unsigned long data)
>> +{
>> + struct zfcp_els_fc_job *els_fc_job = (struct zfcp_els_fc_job *) data;
>> + struct fc_bsg_job *job = els_fc_job->job;
>> + struct fc_bsg_reply *reply = job->reply;
>> +
>> + if (els_fc_job->els.status) {
>> + /* request rejected or timed out */
>> + reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT;
>> + goto out;
>> + }
>> +
>> + reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
>> + reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq);
>
> My intent was to not have the LLDD reference (or even know about) the
> request structures and that bsg exists underneath.
>
> Thus, for the last line above, it should be:
> reply->reply_payload_rcv_len = job->reply_payload->data_len;
>
> Although, I'm a little surprised that your els interface doesn't supply the
> received data length to you, rather than the global assumption that you
> sized the reply buffer for exactly what you always get.
I guess this is one thing we have to investigate. Either use the
data_lan or get the data from the hardware.
>> +struct zfcp_ct_fc_job {
>> + struct zfcp_send_ct ct;
>> + struct fc_bsg_job *job;
>> +};
>> +
>> +static void zfcp_fc_generic_ct_handler(unsigned long data)
>> +{
>> + struct zfcp_ct_fc_job *ct_fc_job = (struct zfcp_ct_fc_job *) data;
>> + struct fc_bsg_job *job = ct_fc_job->job;
>> +
>> + job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ?
>> + FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK;
>> + job->state_flags = FC_RQST_STATE_DONE;
>> + job->reply->reply_payload_rcv_len = blk_rq_bytes(job->req->next_rq);
>
> same comment as above.
>
>> + job->job_done(job);
>> +
>> + zfcp_wka_port_put(ct_fc_job->ct.wka_port);
>> +
>> + kfree(ct_fc_job);
>> +}
>
> Are you going to add support for the ELS/CT request timing out (e.g. for
> bsg_timeout callback) ?
We don't have an interface to our hardware to abort ELS or CT
requests. I suggested to remove the bsg_timeout callback, since there
is not much zfcp can do here. Any pending request will timeout in the
SAN or in the HBA if there is not response.
> Everything else looks good, and looks like it wasn't much effort to support.
> Great.
Yes, the result looks good.
With 2.6.30-rc1 being out, the next merge window will be for 2.6.31.
Are you going to push the FC passthrough support for 2.6.31?
--
Christof Schmitt
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 2/2] zfcp: Add FC pass-through support
2009-04-06 16:31 ` [patch 2/2] zfcp: Add FC pass-through support Christof Schmitt
2009-04-07 23:17 ` James Smart
@ 2009-04-08 11:29 ` Heiko Carstens
2009-04-08 11:38 ` Christof Schmitt
1 sibling, 1 reply; 7+ messages in thread
From: Heiko Carstens @ 2009-04-08 11:29 UTC (permalink / raw)
Cc: linux-scsi, Sven Schuetz, James.Smart, Christof Schmitt
On Mon, 06 Apr 2009 18:31:47 +0200
Christof Schmitt <christof.schmitt@de.ibm.com> wrote:
> + els_fc_job->els.adapter = adapter;
> + if (rport) {
> + read_lock_irq(&zfcp_data.config_lock);
> + port = rport->dd_data;
> + if (port)
> + zfcp_port_get(port);
> + read_unlock_irq(&zfcp_data.config_lock);
> + if (!port) {
> + kfree(els_fc_job);
> + return -EINVAL;
> + }
> + els_fc_job->els.port = port;
> + els_fc_job->els.d_id = port->d_id;
> + zfcp_port_put(port);
> + } else {
This piece looks a bit strange. Why is the reference count of the port
increased and afterwards decreased again? Still the pointer to the port
gets added to els_fc_job->els.port and therefore the structure will be
accessed later.
So either the reference count is decreased too early and this is a bug
or it's not needed at all.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 2/2] zfcp: Add FC pass-through support
2009-04-08 11:29 ` Heiko Carstens
@ 2009-04-08 11:38 ` Christof Schmitt
0 siblings, 0 replies; 7+ messages in thread
From: Christof Schmitt @ 2009-04-08 11:38 UTC (permalink / raw)
To: Heiko Carstens; +Cc: linux-scsi, Sven Schuetz, James.Smart
On Wed, Apr 08, 2009 at 01:29:45PM +0200, Heiko Carstens wrote:
> On Mon, 06 Apr 2009 18:31:47 +0200
> Christof Schmitt <christof.schmitt@de.ibm.com> wrote:
> > + els_fc_job->els.adapter = adapter;
> > + if (rport) {
> > + read_lock_irq(&zfcp_data.config_lock);
> > + port = rport->dd_data;
> > + if (port)
> > + zfcp_port_get(port);
> > + read_unlock_irq(&zfcp_data.config_lock);
> > + if (!port) {
> > + kfree(els_fc_job);
> > + return -EINVAL;
> > + }
> > + els_fc_job->els.port = port;
> > + els_fc_job->els.d_id = port->d_id;
> > + zfcp_port_put(port);
> > + } else {
>
> This piece looks a bit strange. Why is the reference count of the port
> increased and afterwards decreased again? Still the pointer to the port
> gets added to els_fc_job->els.port and therefore the structure will be
> accessed later.
>
> So either the reference count is decreased too early and this is a bug
> or it's not needed at all.
Only the d_id is needed from the port, after this we don't access the
port anymore. The assignment of the pointer to els.port is not
required. We might do without the reference count and try to get the
d_id while holding the config_lock.
Christof
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-04-08 11:39 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-06 16:31 [patch 0/2] FC pass-through support for zfcp Christof Schmitt
2009-04-06 16:31 ` [patch 1/2] zfcp: Set WKA-port to offline on adapter deactivation Christof Schmitt
2009-04-06 16:31 ` [patch 2/2] zfcp: Add FC pass-through support Christof Schmitt
2009-04-07 23:17 ` James Smart
2009-04-08 7:39 ` Christof Schmitt
2009-04-08 11:29 ` Heiko Carstens
2009-04-08 11:38 ` Christof Schmitt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox