public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: Robert Love <robert.w.love@intel.com>
To: James.Bottomley@HansenPartnership.com, linux-scsi@vger.kernel.org
Cc: Steve Ma <steve.ma@intel.com>, Robert Love <robert.w.love@intel.com>
Subject: [PATCH 23/54] libfc, fcoe: Add FC passthrough support
Date: Tue, 03 Nov 2009 11:47:34 -0800	[thread overview]
Message-ID: <20091103194733.4085.28246.stgit@localhost.localdomain> (raw)
In-Reply-To: <20091103194530.4085.37963.stgit@localhost.localdomain>

From: Steve Ma <steve.ma@intel.com>

This is the Open-FCoE implementation of the FC
passthrough support via bsg interface.

Passthrough support is added to both N_Ports and
VN_Ports.

Signed-off-by: Steve Ma <steve.ma@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---

 drivers/scsi/fcoe/fcoe.c      |    4 +
 drivers/scsi/libfc/fc_lport.c |  267 +++++++++++++++++++++++++++++++++++++++++
 include/scsi/libfc.h          |    7 +
 3 files changed, 278 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index f1c126b..8f078d3 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -134,6 +134,8 @@ struct fc_function_template fcoe_transport_function = {
 	.vport_delete = fcoe_vport_destroy,
 	.vport_disable = fcoe_vport_disable,
 	.set_vport_symbolic_name = fcoe_set_vport_symbolic_name,
+
+	.bsg_request = fc_lport_bsg_request,
 };
 
 struct fc_function_template fcoe_vport_transport_function = {
@@ -167,6 +169,8 @@ struct fc_function_template fcoe_vport_transport_function = {
 	.issue_fc_host_lip = fcoe_reset,
 
 	.terminate_rport_io = fc_rport_terminate_io,
+
+	.bsg_request = fc_lport_bsg_request,
 };
 
 static struct scsi_host_template fcoe_shost_template = {
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index dfea6c5..2162e6b 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -94,6 +94,7 @@
 
 #include <scsi/libfc.h>
 #include <scsi/fc_encode.h>
+#include <linux/scatterlist.h>
 
 #include "fc_libfc.h"
 
@@ -127,6 +128,24 @@ static const char *fc_lport_state_names[] = {
 	[LPORT_ST_RESET] =    "reset",
 };
 
+/**
+ * struct fc_bsg_info - FC Passthrough managemet structure
+ * @job:      The passthrough job
+ * @lport:    The local port to pass through a command
+ * @rsp_code: The expected response code
+ * @sg:       job->reply_payload.sg_list
+ * @nents:    job->reply_payload.sg_cnt
+ * @offset:   The offset into the response data
+ */
+struct fc_bsg_info {
+	struct fc_bsg_job *job;
+	struct fc_lport *lport;
+	u16 rsp_code;
+	struct scatterlist *sg;
+	u32 nents;
+	size_t offset;
+};
+
 static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
 {
 	fc_frame_free(fp);
@@ -1512,3 +1531,251 @@ int fc_lport_init(struct fc_lport *lport)
 	return 0;
 }
 EXPORT_SYMBOL(fc_lport_init);
+
+/**
+ * fc_lport_bsg_resp() - The common response handler for fc pass-thru requests
+ * @sp: current sequence in the fc pass-thru request exchange
+ * @fp: received response frame
+ * @info_arg: pointer to struct fc_bsg_info
+ */
+static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
+			      void *info_arg)
+{
+	struct fc_bsg_info *info = info_arg;
+	struct fc_bsg_job *job = info->job;
+	struct fc_lport *lport = info->lport;
+	struct fc_frame_header *fh;
+	size_t len;
+	void *buf;
+
+	if (IS_ERR(fp)) {
+		job->reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ?
+			-ECONNABORTED : -ETIMEDOUT;
+		job->reply_len = sizeof(uint32_t);
+		job->state_flags |= FC_RQST_STATE_DONE;
+		job->job_done(job);
+		kfree(info);
+		return;
+	}
+
+	mutex_lock(&lport->lp_mutex);
+	fh = fc_frame_header_get(fp);
+	len = fr_len(fp) - sizeof(*fh);
+	buf = fc_frame_payload_get(fp, 0);
+
+	if (fr_sof(fp) == FC_SOF_I3 && !ntohs(fh->fh_seq_cnt)) {
+		/* Get the response code from the first frame payload */
+		unsigned short cmd = (info->rsp_code == FC_FS_ACC) ?
+			ntohs(((struct fc_ct_hdr *)buf)->ct_cmd) :
+			(unsigned short)fc_frame_payload_op(fp);
+
+		/* Save the reply status of the job */
+		job->reply->reply_data.ctels_reply.status =
+			(cmd == info->rsp_code) ?
+			FC_CTELS_STATUS_OK : FC_CTELS_STATUS_REJECT;
+	}
+
+	job->reply->reply_payload_rcv_len +=
+		fc_copy_buffer_to_sglist(buf, len, info->sg, &info->nents,
+					 &info->offset, KM_BIO_SRC_IRQ, NULL);
+
+	if (fr_eof(fp) == FC_EOF_T &&
+	    (ntoh24(fh->fh_f_ctl) & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==
+	    (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) {
+		if (job->reply->reply_payload_rcv_len >
+		    job->reply_payload.payload_len)
+			job->reply->reply_payload_rcv_len =
+				job->reply_payload.payload_len;
+		job->reply->result = 0;
+		job->state_flags |= FC_RQST_STATE_DONE;
+		job->job_done(job);
+		kfree(info);
+	}
+	fc_frame_free(fp);
+	mutex_unlock(&lport->lp_mutex);
+}
+
+/**
+ * fc_lport_els_request() - Send ELS pass-thru request
+ * @job: The bsg fc pass-thru job structure
+ * @lport: The local port sending the request
+ * @did: The destination port id.
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
+ */
+static int fc_lport_els_request(struct fc_bsg_job *job,
+				struct fc_lport *lport,
+				u32 did, u32 tov)
+{
+	struct fc_bsg_info *info;
+	struct fc_frame *fp;
+	struct fc_frame_header *fh;
+	char *pp;
+	int len;
+
+	fp = fc_frame_alloc(lport, sizeof(struct fc_frame_header) +
+			    job->request_payload.payload_len);
+	if (!fp)
+		return -ENOMEM;
+
+	len = job->request_payload.payload_len;
+	pp = fc_frame_payload_get(fp, len);
+
+	sg_copy_to_buffer(job->request_payload.sg_list,
+			  job->request_payload.sg_cnt,
+			  pp, len);
+
+	fh = fc_frame_header_get(fp);
+	fh->fh_r_ctl = FC_RCTL_ELS_REQ;
+	hton24(fh->fh_d_id, did);
+	hton24(fh->fh_s_id, fc_host_port_id(lport->host));
+	fh->fh_type = FC_TYPE_ELS;
+	hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
+	       FC_FC_END_SEQ | FC_FC_SEQ_INIT);
+	fh->fh_cs_ctl = 0;
+	fh->fh_df_ctl = 0;
+	fh->fh_parm_offset = 0;
+
+	info = kzalloc(sizeof(struct fc_bsg_info), GFP_KERNEL);
+	if (!info) {
+		fc_frame_free(fp);
+		return -ENOMEM;
+	}
+
+	info->job = job;
+	info->lport = lport;
+	info->rsp_code = ELS_LS_ACC;
+	info->nents = job->reply_payload.sg_cnt;
+	info->sg = job->reply_payload.sg_list;
+
+	if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp,
+				     NULL, info, tov))
+		return -ECOMM;
+	return 0;
+}
+
+/**
+ * fc_lport_ct_request() - Send CT pass-thru request
+ * @job:   The bsg fc pass-thru job structure
+ * @lport: The local port sending the request
+ * @did:   The destination FC-ID
+ * @tov:   The time to wait for a response
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
+ */
+static int fc_lport_ct_request(struct fc_bsg_job *job,
+			       struct fc_lport *lport, u32 did, u32 tov)
+{
+	struct fc_bsg_info *info;
+	struct fc_frame *fp;
+	struct fc_frame_header *fh;
+	struct fc_ct_req *ct;
+	size_t len;
+
+	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
+			    job->request_payload.payload_len);
+	if (!fp)
+		return -ENOMEM;
+
+	len = job->request_payload.payload_len;
+	ct = fc_frame_payload_get(fp, len);
+
+	sg_copy_to_buffer(job->request_payload.sg_list,
+			  job->request_payload.sg_cnt,
+			  ct, len);
+
+	fh = fc_frame_header_get(fp);
+	fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL;
+	hton24(fh->fh_d_id, did);
+	hton24(fh->fh_s_id, fc_host_port_id(lport->host));
+	fh->fh_type = FC_TYPE_CT;
+	hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
+	       FC_FC_END_SEQ | FC_FC_SEQ_INIT);
+	fh->fh_cs_ctl = 0;
+	fh->fh_df_ctl = 0;
+	fh->fh_parm_offset = 0;
+
+	info = kzalloc(sizeof(struct fc_bsg_info), GFP_KERNEL);
+	if (!info) {
+		fc_frame_free(fp);
+		return -ENOMEM;
+	}
+
+	info->job = job;
+	info->lport = lport;
+	info->rsp_code = FC_FS_ACC;
+	info->nents = job->reply_payload.sg_cnt;
+	info->sg = job->reply_payload.sg_list;
+
+	if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp,
+				     NULL, info, tov))
+		return -ECOMM;
+	return 0;
+}
+
+/**
+ * fc_lport_bsg_request() - The common entry point for sending
+ *                          fc pass-thru requests
+ * @job: The fc pass-thru job structure
+ */
+int fc_lport_bsg_request(struct fc_bsg_job *job)
+{
+	struct request *rsp = job->req->next_rq;
+	struct Scsi_Host *shost = job->shost;
+	struct fc_lport *lport = shost_priv(shost);
+	struct fc_rport *rport;
+	struct fc_rport_priv *rdata;
+	int rc = -EINVAL;
+	u32 did;
+
+	job->reply->reply_payload_rcv_len = 0;
+	rsp->resid_len = job->reply_payload.payload_len;
+
+	mutex_lock(&lport->lp_mutex);
+
+	switch (job->request->msgcode) {
+	case FC_BSG_RPT_ELS:
+		rport = job->rport;
+		if (!rport)
+			break;
+
+		rdata = rport->dd_data;
+		rc = fc_lport_els_request(job, lport, rport->port_id,
+					  rdata->e_d_tov);
+		break;
+
+	case FC_BSG_RPT_CT:
+		rport = job->rport;
+		if (!rport)
+			break;
+
+		rdata = rport->dd_data;
+		rc = fc_lport_ct_request(job, lport, rport->port_id,
+					 rdata->e_d_tov);
+		break;
+
+	case FC_BSG_HST_CT:
+		did = ntoh24(job->request->rqst_data.h_ct.port_id);
+		if (did == FC_FID_DIR_SERV)
+			rdata = lport->dns_rp;
+		else
+			rdata = lport->tt.rport_lookup(lport, did);
+
+		if (!rdata)
+			break;
+
+		rc = fc_lport_ct_request(job, lport, did, rdata->e_d_tov);
+		break;
+
+	case FC_BSG_HST_ELS_NOLOGIN:
+		did = ntoh24(job->request->rqst_data.h_els.port_id);
+		rc = fc_lport_els_request(job, lport, did, lport->e_d_tov);
+		break;
+	}
+
+	mutex_unlock(&lport->lp_mutex);
+	return rc;
+}
+EXPORT_SYMBOL(fc_lport_bsg_request);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 8258edf..54df9fe 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -26,6 +26,7 @@
 
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_bsg_fc.h>
 
 #include <scsi/fc/fc_fcp.h>
 #include <scsi/fc/fc_ns.h>
@@ -831,6 +832,12 @@ void fc_vport_setlink(struct fc_lport *vn_port);
 void fc_vports_linkchange(struct fc_lport *n_port);
 
 /*
+ * Issue fc pass-thru request via bsg interface
+ */
+int fc_lport_bsg_request(struct fc_bsg_job *job);
+
+
+/*
  * REMOTE PORT LAYER
  *****************************/
 int fc_rport_init(struct fc_lport *lp);


  parent reply	other threads:[~2009-11-03 19:47 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-03 19:45 [PATCH 00/54] libfc, libfcoe, fcoe and fnic updates for 2.6.33 Robert Love
2009-11-03 19:45 ` [PATCH 01/54] fnic: Allocate OS interrupt resources just before enabling interrupts Robert Love
2009-11-03 19:45 ` [PATCH 02/54] fcoe: Increase FCOE_MAX_LUN to 0xFFFF (65535) Robert Love
2009-11-03 19:45 ` [PATCH 03/54] libfc: Move non-common routines and prototypes out of libfc.h Robert Love
2009-11-03 19:45 ` [PATCH 04/54] libfc: Remove fc_fcp_complete Robert Love
2009-11-03 19:45 ` [PATCH 05/54] libfc: Add libfc/fc_libfc.[ch] for libfc internal routines Robert Love
2009-11-03 19:46 ` [PATCH 06/54] libfc: Move libfc_init and libfc_exit to fc_libfc.c Robert Love
2009-11-03 19:46 ` [PATCH 07/54] libfc: changes to libfc_host_alloc to consolidate initialization with allocation Robert Love
2009-11-03 19:46 ` [PATCH 08/54] libfc: add some generic NPIV support routines to libfc Robert Love
2009-11-03 19:46 ` [PATCH 09/54] libfc: vport link handling and fc_vport state managment Robert Love
2009-11-03 19:46 ` [PATCH 10/54] libfc, libfcoe: FDISC ELS for NPIV Robert Love
2009-11-03 19:46 ` [PATCH 11/54] libfcoe, fcoe: libfcoe NPIV support Robert Love
2009-11-03 19:46 ` [PATCH 12/54] fcoe: add a separate scsi transport template for NPIV vports Robert Love
2009-11-03 19:46 ` [PATCH 13/54] fcoe: NPIV vport create/destroy Robert Love
2009-11-03 19:46 ` [PATCH 14/54] libfc: RPN_ID is obsolete and unnecessary Robert Love
2009-11-03 19:46 ` [PATCH 15/54] libfc: RNN_ID may be required before RSNN_NN with some switches Robert Love
2009-11-03 19:46 ` [PATCH 16/54] libfc: Register Symbolic Node Name (RSNN_NN) Robert Love
2009-11-03 19:47 ` [PATCH 17/54] libfc: Register Symbolic Port Name (RSPN_ID) Robert Love
2009-11-03 19:47 ` [PATCH 18/54] libfc: combine name server registration response handlers Robert Love
2009-11-03 19:47 ` [PATCH 19/54] libfc: combine name server registration request functions Robert Love
2009-11-03 19:47 ` [PATCH 20/54] fcoe: vport symbolic name support Robert Love
2009-11-03 19:47 ` [PATCH 21/54] libfc: Export FC headers Robert Love
2009-11-03 19:47 ` [PATCH 22/54] libfc: Add routine to copy data from a buffer to a SG list Robert Love
2009-11-03 19:47 ` Robert Love [this message]
2009-11-03 19:47 ` [PATCH 24/54] libfc: Formatting cleanups across libfc Robert Love
2009-11-03 19:47 ` [PATCH 25/54] libfcoe: formatting and comment cleanups Robert Love
2009-11-03 19:47 ` [PATCH 26/54] fcoe: Formatting cleanups and commenting Robert Love
2009-11-03 19:47 ` [PATCH 27/54] fcoe, libfc: use single frame allocation API Robert Love
2009-11-03 19:48 ` [PATCH 28/54] libfc: reduce can_queue for all FCP frame allocation failures Robert Love
2009-11-03 19:48 ` [PATCH 29/54] libfc: adds can_queue ramp up Robert Love
2009-11-03 19:48 ` [PATCH 30/54] libfcoe: Allow FIP to be disabled by the driver Robert Love
2009-11-03 19:48 ` [PATCH 31/54] libfcoe: fip: use SCSI host number to identify debug messages Robert Love
2009-11-03 19:48 ` [PATCH 32/54] libfcoe: fip: allow FIP receive to be called from IRQ Robert Love
2009-11-03 19:48 ` [PATCH 33/54] libfcoe: FIP should report link to libfc whether selected or not Robert Love
2009-11-03 19:48 ` [PATCH 34/54] libfcoe: don't send ELS in FIP mode if no FCF selected Robert Love
2009-11-03 19:48 ` [PATCH 35/54] fcoe: remove extra function decalrations Robert Love
2009-11-03 19:48 ` [PATCH 36/54] fcoe: add check to fail gracefully in bonding mode Robert Love
2009-11-03 19:48 ` [PATCH 37/54] libfc: fix RNN_ID smashing skb payload Robert Love
2009-11-03 19:48 ` [PATCH 38/54] libfc: fix symbolic name registrations smashing skb data Robert Love
2009-11-03 19:49 ` [PATCH 39/54] libfc: fix fc_els_resp_type to correct display of CT responses Robert Love
2009-11-03 19:49 ` [PATCH 40/54] libfc: add set_fid function to libfc template Robert Love
2009-11-03 19:49 ` [PATCH 41/54] libfc: add host number to lport link up/down messages Robert Love
2009-11-03 19:49 ` [PATCH 42/54] libfcoe: fcoe: simplify receive FLOGI response Robert Love
2009-11-03 19:49 ` [PATCH 43/54] fnic: Add FIP support to the fnic driver Robert Love
2009-11-03 19:49 ` [PATCH 44/54] libfc: register FC4 features with the FC switch Robert Love
2009-11-03 19:49 ` [PATCH 45/54] fnic: enable bsg pass-thru for fcping Robert Love
2009-11-03 19:49 ` [PATCH 46/54] fcoe: Fix checking san mac address Robert Love
2009-11-03 19:49 ` [PATCH 47/54] fcoe: Fix getting san mac for VLAN interface Robert Love
2009-11-03 19:49 ` [PATCH 48/54] fcoe: Fix setting lport's WWNN/WWPN to use san mac address Robert Love
2009-11-03 19:49 ` [PATCH 49/54] libfc: do not use DID_NO_CONNECT for pkt alloc failures Robert Love
2009-11-03 19:49 ` [PATCH 50/54] fcoe: Fix using VLAN ID in creating lport's WWWN/WWPN Robert Love
2009-11-03 19:50 ` [PATCH 51/54] libfc, fcoe: fixes for highmem skb linearize panics Robert Love
2009-11-03 19:50 ` [PATCH 52/54] libfc: fix an issue of pending exch/es after i/f destroyed or rmmod fcoe Robert Love
2009-11-03 19:50 ` [PATCH 53/54] libfcoe: Do not pad FIP keep-alive to full frame size Robert Love
2009-11-03 19:50 ` [PATCH 54/54] libfc fcoe: increase ELS and CT timeouts Robert Love

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091103194733.4085.28246.stgit@localhost.localdomain \
    --to=robert.w.love@intel.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=steve.ma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox