public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] create scsi bsg lib
@ 2011-07-22 10:04 michaelc
  2011-07-22 10:04 ` [RFC PATCH 01/10] scsi transport: add bsg callouts michaelc
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi

The iSCSI drivers want to use bsg for things like flash updates.
When people were sending patches for this, they were just
cutting and pasting the FC bsg code and renaming structs/functions,
so the following patches move the FC bsg code to a scsi lib.

The Qlogic developers and I have converted the FC drivers to the
new lib, but we have not tested all the driver specific patches
lately. In this sending we are more looking for comments
on the updated approach.

What has changed since the last posting is just that instead
of adding function pointers as args to a lot of the lib
functions we added some fields on the scsi transport template.
There is now 1 for queueing and 1 for timeout handling. It
seems cleaner this way.

The LLD code has not changed from my last posting, so hopefully if
the patches worked before they should still work.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC PATCH 01/10] scsi transport: add bsg callouts
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib michaelc
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This patch adds a bsg queueing and timeout function
callout to the scsi host transport template. In the
next patches the transport classes will use this along
with the scsi_bsg lib.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 include/scsi/scsi_transport.h |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index 0de32cd..2167b8c 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -25,6 +25,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 
+struct scsi_bsg_job;
+
 struct scsi_transport_template {
 	/* the attribute containers */
 	struct transport_container host_attrs;
@@ -68,6 +70,27 @@ struct scsi_transport_template {
 	enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *);
 
 	/*
+	 * This is an optional routine that allows the transport to become
+	 * involved when a bsg req timer fires. 0 should be returned on
+	 * success and a -Exyz code should be returned on a error.
+	 * If -EAGAIN is returned we give the request more time.
+	 */
+	int (*eh_bsg_job_timed_out)(struct scsi_bsg_job *);
+
+	/*
+	 * This is optional. LLDDs should set this to the amount of space
+	 * it needs for a bsg_job that is queued to @queue_bsg_job.
+	 */
+	int bsg_job_size;
+
+	/*
+	 * This is a an optional routine that is used to queue a bsg job
+	 * to the LLDD. The LLDD should return 0 for success and a -Exyz
+	 * error code for a failure.
+	 */
+	int (*queue_bsg_job)(struct scsi_bsg_job *);
+
+	/*
 	 * Used as callback for the completion of i_t_nexus request
 	 * for target drivers.
 	 */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
  2011-07-22 10:04 ` [RFC PATCH 01/10] scsi transport: add bsg callouts michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 16:31   ` FUJITA Tomonori
  2011-07-22 10:04 ` [RFC PATCH 03/10] FC class: convert to scsi bsg lib michaelc
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This moves the FC class bsg code to a scsi lib, so
all drivers and classes do not have to duplicate common
bits.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/Kconfig    |    6 +
 drivers/scsi/Makefile   |    1 +
 drivers/scsi/scsi_bsg.c |  374 +++++++++++++++++++++++++++++++++++++++++++++++
 include/scsi/Kbuild     |    1 +
 include/scsi/scsi_bsg.h |   83 +++++++++++
 5 files changed, 465 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/scsi_bsg.c
 create mode 100644 include/scsi/scsi_bsg.h

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4a1f029..327ec7e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -47,6 +47,11 @@ config SCSI_TGT
 	  If you want to use SCSI target mode drivers enable this option.
 	  If you choose M, the module will be called scsi_tgt.
 
+config SCSI_BSG
+	bool
+	default	n
+	select BLK_DEV_BSG
+
 config SCSI_NETLINK
 	bool
 	default	n
@@ -294,6 +299,7 @@ config SCSI_FC_ATTRS
 	tristate "FiberChannel Transport Attributes"
 	depends on SCSI
 	select SCSI_NETLINK
+	select SCSI_BSG
 	help
 	  If you wish to export transport-specific information about
 	  each attached FiberChannel device to sysfs, say Y.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 7ad0b8a..0cdb572 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -162,6 +162,7 @@ scsi_mod-y			+= scsi.o hosts.o scsi_ioctl.o constants.o \
 				   scsicam.o scsi_error.o scsi_lib.o
 scsi_mod-$(CONFIG_SCSI_DMA)	+= scsi_lib_dma.o
 scsi_mod-y			+= scsi_scan.o scsi_sysfs.o scsi_devinfo.o
+scsi_mod-$(CONFIG_SCSI_BSG)	+= scsi_bsg.o
 scsi_mod-$(CONFIG_SCSI_NETLINK)	+= scsi_netlink.o
 scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
new file mode 100644
index 0000000..89b507e
--- /dev/null
+++ b/drivers/scsi/scsi_bsg.c
@@ -0,0 +1,374 @@
+/*
+ *  BSG helper library for scsi classes
+ *
+ *  Copyright (C) 2008   James Smart, Emulex Corporation
+ *  Copyright (C) 2010   Red Hat, Inc.  All rights reserved.
+ *  Copyright (C) 2010   Mike Christie
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <scsi/scsi_bsg.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+
+/**
+ * scsi_destroy_bsg_job - routine to teardown/delete a bsg job
+ * @job: scsi_bsg_job that is to be torn down
+ */
+static void scsi_destroy_bsg_job(struct scsi_bsg_job *job)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&job->job_lock, flags);
+	if (job->ref_cnt) {
+		spin_unlock_irqrestore(&job->job_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&job->job_lock, flags);
+
+	put_device(job->dev);	/* release reference for the request */
+
+	kfree(job->request_payload.sg_list);
+	kfree(job->reply_payload.sg_list);
+	kfree(job);
+}
+
+/**
+ * scsi_bsg_job_done - completion routine for bsg requests
+ * @job: scsi_bsg_job that is complete
+ * @result: job reply result
+ * @reply_payload_rcv_len: length of payload recvd
+ */
+void scsi_bsg_job_done(struct scsi_bsg_job *job, int result,
+		       unsigned int reply_payload_rcv_len)
+{
+	struct request *req = job->req;
+	struct request *rsp = req->next_rq;
+	int err;
+
+	err = job->req->errors = result;
+	if (err < 0)
+		/* we're only returning the result field in the reply */
+		job->req->sense_len = sizeof(u32);
+	else
+		job->req->sense_len = job->reply_len;
+	/* we assume all request payload was transferred, residual == 0 */
+	req->resid_len = 0;
+
+	if (rsp) {
+		WARN_ON(reply_payload_rcv_len > rsp->resid_len);
+
+		/* set reply (bidi) residual */
+		rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len);
+	}
+	blk_complete_request(req);
+}
+EXPORT_SYMBOL_GPL(scsi_bsg_job_done);
+
+/**
+ * scsi_bsg_softirq_done - softirq done routine for destroying the bsg requests
+ * @rq: BSG request that holds the job to be destroyed
+ */
+static void scsi_bsg_softirq_done(struct request *rq)
+{
+	struct scsi_bsg_job *job = rq->special;
+	unsigned long flags;
+
+	spin_lock_irqsave(&job->job_lock, flags);
+	job->state_flags |= SCSI_RQST_STATE_DONE;
+	job->ref_cnt--;
+	spin_unlock_irqrestore(&job->job_lock, flags);
+
+	blk_end_request_all(rq, rq->errors);
+	scsi_destroy_bsg_job(job);
+}
+
+/**
+ * scsi_bsg_job_timeout - handler for when a bsg request timesout
+ * @req: request that timed out
+ */
+static enum blk_eh_timer_return scsi_bsg_job_timeout(struct request *req)
+{
+	struct scsi_bsg_job *job = req->special;
+	struct Scsi_Host *shost = job->shost;
+	unsigned long flags;
+	int err = 0, done = 0;
+
+	spin_lock_irqsave(&job->job_lock, flags);
+	if (job->state_flags & SCSI_RQST_STATE_DONE)
+		done = 1;
+	else
+		job->ref_cnt++;
+	spin_unlock_irqrestore(&job->job_lock, flags);
+
+	if (!done && shost->transportt->eh_bsg_job_timed_out) {
+		/* call LLDD to abort the i/o as it has timed out */
+		err = shost->transportt->eh_bsg_job_timed_out(job);
+		if (err == -EAGAIN) {
+			job->ref_cnt--;
+			return BLK_EH_RESET_TIMER;
+		} else if (err)
+			printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
+				"abort failed with status %d\n", err);
+	}
+
+	/* the blk_end_sync_io() doesn't check the error */
+	if (done)
+		return BLK_EH_NOT_HANDLED;
+	else
+		return BLK_EH_HANDLED;
+}
+
+static int scsi_bsg_map_buffer(struct scsi_bsg_buffer *buf, struct request *req)
+{
+	size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
+
+	BUG_ON(!req->nr_phys_segments);
+
+	buf->sg_list = kzalloc(sz, GFP_KERNEL);
+	if (!buf->sg_list)
+		return -ENOMEM;
+	sg_init_table(buf->sg_list, req->nr_phys_segments);
+	buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
+	buf->payload_len = blk_rq_bytes(req);
+	return 0;
+}
+
+/**
+ * scsi_bsg_create_job - create the scsi_bsg_job structure for the bsg request
+ * @shost: SCSI Host corresponding to the bsg object
+ * @dev: device that is being sent the bsg request
+ * @req: BSG request that needs a job structure
+ */
+static int scsi_bsg_create_job(struct Scsi_Host *shost, struct device *dev,
+			       struct request *req)
+{
+	struct request *rsp = req->next_rq;
+	struct scsi_bsg_job *job;
+	int ret;
+
+	BUG_ON(req->special);
+
+	job = kzalloc(sizeof(struct scsi_bsg_job) +
+		      shost->transportt->bsg_job_size, GFP_KERNEL);
+	if (!job)
+		return -ENOMEM;
+
+	/*
+	 * Note: this is a bit silly.
+	 * The request gets formatted as a SGIO v4 ioctl request, which
+	 * then gets reformatted as a blk request, which then gets
+	 * reformatted as a scsi bsg request. And on completion, we have
+	 * to wrap return results such that SGIO v4 thinks it was a scsi
+	 * status.  I hope this was all worth it.
+	 */
+
+	req->special = job;
+	job->shost = shost;
+	job->req = req;
+	if (shost->transportt->bsg_job_size)
+		job->dd_data = (void *)&job[1];
+	spin_lock_init(&job->job_lock);
+	job->request = req->cmd;
+	job->request_len = req->cmd_len;
+	job->reply = req->sense;
+	job->reply_len = SCSI_SENSE_BUFFERSIZE;	/* Size of sense buffer
+						 * allocated */
+	if (req->bio) {
+		ret = scsi_bsg_map_buffer(&job->request_payload, req);
+		if (ret)
+			goto failjob_rls_job;
+	}
+	if (rsp && rsp->bio) {
+		ret = scsi_bsg_map_buffer(&job->reply_payload, rsp);
+		if (ret)
+			goto failjob_rls_rqst_payload;
+	}
+	job->job_done = scsi_bsg_job_done;
+	job->dev = dev;
+	/* take a reference for the request */
+	get_device(job->dev);
+	job->ref_cnt = 1;
+	return 0;
+
+failjob_rls_rqst_payload:
+	kfree(job->request_payload.sg_list);
+failjob_rls_job:
+	kfree(job);
+	return -ENOMEM;
+}
+
+/*
+ * scsi_bsg_goose_queue - restart queue in case it was stopped
+ * @dev: device that owns queue
+ * @q: request q to be restarted
+ */
+void scsi_bsg_goose_queue(struct device *dev, struct request_queue *q)
+{
+	if (!q)
+		return;
+
+	/*
+	 * This get/put dance makes no sense
+	 */
+
+	get_device(dev);
+	blk_run_queue_async(q);
+	put_device(dev);
+}
+EXPORT_SYMBOL_GPL(scsi_bsg_goose_queue);
+
+/**
+ * scsi_bsg_request_fn - generic handler for bsg requests
+ * @q: request queue to manage
+ *
+ * On error the create_bsg_job function should return a -Exyz error value
+ * that will be set to the req->errors.
+ */
+static void scsi_bsg_request_fn(struct request_queue *q)
+{
+	struct device *dev = q->queuedata;
+	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct request *req;
+	struct scsi_bsg_job *job;
+	int ret;
+
+	if (!shost)
+		return;
+
+	if (!get_device(dev))
+		return;
+
+	while (1) {
+		req = blk_fetch_request(q);
+		if (!req)
+			break;
+		spin_unlock_irq(q->queue_lock);
+
+		ret = scsi_bsg_create_job(shost, dev, req);
+		if (ret) {
+			req->errors = ret;
+			blk_end_request_all(req, ret);
+			spin_lock_irq(q->queue_lock);
+			continue;
+		}
+
+		job = req->special;
+		/* the dispatch routines will unlock the queue_lock */
+		ret = shost->transportt->queue_bsg_job(job);
+		spin_lock_irq(q->queue_lock);
+		if (ret)
+			break;
+	}
+
+	spin_unlock_irq(q->queue_lock);
+	put_device(dev);
+	spin_lock_irq(q->queue_lock);
+}
+
+/**
+ * scsi_bsg_add - Create and add the bsg hooks so we can receive requests
+ * @dev: device to attach bsg device to
+ */
+struct request_queue *scsi_bsg_add(struct device *dev, char *name)
+{
+	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct request_queue *q;
+
+	if (!shost)
+		return NULL;
+
+	q = __scsi_alloc_queue(shost, scsi_bsg_request_fn);
+	if (!q) {
+		printk(KERN_ERR "%s: bsg interface failed to "
+				"initialize - no request queue\n",
+				 dev->kobj.name);
+		return NULL;
+	}
+	q->queuedata = dev;
+
+	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
+	blk_queue_softirq_done(q, scsi_bsg_softirq_done);
+	blk_queue_rq_timed_out(q, scsi_bsg_job_timeout);
+	blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
+
+	if (bsg_register_queue(q, dev, name, NULL)) {
+		printk(KERN_ERR "%s: bsg interface failed to "
+		       "initialize - register queue\n", dev->kobj.name);
+		blk_cleanup_queue(q);
+		return NULL;
+	}
+
+	return q;
+}
+EXPORT_SYMBOL_GPL(scsi_bsg_add);
+
+/**
+ * scsi_bsg_remove - Deletes the bsg dev from the q
+ * @q:	the request_queue that is to be torn down.
+ *
+ * Notes:
+ *   Before unregistering the queue empty any requests that are blocked
+ */
+void scsi_bsg_remove(struct request_queue *q)
+{
+	struct request *req; /* block request */
+	int counts; /* totals for request_list count and starved */
+
+	if (q) {
+		/* Stop taking in new requests */
+		spin_lock_irq(q->queue_lock);
+		blk_stop_queue(q);
+
+		/* drain all requests in the queue */
+		while (1) {
+			/* need the lock to fetch a request
+			 * this may fetch the same reqeust as the previous pass
+			 */
+			req = blk_fetch_request(q);
+			/* save requests in use and starved */
+			counts = q->rq.count[0] + q->rq.count[1] +
+				 q->rq.starved[0] + q->rq.starved[1];
+			spin_unlock_irq(q->queue_lock);
+			/* any requests still outstanding? */
+			if (counts == 0)
+				break;
+
+			/* This may be the same req as the previous iteration,
+			 * always send the blk_end_request_all after a prefetch.
+			 * It is not okay to not end the request because the
+			 * prefetch started the request.
+			 */
+			if (req) {
+				/* return -ENXIO to indicate that this queue is
+				 * going away
+				 */
+				req->errors = -ENXIO;
+				blk_end_request_all(req, -ENXIO);
+			}
+
+			msleep(200); /* allow bsg to possibly finish */
+			spin_lock_irq(q->queue_lock);
+		}
+		bsg_unregister_queue(q);
+		blk_cleanup_queue(q);
+	}
+}
+EXPORT_SYMBOL_GPL(scsi_bsg_remove);
diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild
index f2b9491..df8f159 100644
--- a/include/scsi/Kbuild
+++ b/include/scsi/Kbuild
@@ -1,4 +1,5 @@
 header-y += scsi_netlink.h
 header-y += scsi_netlink_fc.h
 header-y += scsi_bsg_fc.h
+header-y += scsi_bsg_iscsi.h
 header-y += fc/
diff --git a/include/scsi/scsi_bsg.h b/include/scsi/scsi_bsg.h
new file mode 100644
index 0000000..3e15ad0
--- /dev/null
+++ b/include/scsi/scsi_bsg.h
@@ -0,0 +1,83 @@
+/*
+ *  BSG helper library for scsi classes
+ *
+ *  Copyright (C) 2008   James Smart, Emulex Corporation
+ *  Copyright (C) 2010   Red Hat, Inc.  All rights reserved.
+ *  Copyright (C) 2010   Mike Christie
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef _SCSI_BSG_
+#define _SCSI_BSG_
+
+#include <linux/blkdev.h>
+struct Scsi_Host;
+struct request;
+struct device;
+struct scatterlist;
+struct request_queue;
+
+struct scsi_bsg_buffer {
+	unsigned int payload_len;
+	int sg_cnt;
+	struct scatterlist *sg_list;
+};
+
+/* Values for scsi_bsg_job->state_flags (bitflags) */
+#define SCSI_RQST_STATE_INPROGRESS	0
+#define SCSI_RQST_STATE_DONE		1
+
+struct scsi_bsg_job {
+	struct Scsi_Host *shost;
+
+	struct device *dev;
+	struct request *req;
+	spinlock_t job_lock;
+	unsigned int state_flags;
+	unsigned int ref_cnt;
+
+	void (*job_done)(struct scsi_bsg_job *job, int result,
+			 unsigned int reply_payload_rcv_len);
+
+	/* Transport/driver specific request/reply structs */
+	void *request;
+	void *reply;
+
+	unsigned int request_len;
+	unsigned int reply_len;
+	/*
+	 * On entry : reply_len indicates the buffer size allocated for
+	 * the reply.
+	 *
+	 * Upon completion : the message handler must set reply_len
+	 *  to indicates the size of the reply to be returned to the
+	 *  caller.
+	 */
+
+	/* DMA payloads for the request/response */
+	struct scsi_bsg_buffer request_payload;
+	struct scsi_bsg_buffer reply_payload;
+
+	void *dd_data;		/* Used for driver-specific storage */
+};
+
+void scsi_bsg_job_done(struct scsi_bsg_job *job, int result,
+		       unsigned int reply_payload_rcv_len);
+struct request_queue *scsi_bsg_add(struct device *dev, char *name);
+void scsi_bsg_remove(struct request_queue *q);
+void scsi_bsg_goose_queue(struct device *dev, struct request_queue *q);
+
+#endif
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 03/10] FC class: convert to scsi bsg lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
  2011-07-22 10:04 ` [RFC PATCH 01/10] scsi transport: add bsg callouts michaelc
  2011-07-22 10:04 ` [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 04/10] iscsi class: add bsg support to iscsi class michaelc
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This patch just converts the FC class to use the bsg
lib.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/scsi_transport_fc.c |  533 ++++++--------------------------------
 include/scsi/scsi_transport_fc.h |   53 +---
 2 files changed, 93 insertions(+), 493 deletions(-)

diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 1b21491..ec445aa 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -39,6 +39,7 @@
 #include <net/netlink.h>
 #include <scsi/scsi_netlink_fc.h>
 #include <scsi/scsi_bsg_fc.h>
+#include <scsi/scsi_bsg.h>
 #include "scsi_priv.h"
 #include "scsi_transport_fc_internal.h"
 
@@ -49,8 +50,8 @@ static int fc_vport_setup(struct Scsi_Host *shost, int channel,
 	struct fc_vport **vport);
 static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
 static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
-static void fc_bsg_remove(struct request_queue *);
-static void fc_bsg_goose_queue(struct fc_rport *);
+static int fc_bsg_job_timed_out(struct scsi_bsg_job *);
+static int fc_bsg_dispatch(struct scsi_bsg_job *);
 
 /*
  * Module Parameters
@@ -450,7 +451,7 @@ static int fc_host_remove(struct transport_container *tc, struct device *dev,
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 
-	fc_bsg_remove(fc_host->rqst_q);
+	scsi_bsg_remove(fc_host->rqst_q);
 	return 0;
 }
 
@@ -2175,6 +2176,10 @@ fc_attach_transport(struct fc_function_template *ft)
 
 	i->t.user_scan = fc_user_scan;
 
+	i->t.bsg_job_size = ft->dd_bsg_size;
+	i->t.eh_bsg_job_timed_out = fc_bsg_job_timed_out;
+	i->t.queue_bsg_job = fc_bsg_dispatch;
+
 	/* target-mode drivers' functions */
 	i->t.tsk_mgmt_response = fc_tsk_mgmt_response;
 	i->t.it_nexus_response = fc_it_nexus_response;
@@ -2536,7 +2541,7 @@ fc_rport_final_delete(struct work_struct *work)
 	if (do_callback)
 		i->f->dev_loss_tmo_callbk(rport);
 
-	fc_bsg_remove(rport->rqst_q);
+	scsi_bsg_remove(rport->rqst_q);
 
 	transport_remove_device(dev);
 	device_del(dev);
@@ -2792,7 +2797,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
 					spin_unlock_irqrestore(shost->host_lock,
 							flags);
 
-				fc_bsg_goose_queue(rport);
+				scsi_bsg_goose_queue(&rport->dev,
+						     rport->rqst_q);
 
 				return rport;
 			}
@@ -3514,236 +3520,38 @@ fc_vport_sched_delete(struct work_struct *work)
  * BSG support
  */
 
-
-/**
- * fc_destroy_bsgjob - routine to teardown/delete a fc bsg job
- * @job:	fc_bsg_job that is to be torn down
- */
-static void
-fc_destroy_bsgjob(struct fc_bsg_job *job)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&job->job_lock, flags);
-	if (job->ref_cnt) {
-		spin_unlock_irqrestore(&job->job_lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&job->job_lock, flags);
-
-	put_device(job->dev);	/* release reference for the request */
-
-	kfree(job->request_payload.sg_list);
-	kfree(job->reply_payload.sg_list);
-	kfree(job);
-}
-
-/**
- * fc_bsg_jobdone - completion routine for bsg requests that the LLD has
- *                  completed
- * @job:	fc_bsg_job that is complete
- */
-static void
-fc_bsg_jobdone(struct fc_bsg_job *job)
-{
-	struct request *req = job->req;
-	struct request *rsp = req->next_rq;
-	int err;
-
-	err = job->req->errors = job->reply->result;
-
-	if (err < 0)
-		/* we're only returning the result field in the reply */
-		job->req->sense_len = sizeof(uint32_t);
-	else
-		job->req->sense_len = job->reply_len;
-
-	/* we assume all request payload was transferred, residual == 0 */
-	req->resid_len = 0;
-
-	if (rsp) {
-		WARN_ON(job->reply->reply_payload_rcv_len > rsp->resid_len);
-
-		/* set reply (bidi) residual */
-		rsp->resid_len -= min(job->reply->reply_payload_rcv_len,
-				      rsp->resid_len);
-	}
-	blk_complete_request(req);
-}
-
-/**
- * fc_bsg_softirq_done - softirq done routine for destroying the bsg requests
- * @rq:        BSG request that holds the job to be destroyed
- */
-static void fc_bsg_softirq_done(struct request *rq)
-{
-	struct fc_bsg_job *job = rq->special;
-	unsigned long flags;
-
-	spin_lock_irqsave(&job->job_lock, flags);
-	job->state_flags |= FC_RQST_STATE_DONE;
-	job->ref_cnt--;
-	spin_unlock_irqrestore(&job->job_lock, flags);
-
-	blk_end_request_all(rq, rq->errors);
-	fc_destroy_bsgjob(job);
-}
-
-/**
- * fc_bsg_job_timeout - handler for when a bsg request timesout
- * @req:	request that timed out
- */
-static enum blk_eh_timer_return
-fc_bsg_job_timeout(struct request *req)
+static void fc_bsg_fail_job(struct scsi_bsg_job *job, int ret)
 {
-	struct fc_bsg_job *job = (void *) req->special;
-	struct Scsi_Host *shost = job->shost;
-	struct fc_internal *i = to_fc_internal(shost->transportt);
-	unsigned long flags;
-	int err = 0, done = 0;
-
-	if (job->rport && job->rport->port_state == FC_PORTSTATE_BLOCKED)
-		return BLK_EH_RESET_TIMER;
-
-	spin_lock_irqsave(&job->job_lock, flags);
-	if (job->state_flags & FC_RQST_STATE_DONE)
-		done = 1;
-	else
-		job->ref_cnt++;
-	spin_unlock_irqrestore(&job->job_lock, flags);
-
-	if (!done && i->f->bsg_timeout) {
-		/* call LLDD to abort the i/o as it has timed out */
-		err = i->f->bsg_timeout(job);
-		if (err == -EAGAIN) {
-			job->ref_cnt--;
-			return BLK_EH_RESET_TIMER;
-		} else if (err)
-			printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
-				"abort failed with status %d\n", err);
-	}
-
-	/* the blk_end_sync_io() doesn't check the error */
-	if (done)
-		return BLK_EH_NOT_HANDLED;
-	else
-		return BLK_EH_HANDLED;
-}
-
-static int
-fc_bsg_map_buffer(struct fc_bsg_buffer *buf, struct request *req)
-{
-	size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
-
-	BUG_ON(!req->nr_phys_segments);
-
-	buf->sg_list = kzalloc(sz, GFP_KERNEL);
-	if (!buf->sg_list)
-		return -ENOMEM;
-	sg_init_table(buf->sg_list, req->nr_phys_segments);
-	buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
-	buf->payload_len = blk_rq_bytes(req);
-	return 0;
-}
-
-
-/**
- * fc_req_to_bsgjob - Allocate/create the fc_bsg_job structure for the
- *                   bsg request
- * @shost:	SCSI Host corresponding to the bsg object
- * @rport:	(optional) FC Remote Port corresponding to the bsg object
- * @req:	BSG request that needs a job structure
- */
-static int
-fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport,
-	struct request *req)
-{
-	struct fc_internal *i = to_fc_internal(shost->transportt);
-	struct request *rsp = req->next_rq;
-	struct fc_bsg_job *job;
-	int ret;
-
-	BUG_ON(req->special);
-
-	job = kzalloc(sizeof(struct fc_bsg_job) + i->f->dd_bsg_size,
-			GFP_KERNEL);
-	if (!job)
-		return -ENOMEM;
-
-	/*
-	 * Note: this is a bit silly.
-	 * The request gets formatted as a SGIO v4 ioctl request, which
-	 * then gets reformatted as a blk request, which then gets
-	 * reformatted as a fc bsg request. And on completion, we have
-	 * to wrap return results such that SGIO v4 thinks it was a scsi
-	 * status.  I hope this was all worth it.
-	 */
-
-	req->special = job;
-	job->shost = shost;
-	job->rport = rport;
-	job->req = req;
-	if (i->f->dd_bsg_size)
-		job->dd_data = (void *)&job[1];
-	spin_lock_init(&job->job_lock);
-	job->request = (struct fc_bsg_request *)req->cmd;
-	job->request_len = req->cmd_len;
-	job->reply = req->sense;
-	job->reply_len = SCSI_SENSE_BUFFERSIZE;	/* Size of sense buffer
-						 * allocated */
-	if (req->bio) {
-		ret = fc_bsg_map_buffer(&job->request_payload, req);
-		if (ret)
-			goto failjob_rls_job;
-	}
-	if (rsp && rsp->bio) {
-		ret = fc_bsg_map_buffer(&job->reply_payload, rsp);
-		if (ret)
-			goto failjob_rls_rqst_payload;
-	}
-	job->job_done = fc_bsg_jobdone;
-	if (rport)
-		job->dev = &rport->dev;
-	else
-		job->dev = &shost->shost_gendev;
-	get_device(job->dev);		/* take a reference for the request */
-
-	job->ref_cnt = 1;
-
-	return 0;
-
-
-failjob_rls_rqst_payload:
-	kfree(job->request_payload.sg_list);
-failjob_rls_job:
-	kfree(job);
-	return -ENOMEM;
+	struct fc_bsg_reply *bsg_reply = job->reply;
+	BUG_ON(job->reply_len < sizeof(uint32_t));
+	bsg_reply->reply_payload_rcv_len = 0;
+	/* return the errno failure code as the only status */
+	bsg_reply->result = ret;
+	job->reply_len = sizeof(uint32_t);
+	scsi_bsg_job_done(job, ret, 0);
 }
 
-
-enum fc_dispatch_result {
-	FC_DISPATCH_BREAK,	/* on return, q is locked, break from q loop */
-	FC_DISPATCH_LOCKED,	/* on return, q is locked, continue on */
-	FC_DISPATCH_UNLOCKED,	/* on return, q is unlocked, continue on */
-};
-
-
 /**
  * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD
- * @q:		fc host request queue
- * @shost:	scsi host rport attached to
+ * @shost:	scsi host
  * @job:	bsg job to be processed
  */
-static enum fc_dispatch_result
-fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost,
-			 struct fc_bsg_job *job)
+static int
+fc_bsg_host_dispatch(struct Scsi_Host *shost, struct scsi_bsg_job *job)
 {
 	struct fc_internal *i = to_fc_internal(shost->transportt);
 	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */
+	struct fc_bsg_request *bsg_req = job->request;
 	int ret;
 
+	/* check if we have the msgcode value at least */
+	if (job->request_len < sizeof(uint32_t)) {
+		ret = -ENOMSG;
+		goto fail_host_msg;
+	}
+
 	/* Validate the host command */
-	switch (job->request->msgcode) {
+	switch (bsg_req->msgcode) {
 	case FC_BSG_HST_ADD_RPORT:
 		cmdlen += sizeof(struct fc_bsg_host_add_rport);
 		break;
@@ -3775,8 +3583,8 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost,
 	case FC_BSG_HST_VENDOR:
 		cmdlen += sizeof(struct fc_bsg_host_vendor);
 		if ((shost->hostt->vendor_id == 0L) ||
-		    (job->request->rqst_data.h_vendor.vendor_id !=
-			shost->hostt->vendor_id)) {
+		    (bsg_req->rqst_data.h_vendor.vendor_id !=
+		     shost->hostt->vendor_id)) {
 			ret = -ESRCH;
 			goto fail_host_msg;
 		}
@@ -3795,54 +3603,34 @@ fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost,
 
 	ret = i->f->bsg_request(job);
 	if (!ret)
-		return FC_DISPATCH_UNLOCKED;
+		return 0;
 
 fail_host_msg:
-	/* return the errno failure code as the only status */
-	BUG_ON(job->reply_len < sizeof(uint32_t));
-	job->reply->reply_payload_rcv_len = 0;
-	job->reply->result = ret;
-	job->reply_len = sizeof(uint32_t);
-	fc_bsg_jobdone(job);
-	return FC_DISPATCH_UNLOCKED;
-}
-
-
-/*
- * fc_bsg_goose_queue - restart rport queue in case it was stopped
- * @rport:	rport to be restarted
- */
-static void
-fc_bsg_goose_queue(struct fc_rport *rport)
-{
-	if (!rport->rqst_q)
-		return;
-
-	/*
-	 * This get/put dance makes no sense
-	 */
-	get_device(&rport->dev);
-	blk_run_queue_async(rport->rqst_q);
-	put_device(&rport->dev);
+	fc_bsg_fail_job(job, ret);
+	return 0;
 }
 
 /**
  * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
- * @q:		rport request queue
  * @shost:	scsi host rport attached to
- * @rport:	rport request destined to
  * @job:	bsg job to be processed
  */
-static enum fc_dispatch_result
-fc_bsg_rport_dispatch(struct request_queue *q, struct Scsi_Host *shost,
-			 struct fc_rport *rport, struct fc_bsg_job *job)
+static int
+fc_bsg_rport_dispatch(struct Scsi_Host *shost, struct scsi_bsg_job *job)
 {
 	struct fc_internal *i = to_fc_internal(shost->transportt);
 	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */
+	struct fc_bsg_request *bsg_req = job->request;
 	int ret;
 
+	/* check if we have the msgcode value at least */
+	if (job->request_len < sizeof(uint32_t)) {
+		ret = -ENOMSG;
+		goto fail_rport_msg;
+	}
+
 	/* Validate the rport command */
-	switch (job->request->msgcode) {
+	switch (bsg_req->msgcode) {
 	case FC_BSG_RPT_ELS:
 		cmdlen += sizeof(struct fc_bsg_rport_els);
 		goto check_bidi;
@@ -3870,124 +3658,59 @@ check_bidi:
 
 	ret = i->f->bsg_request(job);
 	if (!ret)
-		return FC_DISPATCH_UNLOCKED;
+		return 0;
 
 fail_rport_msg:
-	/* return the errno failure code as the only status */
-	BUG_ON(job->reply_len < sizeof(uint32_t));
-	job->reply->reply_payload_rcv_len = 0;
-	job->reply->result = ret;
-	job->reply_len = sizeof(uint32_t);
-	fc_bsg_jobdone(job);
-	return FC_DISPATCH_UNLOCKED;
+	fc_bsg_fail_job(job, ret);
+	return 0;
 }
 
-
 /**
- * fc_bsg_request_handler - generic handler for bsg requests
- * @q:		request queue to manage
- * @shost:	Scsi_Host related to the bsg object
- * @rport:	FC remote port related to the bsg object (optional)
- * @dev:	device structure for bsg object
+ * fc_bsg_dispatch - process fc bsg requests and dispatch to LLDD
+ * @job:	bsg job to be processed
  */
-static void
-fc_bsg_request_handler(struct request_queue *q, struct Scsi_Host *shost,
-		       struct fc_rport *rport, struct device *dev)
+static int fc_bsg_dispatch(struct scsi_bsg_job *job)
 {
-	struct request *req;
-	struct fc_bsg_job *job;
-	enum fc_dispatch_result ret;
-
-	if (!get_device(dev))
-		return;
-
-	while (1) {
-		if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) &&
-		    !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
-			break;
-
-		req = blk_fetch_request(q);
-		if (!req)
-			break;
-
-		if (rport && (rport->port_state != FC_PORTSTATE_ONLINE)) {
-			req->errors = -ENXIO;
-			spin_unlock_irq(q->queue_lock);
-			blk_end_request_all(req, -ENXIO);
-			spin_lock_irq(q->queue_lock);
-			continue;
-		}
-
-		spin_unlock_irq(q->queue_lock);
-
-		ret = fc_req_to_bsgjob(shost, rport, req);
-		if (ret) {
-			req->errors = ret;
-			blk_end_request_all(req, ret);
-			spin_lock_irq(q->queue_lock);
-			continue;
-		}
-
-		job = req->special;
-
-		/* check if we have the msgcode value at least */
-		if (job->request_len < sizeof(uint32_t)) {
-			BUG_ON(job->reply_len < sizeof(uint32_t));
-			job->reply->reply_payload_rcv_len = 0;
-			job->reply->result = -ENOMSG;
-			job->reply_len = sizeof(uint32_t);
-			fc_bsg_jobdone(job);
-			spin_lock_irq(q->queue_lock);
-			continue;
-		}
-
-		/* the dispatch routines will unlock the queue_lock */
-		if (rport)
-			ret = fc_bsg_rport_dispatch(q, shost, rport, job);
-		else
-			ret = fc_bsg_host_dispatch(q, shost, job);
-
-		/* did dispatcher hit state that can't process any more */
-		if (ret == FC_DISPATCH_BREAK)
-			break;
-
-		/* did dispatcher had released the lock */
-		if (ret == FC_DISPATCH_UNLOCKED)
-			spin_lock_irq(q->queue_lock);
-	}
+	struct Scsi_Host *shost = job->shost;
 
-	spin_unlock_irq(q->queue_lock);
-	put_device(dev);
-	spin_lock_irq(q->queue_lock);
+	if (scsi_is_fc_rport(job->dev))
+		return fc_bsg_rport_dispatch(shost, job);
+	else
+		return fc_bsg_host_dispatch(shost, job);
 }
 
-
 /**
- * fc_bsg_host_handler - handler for bsg requests for a fc host
- * @q:		fc host request queue
+ * fc_bsg_job_timed_out - handler for when a bsg request timesout
+ * @job:       bsg job that timed out
  */
-static void
-fc_bsg_host_handler(struct request_queue *q)
+static int fc_bsg_job_timed_out(struct scsi_bsg_job *job)
+
 {
-	struct Scsi_Host *shost = q->queuedata;
+	struct Scsi_Host *shost = job->shost;
+	struct fc_internal *i = to_fc_internal(shost->transportt);
+	struct fc_rport *rport = fc_bsg_get_rport(job);
+	int err = 0;
 
-	fc_bsg_request_handler(q, shost, NULL, &shost->shost_gendev);
+	if (rport && rport->port_state == FC_PORTSTATE_BLOCKED)
+		return -EAGAIN;
+	if (i->f->bsg_timeout)
+		err = i->f->bsg_timeout(job);
+	return err;
 }
 
-
-/**
- * fc_bsg_rport_handler - handler for bsg requests for a fc rport
- * @q:		rport request queue
- */
-static void
-fc_bsg_rport_handler(struct request_queue *q)
+static int fc_bsg_rport_prep(struct request_queue *q, struct request *req)
 {
-	struct fc_rport *rport = q->queuedata;
-	struct Scsi_Host *shost = rport_to_shost(rport);
+	struct fc_rport *rport = dev_to_rport(q->queuedata);
 
-	fc_bsg_request_handler(q, shost, rport, &rport->dev);
-}
+	if (rport->port_state == FC_PORTSTATE_BLOCKED &&
+	    !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
+		return BLKPREP_DEFER;
 
+	if (rport->port_state != FC_PORTSTATE_ONLINE)
+		return BLKPREP_KILL;
+
+	return BLKPREP_OK;
+}
 
 /**
  * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests
@@ -4000,7 +3723,6 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
 	struct device *dev = &shost->shost_gendev;
 	struct fc_internal *i = to_fc_internal(shost->transportt);
 	struct request_queue *q;
-	int err;
 	char bsg_name[20];
 
 	fc_host->rqst_q = NULL;
@@ -4008,10 +3730,9 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
 	if (!i->f->bsg_request)
 		return -ENOTSUPP;
 
-	snprintf(bsg_name, sizeof(bsg_name),
-		 "fc_host%d", shost->host_no);
+	snprintf(bsg_name, sizeof(bsg_name), "fc_host%d", shost->host_no);
 
-	q = __scsi_alloc_queue(shost, fc_bsg_host_handler);
+	q = scsi_bsg_add(dev, bsg_name);
 	if (!q) {
 		printk(KERN_ERR "fc_host%d: bsg interface failed to "
 				"initialize - no request queue\n",
@@ -4019,21 +3740,6 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
 		return -ENOMEM;
 	}
 
-	q->queuedata = shost;
-	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
-	blk_queue_softirq_done(q, fc_bsg_softirq_done);
-	blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
-	blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT);
-
-	err = bsg_register_queue(q, dev, bsg_name, NULL);
-	if (err) {
-		printk(KERN_ERR "fc_host%d: bsg interface failed to "
-				"initialize - register queue\n",
-				shost->host_no);
-		blk_cleanup_queue(q);
-		return err;
-	}
-
 	fc_host->rqst_q = q;
 	return 0;
 }
@@ -4050,14 +3756,13 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
 	struct device *dev = &rport->dev;
 	struct fc_internal *i = to_fc_internal(shost->transportt);
 	struct request_queue *q;
-	int err;
 
 	rport->rqst_q = NULL;
 
 	if (!i->f->bsg_request)
 		return -ENOTSUPP;
 
-	q = __scsi_alloc_queue(shost, fc_bsg_rport_handler);
+	q = scsi_bsg_add(dev, NULL);
 	if (!q) {
 		printk(KERN_ERR "%s: bsg interface failed to "
 				"initialize - no request queue\n",
@@ -4065,83 +3770,11 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
 		return -ENOMEM;
 	}
 
-	q->queuedata = rport;
-	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
-	blk_queue_softirq_done(q, fc_bsg_softirq_done);
-	blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
-	blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
-
-	err = bsg_register_queue(q, dev, NULL, NULL);
-	if (err) {
-		printk(KERN_ERR "%s: bsg interface failed to "
-				"initialize - register queue\n",
-				 dev->kobj.name);
-		blk_cleanup_queue(q);
-		return err;
-	}
-
 	rport->rqst_q = q;
+	blk_queue_prep_rq(q, fc_bsg_rport_prep);
 	return 0;
 }
 
-
-/**
- * fc_bsg_remove - Deletes the bsg hooks on fchosts/rports
- * @q:	the request_queue that is to be torn down.
- *
- * Notes:
- *   Before unregistering the queue empty any requests that are blocked
- *
- *
- */
-static void
-fc_bsg_remove(struct request_queue *q)
-{
-	struct request *req; /* block request */
-	int counts; /* totals for request_list count and starved */
-
-	if (q) {
-		/* Stop taking in new requests */
-		spin_lock_irq(q->queue_lock);
-		blk_stop_queue(q);
-
-		/* drain all requests in the queue */
-		while (1) {
-			/* need the lock to fetch a request
-			 * this may fetch the same reqeust as the previous pass
-			 */
-			req = blk_fetch_request(q);
-			/* save requests in use and starved */
-			counts = q->rq.count[0] + q->rq.count[1] +
-				q->rq.starved[0] + q->rq.starved[1];
-			spin_unlock_irq(q->queue_lock);
-			/* any requests still outstanding? */
-			if (counts == 0)
-				break;
-
-			/* This may be the same req as the previous iteration,
-			 * always send the blk_end_request_all after a prefetch.
-			 * It is not okay to not end the request because the
-			 * prefetch started the request.
-			 */
-			if (req) {
-				/* return -ENXIO to indicate that this queue is
-				 * going away
-				 */
-				req->errors = -ENXIO;
-				blk_end_request_all(req, -ENXIO);
-			}
-
-			msleep(200); /* allow bsg to possibly finish */
-			spin_lock_irq(q->queue_lock);
-		}
-
-		bsg_unregister_queue(q);
-		blk_cleanup_queue(q);
-	}
-}
-
-
 /* Original Author:  Martin Hicks */
 MODULE_AUTHOR("James Smart");
 MODULE_DESCRIPTION("FC Transport Attributes");
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 2a65167..0686c22 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -30,6 +30,8 @@
 #include <linux/sched.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_netlink.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_bsg.h>
 
 struct scsi_transport_template;
 
@@ -584,47 +586,12 @@ struct fc_host_attrs {
 #define fc_host_dev_loss_tmo(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
 
-
-struct fc_bsg_buffer {
-	unsigned int payload_len;
-	int sg_cnt;
-	struct scatterlist *sg_list;
-};
-
-/* Values for fc_bsg_job->state_flags (bitflags) */
-#define FC_RQST_STATE_INPROGRESS	0
-#define FC_RQST_STATE_DONE		1
-
-struct fc_bsg_job {
-	struct Scsi_Host *shost;
-	struct fc_rport *rport;
-	struct device *dev;
-	struct request *req;
-	spinlock_t job_lock;
-	unsigned int state_flags;
-	unsigned int ref_cnt;
-	void (*job_done)(struct fc_bsg_job *);
-
-	struct fc_bsg_request *request;
-	struct fc_bsg_reply *reply;
-	unsigned int request_len;
-	unsigned int reply_len;
-	/*
-	 * On entry : reply_len indicates the buffer size allocated for
-	 * the reply.
-	 *
-	 * Upon completion : the message handler must set reply_len
-	 *  to indicates the size of the reply to be returned to the
-	 *  caller.
-	 */
-
-	/* DMA payloads for the request/response */
-	struct fc_bsg_buffer request_payload;
-	struct fc_bsg_buffer reply_payload;
-
-	void *dd_data;			/* Used for driver-specific storage */
-};
-
+static inline struct fc_rport *fc_bsg_get_rport(struct scsi_bsg_job *job)
+{
+	if (&job->shost->shost_gendev == job->dev)
+		return NULL;
+	return dev_to_rport(job->dev);
+}
 
 /* The functions by which the transport class and the driver communicate */
 struct fc_function_template {
@@ -662,8 +629,8 @@ struct fc_function_template {
 	int     (* it_nexus_response)(struct Scsi_Host *, u64, int);
 
 	/* bsg support */
-	int	(*bsg_request)(struct fc_bsg_job *);
-	int	(*bsg_timeout)(struct fc_bsg_job *);
+	int	(*bsg_request)(struct scsi_bsg_job *);
+	int	(*bsg_timeout)(struct scsi_bsg_job *);
 
 	/* allocation lengths for host-specific data */
 	u32	 			dd_fcrport_size;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 04/10] iscsi class: add bsg support to iscsi class
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (2 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 03/10] FC class: convert to scsi bsg lib michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 05/10] ibmvfc: convert ibmvfc to scsi bsg lib michaelc
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Mike Christie

From: Mike Christie <michaelc@cs.wisc.edu>

This patch adds bsg support to the iscsi class. There is only
1 request, the host vendor one, supported. It is expected that
this would be used for things like flash updates.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/scsi_transport_iscsi.c |  126 ++++++++++++++++++++++++++++++++++-
 include/scsi/scsi_bsg_iscsi.h       |  110 ++++++++++++++++++++++++++++++
 include/scsi/scsi_transport_iscsi.h |    5 ++
 3 files changed, 240 insertions(+), 1 deletions(-)
 create mode 100644 include/scsi/scsi_bsg_iscsi.h

diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3fd16d7..7820940 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -31,6 +31,8 @@
 #include <scsi/scsi_transport_iscsi.h>
 #include <scsi/iscsi_if.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_bsg_iscsi.h>
+#include <scsi/scsi_bsg.h>
 
 #define ISCSI_SESSION_ATTRS 23
 #define ISCSI_CONN_ATTRS 13
@@ -270,6 +272,112 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
 }
 EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
 
+/*
+ * BSG support
+ */
+/**
+ * iscsi_bsg_job_timeout - handler for when a bsg request timesout
+ * @job: bsg job
+ */
+static int iscsi_bsg_job_timeout(struct scsi_bsg_job *job)
+{
+	struct Scsi_Host *shost = job->shost;
+	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
+	int err = 0;
+
+	if (i->iscsi_transport->bsg_timeout)
+		err = i->iscsi_transport->bsg_timeout(job);
+	return err;
+}
+
+/**
+ * iscsi_bsg_host_dispatch - Dispatch command to LLD.
+ * @job:	bsg job to be processed
+ */
+static int iscsi_bsg_host_dispatch(struct scsi_bsg_job *job)
+{
+	struct Scsi_Host *shost = job->shost;
+	struct iscsi_bsg_request *req = job->request;
+	struct iscsi_bsg_reply *reply = job->reply;
+	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
+	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */
+	int ret;
+
+	/* check if we have the msgcode value at least */
+	if (job->request_len < sizeof(uint32_t)) {
+		ret = -ENOMSG;
+		goto fail_host_msg;
+	}
+
+	/* Validate the host command */
+	switch (req->msgcode) {
+	case ISCSI_BSG_HST_VENDOR:
+		cmdlen += sizeof(struct iscsi_bsg_host_vendor);
+		if ((shost->hostt->vendor_id == 0L) ||
+		    (req->rqst_data.h_vendor.vendor_id !=
+			shost->hostt->vendor_id)) {
+			ret = -ESRCH;
+			goto fail_host_msg;
+		}
+		break;
+	default:
+		ret = -EBADR;
+		goto fail_host_msg;
+	}
+
+	/* check if we really have all the request data needed */
+	if (job->request_len < cmdlen) {
+		ret = -ENOMSG;
+		goto fail_host_msg;
+	}
+
+	ret = i->iscsi_transport->bsg_request(job);
+	if (!ret)
+		return 0;
+
+fail_host_msg:
+	/* return the errno failure code as the only status */
+	BUG_ON(job->reply_len < sizeof(uint32_t));
+	reply->reply_payload_rcv_len = 0;
+	reply->result = ret;
+	job->reply_len = sizeof(uint32_t);
+	scsi_bsg_job_done(job, ret, 0);
+	return 0;
+}
+
+/**
+ * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
+ * @shost: shost for iscsi_host
+ * @cls_host: iscsi_cls_host adding the structures to
+ */
+static int
+iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
+{
+	struct device *dev = &shost->shost_gendev;
+	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
+	struct request_queue *q;
+	char bsg_name[20];
+
+	ihost->rqst_q = NULL;
+
+	if (!i->iscsi_transport->bsg_request)
+		return -ENOTSUPP;
+
+	snprintf(bsg_name, sizeof(bsg_name),
+		 "iscsi_host%d", shost->host_no);
+
+	q = scsi_bsg_add(dev, bsg_name);
+	if (!q) {
+		printk(KERN_ERR "iscsi_host%d: bsg interface failed to "
+				"initialize - no request queue\n",
+				 shost->host_no);
+		return -ENOMEM;
+	}
+
+	ihost->rqst_q = q;
+	return 0;
+}
+
 static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
 			    struct device *cdev)
 {
@@ -279,13 +387,27 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
 	memset(ihost, 0, sizeof(*ihost));
 	atomic_set(&ihost->nr_scans, 0);
 	mutex_init(&ihost->mutex);
+
+	iscsi_bsg_host_add(shost, ihost);
+	/* ignore any bsg add error - we just can't do sgio */
+
+	return 0;
+}
+
+static int iscsi_remove_host(struct transport_container *tc,
+			     struct device *dev, struct device *cdev)
+{
+	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct iscsi_cls_host *ihost = shost->shost_data;
+
+	scsi_bsg_remove(ihost->rqst_q);
 	return 0;
 }
 
 static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
 			       "iscsi_host",
 			       iscsi_setup_host,
-			       NULL,
+			       iscsi_remove_host,
 			       NULL);
 
 static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
@@ -2066,6 +2188,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
 	priv->iscsi_transport = tt;
 	priv->t.user_scan = iscsi_user_scan;
 	priv->t.create_work_queue = 1;
+	priv->t.eh_bsg_job_timed_out = iscsi_bsg_job_timeout;
+	priv->t.queue_bsg_job = iscsi_bsg_host_dispatch;
 
 	priv->dev.class = &iscsi_transport_class;
 	dev_set_name(&priv->dev, "%s", tt->name);
diff --git a/include/scsi/scsi_bsg_iscsi.h b/include/scsi/scsi_bsg_iscsi.h
new file mode 100644
index 0000000..fd5689d
--- /dev/null
+++ b/include/scsi/scsi_bsg_iscsi.h
@@ -0,0 +1,110 @@
+/*
+ *  iSCSI Transport BSG Interface
+ *
+ *  Copyright (C) 2009   James Smart, Emulex Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef SCSI_BSG_ISCSI_H
+#define SCSI_BSG_ISCSI_H
+
+/*
+ * This file intended to be included by both kernel and user space
+ */
+
+#include <scsi/scsi.h>
+
+/*
+ * iSCSI Transport SGIO v4 BSG Message Support
+ */
+
+/* Default BSG request timeout (in seconds) */
+#define ISCSI_DEFAULT_BSG_TIMEOUT      (10 * HZ)
+
+
+/*
+ * Request Message Codes supported by the iSCSI Transport
+ */
+
+/* define the class masks for the message codes */
+#define ISCSI_BSG_CLS_MASK     0xF0000000      /* find object class */
+#define ISCSI_BSG_HST_MASK     0x80000000      /* iscsi host class */
+
+/* iscsi host Message Codes */
+#define ISCSI_BSG_HST_VENDOR           (ISCSI_BSG_HST_MASK | 0x000000FF)
+
+
+/*
+ * iSCSI Host Messages
+ */
+
+/* ISCSI_BSG_HST_VENDOR : */
+
+/* Request:
+ * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
+ *   formatting requirements specified in scsi_netlink.h
+ */
+struct iscsi_bsg_host_vendor {
+	/*
+	 * Identifies the vendor that the message is formatted for. This
+	 * should be the recipient of the message.
+	 */
+	uint64_t vendor_id;
+
+	/* start of vendor command area */
+	uint32_t vendor_cmd[0];
+};
+
+/* Response:
+ */
+struct iscsi_bsg_host_vendor_reply {
+	/* start of vendor response area */
+	uint32_t vendor_rsp[0];
+};
+
+
+/* request (CDB) structure of the sg_io_v4 */
+struct iscsi_bsg_request {
+	uint32_t msgcode;
+	union {
+		struct iscsi_bsg_host_vendor    h_vendor;
+	} rqst_data;
+} __attribute__((packed));
+
+
+/* response (request sense data) structure of the sg_io_v4 */
+struct iscsi_bsg_reply {
+	/*
+	 * The completion result. Result exists in two forms:
+	 * if negative, it is an -Exxx system errno value. There will
+	 * be no further reply information supplied.
+	 * else, it's the 4-byte scsi error result, with driver, host,
+	 * msg and status fields. The per-msgcode reply structure
+	 * will contain valid data.
+	 */
+	uint32_t result;
+
+	/* If there was reply_payload, how much was recevied ? */
+	uint32_t reply_payload_rcv_len;
+
+	union {
+		struct iscsi_bsg_host_vendor_reply      vendor_reply;
+	} reply_data;
+};
+
+
+#endif /* SCSI_BSG_ISCSI_H */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index bf8f529..b396630 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -37,6 +37,7 @@ struct iscsi_cls_conn;
 struct iscsi_conn;
 struct iscsi_task;
 struct sockaddr;
+struct scsi_bsg_job;
 
 /**
  * struct iscsi_transport - iSCSI Transport template
@@ -137,6 +138,9 @@ struct iscsi_transport {
 	int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
 			  uint32_t enable, struct sockaddr *dst_addr);
 	int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+	/* bsg support */
+	int (*bsg_request)(struct scsi_bsg_job *job);
+	int (*bsg_timeout)(struct scsi_bsg_job *job);
 };
 
 /*
@@ -216,6 +220,7 @@ struct iscsi_cls_session {
 struct iscsi_cls_host {
 	atomic_t nr_scans;
 	struct mutex mutex;
+	struct request_queue *rqst_q;	/* bsg support */
 };
 
 extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 05/10] ibmvfc: convert ibmvfc to scsi bsg lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (3 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 04/10] iscsi class: add bsg support to iscsi class michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 06/10] libfc: convert " michaelc
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Vikas Chaudhary, Mike Christie

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

This patch converts ibmvfc to the scsi bsg lib. The differences
visible to the driver are:
- fc_bsg_job is now named scsi_bsg_job.
- no rport pointer. Can access it through the device pointer.
- the request and reply pointers on the scsi_bsg_job struct
  are now void pointers, so you cannot do bsg_job->request->some_field.

Patch is only compile tested and made over scsi-misc.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/ibmvscsi/ibmvfc.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index b765061..576594b 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1704,12 +1704,12 @@ static void ibmvfc_bsg_timeout_done(struct ibmvfc_event *evt)
 
 /**
  * ibmvfc_bsg_timeout - Handle a BSG timeout
- * @job:	struct fc_bsg_job that timed out
+ * @job:	struct scsi_bsg_job that timed out
  *
  * Returns:
  *	0 on success / other on failure
  **/
-static int ibmvfc_bsg_timeout(struct fc_bsg_job *job)
+static int ibmvfc_bsg_timeout(struct scsi_bsg_job *job)
 {
 	struct ibmvfc_host *vhost = shost_priv(job->shost);
 	unsigned long port_id = (unsigned long)job->dd_data;
@@ -1817,42 +1817,46 @@ unlock_out:
 
 /**
  * ibmvfc_bsg_request - Handle a BSG request
- * @job:	struct fc_bsg_job to be executed
+ * @job:	struct scsi_bsg_job to be executed
  *
  * Returns:
  *	0 on success / other on failure
  **/
-static int ibmvfc_bsg_request(struct fc_bsg_job *job)
+static int ibmvfc_bsg_request(struct scsi_bsg_job *job)
 {
 	struct ibmvfc_host *vhost = shost_priv(job->shost);
-	struct fc_rport *rport = job->rport;
+	struct fc_rport *rport;
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct ibmvfc_passthru_mad *mad;
 	struct ibmvfc_event *evt;
 	union ibmvfc_iu rsp_iu;
 	unsigned long flags, port_id = -1;
-	unsigned int code = job->request->msgcode;
+	unsigned int code = req->msgcode;
 	int rc = 0, req_seg, rsp_seg, issue_login = 0;
 	u32 fc_flags, rsp_len;
 
 	ENTER;
-	job->reply->reply_payload_rcv_len = 0;
-	if (rport)
-		port_id = rport->port_id;
+	reply->reply_payload_rcv_len = 0;
 
 	switch (code) {
 	case FC_BSG_HST_ELS_NOLOGIN:
-		port_id = (job->request->rqst_data.h_els.port_id[0] << 16) |
-			(job->request->rqst_data.h_els.port_id[1] << 8) |
-			job->request->rqst_data.h_els.port_id[2];
+		port_id = (req->rqst_data.h_els.port_id[0] << 16) |
+			(req->rqst_data.h_els.port_id[1] << 8) |
+			req->rqst_data.h_els.port_id[2];
 	case FC_BSG_RPT_ELS:
+		rport = dev_to_rport(job->dev);
+		port_id = rport->port_id;
 		fc_flags = IBMVFC_FC_ELS;
 		break;
 	case FC_BSG_HST_CT:
 		issue_login = 1;
-		port_id = (job->request->rqst_data.h_ct.port_id[0] << 16) |
-			(job->request->rqst_data.h_ct.port_id[1] << 8) |
-			job->request->rqst_data.h_ct.port_id[2];
+		port_id = (req->rqst_data.h_ct.port_id[0] << 16) |
+			(req->rqst_data.h_ct.port_id[1] << 8) |
+			req->rqst_data.h_ct.port_id[2];
 	case FC_BSG_RPT_CT:
+		rport = dev_to_rport(job->dev);
+		port_id = rport->port_id;
 		fc_flags = IBMVFC_FC_CT_IU;
 		break;
 	default:
@@ -1940,13 +1944,13 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job)
 	if (rsp_iu.passthru.common.status)
 		rc = -EIO;
 	else
-		job->reply->reply_payload_rcv_len = rsp_len;
+		reply->reply_payload_rcv_len = rsp_len;
 
 	spin_lock_irqsave(vhost->host->host_lock, flags);
 	ibmvfc_free_event(evt);
 	spin_unlock_irqrestore(vhost->host->host_lock, flags);
-	job->reply->result = rc;
-	job->job_done(job);
+	reply->result = rc;
+	job->job_done(job, reply->result, reply->reply_payload_rcv_len);
 	rc = 0;
 out:
 	dma_unmap_sg(vhost->dev, job->request_payload.sg_list,
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 06/10] libfc: convert to scsi bsg lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (4 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 05/10] ibmvfc: convert ibmvfc to scsi bsg lib michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 07/10] zfcp: convert zfcp to scsi bsg lib V2 michaelc
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Vikas Chaudhary, Mike Christie

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

This patch converts libfc to the scsi bsg lib. The differences
visible to the driver are:
- fc_bsg_job is now named scsi_bsg_job.
- no rport pointer. Can access it through the device pointer.
- the request and reply pointers on the scsi_bsg_job struct
  are now void pointers, so you cannot do bsg_job->request->some_field.

Patch is only quickly tested with fcping and made over scsi-misc.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/libfc/fc_lport.c |   51 +++++++++++++++++++---------------------
 include/scsi/libfc.h          |    3 +-
 2 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index e008b16..a6ec58b 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -140,7 +140,7 @@ static const char *fc_lport_state_names[] = {
  * @offset:   The offset into the response data
  */
 struct fc_bsg_info {
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
 	struct fc_lport *lport;
 	u16 rsp_code;
 	struct scatterlist *sg;
@@ -1653,18 +1653,19 @@ 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 scsi_bsg_job *job = info->job;
+	struct fc_bsg_reply *reply = job->reply;
 	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) ?
+		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);
+		job->state_flags |= SCSI_RQST_STATE_DONE;
+		job->job_done(job, reply->result, reply->reply_payload_rcv_len);
 		kfree(info);
 		return;
 	}
@@ -1681,25 +1682,25 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
 			(unsigned short)fc_frame_payload_op(fp);
 
 		/* Save the reply status of the job */
-		job->reply->reply_data.ctels_reply.status =
+		reply->reply_data.ctels_reply.status =
 			(cmd == info->rsp_code) ?
 			FC_CTELS_STATUS_OK : FC_CTELS_STATUS_REJECT;
 	}
 
-	job->reply->reply_payload_rcv_len +=
+	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 >
+		if (reply->reply_payload_rcv_len >
 		    job->reply_payload.payload_len)
-			job->reply->reply_payload_rcv_len =
+			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);
+		reply->result = 0;
+		job->state_flags |= SCSI_RQST_STATE_DONE;
+		job->job_done(job, reply->result, reply->reply_payload_rcv_len);
 		kfree(info);
 	}
 	fc_frame_free(fp);
@@ -1715,7 +1716,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
  * 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,
+static int fc_lport_els_request(struct scsi_bsg_job *job,
 				struct fc_lport *lport,
 				u32 did, u32 tov)
 {
@@ -1776,7 +1777,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job,
  * 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,
+static int fc_lport_ct_request(struct scsi_bsg_job *job,
 			       struct fc_lport *lport, u32 did, u32 tov)
 {
 	struct fc_bsg_info *info;
@@ -1832,9 +1833,11 @@ static int fc_lport_ct_request(struct fc_bsg_job *job,
  *			    FC Passthrough requests
  * @job: The BSG passthrough job
  */
-int fc_lport_bsg_request(struct fc_bsg_job *job)
+int fc_lport_bsg_request(struct scsi_bsg_job *job)
 {
 	struct request *rsp = job->req->next_rq;
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct Scsi_Host *shost = job->shost;
 	struct fc_lport *lport = shost_priv(shost);
 	struct fc_rport *rport;
@@ -1842,35 +1845,29 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
 	int rc = -EINVAL;
 	u32 did;
 
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 	if (rsp)
 		rsp->resid_len = job->reply_payload.payload_len;
 
 	mutex_lock(&lport->lp_mutex);
 
-	switch (job->request->msgcode) {
+	switch (req->msgcode) {
 	case FC_BSG_RPT_ELS:
-		rport = job->rport;
-		if (!rport)
-			break;
-
+		rport = dev_to_rport(job->dev);
 		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;
-
+		rport = dev_to_rport(job->dev);
 		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);
+		did = ntoh24(req->rqst_data.h_ct.port_id);
 		if (did == FC_FID_DIR_SERV)
 			rdata = lport->dns_rdata;
 		else
@@ -1883,7 +1880,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
 		break;
 
 	case FC_BSG_HST_ELS_NOLOGIN:
-		did = ntoh24(job->request->rqst_data.h_els.port_id);
+		did = ntoh24(req->rqst_data.h_els.port_id);
 		rc = fc_lport_els_request(job, lport, did, lport->e_d_tov);
 		break;
 	}
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 7d96829..cdad338 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -27,6 +27,7 @@
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_bsg_fc.h>
+#include <scsi/scsi_bsg.h>
 
 #include <scsi/fc/fc_fcp.h>
 #include <scsi/fc/fc_ns.h>
@@ -1055,7 +1056,7 @@ int fc_lport_reset(struct fc_lport *);
 int fc_set_mfs(struct fc_lport *, u32 mfs);
 struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize);
 struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id);
-int fc_lport_bsg_request(struct fc_bsg_job *);
+int fc_lport_bsg_request(struct scsi_bsg_job *);
 void fc_lport_set_local_id(struct fc_lport *, u32 port_id);
 void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *);
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 07/10] zfcp: convert zfcp to scsi bsg lib V2
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (5 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 06/10] libfc: convert " michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 08/10] qla2xxx: convert qla2xxx to scsi bsg lib michaelc
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Vikas Chaudhary, Mike Christie

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

This patch converts zfcp to the scsi bsg lib. The differences
visible to the driver are:
- fc_bsg_job is now named scsi_bsg_job.
- no rport pointer. Can access it through the device pointer.
- the request and reply pointers on the scsi_bsg_job struct
  are now void pointers, so you cannot do bsg_job->request->some_field.

Patch is only compile tested and made over scsi-misc.

V2:
- Fixed fc_bsg_request jr naming to jq to match other
  code.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/s390/scsi/zfcp_ext.h |    4 ++--
 drivers/s390/scsi/zfcp_fc.c  |   29 ++++++++++++++++-------------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 03627cfd..dc9a88e 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -94,8 +94,8 @@ extern void zfcp_fc_link_test_work(struct work_struct *);
 extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *);
 extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
 extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
-extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
-extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
+extern int zfcp_fc_exec_bsg_job(struct scsi_bsg_job *);
+extern int zfcp_fc_timeout_bsg_job(struct scsi_bsg_job *);
 extern void zfcp_fc_sym_name_update(struct work_struct *);
 
 /* zfcp_fsf.c */
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 297e6b7..6257614 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -818,23 +818,24 @@ out_free:
 
 static void zfcp_fc_ct_els_job_handler(void *data)
 {
-	struct fc_bsg_job *job = data;
+	struct scsi_bsg_job *job = data;
 	struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data;
 	struct fc_bsg_reply *jr = job->reply;
 
 	jr->reply_payload_rcv_len = job->reply_payload.payload_len;
 	jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 	jr->result = zfcp_ct_els->status ? -EIO : 0;
-	job->job_done(job);
+	job->job_done(job, jr->result, jr->reply_payload_rcv_len);
 }
 
-static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job)
+static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_request *jq = job->request;
 	u32 preamble_word1;
 	u8 gs_type;
 	struct zfcp_adapter *adapter;
 
-	preamble_word1 = job->request->rqst_data.r_ct.preamble_word1;
+	preamble_word1 = jq->rqst_data.r_ct.preamble_word1;
 	gs_type = (preamble_word1 & 0xff000000) >> 24;
 
 	adapter = (struct zfcp_adapter *) job->shost->hostdata[0];
@@ -857,7 +858,7 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job)
 
 static void zfcp_fc_ct_job_handler(void *data)
 {
-	struct fc_bsg_job *job = data;
+	struct scsi_bsg_job *job = data;
 	struct zfcp_fc_wka_port *wka_port;
 
 	wka_port = zfcp_fc_job_wka_port(job);
@@ -866,11 +867,12 @@ static void zfcp_fc_ct_job_handler(void *data)
 	zfcp_fc_ct_els_job_handler(data);
 }
 
-static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
+static int zfcp_fc_exec_els_job(struct scsi_bsg_job *job,
 				struct zfcp_adapter *adapter)
 {
 	struct zfcp_fsf_ct_els *els = job->dd_data;
-	struct fc_rport *rport = job->rport;
+	struct fc_rport *rport = fc_bsg_get_rport(job);
+	struct fc_bsg_request *jq = job->request;
 	struct zfcp_port *port;
 	u32 d_id;
 
@@ -882,13 +884,13 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
 		d_id = port->d_id;
 		put_device(&port->dev);
 	} else
-		d_id = ntoh24(job->request->rqst_data.h_els.port_id);
+		d_id = ntoh24(jq->rqst_data.h_els.port_id);
 
 	els->handler = zfcp_fc_ct_els_job_handler;
 	return zfcp_fsf_send_els(adapter, d_id, els, job->req->timeout / HZ);
 }
 
-static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job,
+static int zfcp_fc_exec_ct_job(struct scsi_bsg_job *job,
 			       struct zfcp_adapter *adapter)
 {
 	int ret;
@@ -911,13 +913,14 @@ static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job,
 	return ret;
 }
 
-int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
+int zfcp_fc_exec_bsg_job(struct scsi_bsg_job *job)
 {
 	struct Scsi_Host *shost;
 	struct zfcp_adapter *adapter;
 	struct zfcp_fsf_ct_els *ct_els = job->dd_data;
+	struct fc_bsg_request *jq = job->request;
 
-	shost = job->rport ? rport_to_shost(job->rport) : job->shost;
+	shost = job->shost;
 	adapter = (struct zfcp_adapter *)shost->hostdata[0];
 
 	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN))
@@ -927,7 +930,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
 	ct_els->resp = job->reply_payload.sg_list;
 	ct_els->handler_data = job;
 
-	switch (job->request->msgcode) {
+	switch (jq->msgcode) {
 	case FC_BSG_RPT_ELS:
 	case FC_BSG_HST_ELS_NOLOGIN:
 		return zfcp_fc_exec_els_job(job, adapter);
@@ -939,7 +942,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
 	}
 }
 
-int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *job)
+int zfcp_fc_timeout_bsg_job(struct scsi_bsg_job *job)
 {
 	/* hardware tracks timeout, reset bsg timeout to not interfere */
 	return -EAGAIN;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 08/10] qla2xxx: convert qla2xxx to scsi bsg lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (6 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 07/10] zfcp: convert zfcp to scsi bsg lib V2 michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:04 ` [RFC PATCH 09/10] lpfc: convert lpfc " michaelc
  2011-07-22 10:05 ` [RFC PATCH 10/10] bfa: convert bfa " michaelc
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Vikas Chaudhary, Mike Christie

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

This patch converts qla2xxx to the scsi bsg lib. The differences
visible to the driver are:
- fc_bsg_job is now named scsi_bsg_job.
- no rport pointer. Can access it through the device pointer.
- the request and reply pointers on the scsi_bsg_job struct
  are now void pointers, so you cannot do bsg_job->request->some_field.

I did some basic testing with Qlogic's tools that use bsg.
Giri has also reported success with some basic testing.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c  |  219 ++++++++++++++++++++++-----------------
 drivers/scsi/qla2xxx/qla_def.h  |    3 +-
 drivers/scsi/qla2xxx/qla_gbl.h  |    4 +-
 drivers/scsi/qla2xxx/qla_iocb.c |   11 +-
 drivers/scsi/qla2xxx/qla_isr.c  |   44 +++++----
 drivers/scsi/qla2xxx/qla_os.c   |   32 ++++---
 6 files changed, 178 insertions(+), 135 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 8c10e2c..5923b97 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -92,16 +92,18 @@ qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
 }
 
 static int
-qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
+qla24xx_proc_fcp_prio_cfg_cmd(struct scsi_bsg_job *bsg_job)
 {
 	struct Scsi_Host *host = bsg_job->shost;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
 	int ret = 0;
 	uint32_t len;
 	uint32_t oper;
 
-	bsg_job->reply->reply_payload_rcv_len = 0;
+	bsg_reply->reply_payload_rcv_len = 0;
 
 	if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))) {
 		ret = -EINVAL;
@@ -116,7 +118,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 	}
 
 	/* Get the sub command */
-	oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+	oper = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 
 	/* Only set config is allowed if config memory is not allocated */
 	if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
@@ -130,10 +132,10 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 			ha->fcp_prio_cfg->attributes &=
 				~FCP_PRIO_ATTR_ENABLE;
 			qla24xx_update_all_fcp_prio(vha);
-			bsg_job->reply->result = DID_OK;
+			bsg_reply->result = DID_OK;
 		} else {
 			ret = -EINVAL;
-			bsg_job->reply->result = (DID_ERROR << 16);
+			bsg_reply->result = (DID_ERROR << 16);
 			goto exit_fcp_prio_cfg;
 		}
 		break;
@@ -145,10 +147,10 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 				ha->fcp_prio_cfg->attributes |=
 				    FCP_PRIO_ATTR_ENABLE;
 				qla24xx_update_all_fcp_prio(vha);
-				bsg_job->reply->result = DID_OK;
+				bsg_reply->result = DID_OK;
 			} else {
 				ret = -EINVAL;
-				bsg_job->reply->result = (DID_ERROR << 16);
+				bsg_reply->result = (DID_ERROR << 16);
 				goto exit_fcp_prio_cfg;
 			}
 		}
@@ -158,12 +160,12 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 		len = bsg_job->reply_payload.payload_len;
 		if (!len || len > FCP_PRIO_CFG_SIZE) {
 			ret = -EINVAL;
-			bsg_job->reply->result = (DID_ERROR << 16);
+			bsg_reply->result = (DID_ERROR << 16);
 			goto exit_fcp_prio_cfg;
 		}
 
-		bsg_job->reply->result = DID_OK;
-		bsg_job->reply->reply_payload_rcv_len =
+		bsg_reply->result = DID_OK;
+		bsg_reply->reply_payload_rcv_len =
 			sg_copy_from_buffer(
 			bsg_job->reply_payload.sg_list,
 			bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
@@ -174,7 +176,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 	case QLFC_FCP_PRIO_SET_CONFIG:
 		len = bsg_job->request_payload.payload_len;
 		if (!len || len > FCP_PRIO_CFG_SIZE) {
-			bsg_job->reply->result = (DID_ERROR << 16);
+			bsg_reply->result = (DID_ERROR << 16);
 			ret = -EINVAL;
 			goto exit_fcp_prio_cfg;
 		}
@@ -186,7 +188,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 					"Unable to allocate memory "
 					"for fcp prio config data (%x).\n",
 					FCP_PRIO_CFG_SIZE);
-				bsg_job->reply->result = (DID_ERROR << 16);
+				bsg_reply->result = (DID_ERROR << 16);
 				ret = -ENOMEM;
 				goto exit_fcp_prio_cfg;
 			}
@@ -201,7 +203,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 		if (!qla24xx_fcp_prio_cfg_valid(
 			(struct qla_fcp_prio_cfg *)
 			ha->fcp_prio_cfg, 1)) {
-			bsg_job->reply->result = (DID_ERROR << 16);
+			bsg_reply->result = (DID_ERROR << 16);
 			ret = -EINVAL;
 			/* If buffer was invalidatic int
 			 * fcp_prio_cfg is of no use
@@ -215,19 +217,21 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
 		if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
 			ha->flags.fcp_prio_enabled = 1;
 		qla24xx_update_all_fcp_prio(vha);
-		bsg_job->reply->result = DID_OK;
+		bsg_reply->result = DID_OK;
 		break;
 	default:
 		ret = -EINVAL;
 		break;
 	}
 exit_fcp_prio_cfg:
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 	return ret;
 }
 static int
-qla2x00_process_els(struct fc_bsg_job *bsg_job)
+qla2x00_process_els(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 	struct fc_rport *rport;
 	fc_port_t *fcport = NULL;
 	struct Scsi_Host *host;
@@ -240,8 +244,8 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 	uint16_t nextlid = 0;
 	struct srb_ctx *els;
 
-	if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
-		rport = bsg_job->rport;
+	if (bsg_req->msgcode == FC_BSG_RPT_ELS) {
+		rport = dev_to_rport(bsg_job->dev);
 		fcport = *(fc_port_t **) rport->dd_data;
 		host = rport_to_shost(rport);
 		vha = shost_priv(host);
@@ -276,7 +280,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 	}
 
 	/* ELS request for rport */
-	if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
+	if (bsg_req->msgcode == FC_BSG_RPT_ELS) {
 		/* make sure the rport is logged in,
 		 * if not perform fabric login
 		 */
@@ -303,11 +307,11 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 		fcport->vha = vha;
 		fcport->vp_idx = vha->vp_idx;
 		fcport->d_id.b.al_pa =
-			bsg_job->request->rqst_data.h_els.port_id[0];
+			bsg_req->rqst_data.h_els.port_id[0];
 		fcport->d_id.b.area =
-			bsg_job->request->rqst_data.h_els.port_id[1];
+			bsg_req->rqst_data.h_els.port_id[1];
 		fcport->d_id.b.domain =
-			bsg_job->request->rqst_data.h_els.port_id[2];
+			bsg_req->rqst_data.h_els.port_id[2];
 		fcport->loop_id =
 			(fcport->d_id.b.al_pa == 0xFD) ?
 			NPH_FABRIC_CONTROLLER : NPH_F_PORT;
@@ -356,17 +360,17 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
 
 	els = sp->ctx;
 	els->type =
-		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
+		(bsg_req->msgcode == FC_BSG_RPT_ELS ?
 		SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
 	els->name =
-		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
+		(bsg_req->msgcode == FC_BSG_RPT_ELS ?
 		"bsg_els_rpt" : "bsg_els_hst");
 	els->u.bsg_job = bsg_job;
 
 	DEBUG2(qla_printk(KERN_INFO, ha,
 		"scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
 		"portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
-		bsg_job->request->rqst_data.h_els.command_code,
+		bsg_req->rqst_data.h_els.command_code,
 		fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
 		fcport->d_id.b.al_pa));
 
@@ -387,16 +391,17 @@ done_unmap_sg:
 	goto done_free_fcport;
 
 done_free_fcport:
-	if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
+	if (bsg_req->msgcode == FC_BSG_HST_ELS_NOLOGIN)
 		kfree(fcport);
 done:
 	return rval;
 }
 
 static int
-qla2x00_process_ct(struct fc_bsg_job *bsg_job)
+qla2x00_process_ct(struct scsi_bsg_job *bsg_job)
 {
 	srb_t *sp;
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
@@ -441,7 +446,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 	}
 
 	loop_id =
-		(bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
+		(bsg_req->rqst_data.h_ct.preamble_word1 & 0xFF000000)
 			>> 24;
 	switch (loop_id) {
 	case 0xFC:
@@ -471,9 +476,9 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 	/* Initialize all required  fields of fcport */
 	fcport->vha = vha;
 	fcport->vp_idx = vha->vp_idx;
-	fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0];
-	fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1];
-	fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2];
+	fcport->d_id.b.al_pa = bsg_req->rqst_data.h_ct.port_id[0];
+	fcport->d_id.b.area = bsg_req->rqst_data.h_ct.port_id[1];
+	fcport->d_id.b.domain = bsg_req->rqst_data.h_ct.port_id[2];
 	fcport->loop_id = loop_id;
 
 	/* Alloc SRB structure */
@@ -491,7 +496,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 	DEBUG2(qla_printk(KERN_INFO, ha,
 		"scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
 		"portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
-		(bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
+		(bsg_req->rqst_data.h_ct.preamble_word2 >> 16),
 		fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
 		fcport->d_id.b.al_pa));
 
@@ -608,8 +613,10 @@ done_reset_internal:
 }
 
 static int
-qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
+qla2x00_process_loopback(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_request *bsg_req = bsg_job->request;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
@@ -691,7 +698,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 	elreq.rcv_dma = rsp_data_dma;
 	elreq.transfer_size = req_data_len;
 
-	elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+	elreq.options = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 
 	if ((ha->current_topology == ISP_CFG_F ||
 	    (IS_QLA81XX(ha) &&
@@ -711,8 +718,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 				DEBUG2(printk(KERN_ERR
 					"%s(%lu): Get port config failed\n",
 					__func__, vha->host_no));
-				bsg_job->reply->reply_payload_rcv_len = 0;
-				bsg_job->reply->result = (DID_ERROR << 16);
+				bsg_reply->reply_payload_rcv_len = 0;
+				bsg_reply->result = (DID_ERROR << 16);
 				rval = -EPERM;
 				goto done_free_dma_req;
 			}
@@ -723,10 +730,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 					config[0]));
 				if (qla81xx_set_internal_loopback(vha, config,
 					new_config)) {
-					bsg_job->reply->reply_payload_rcv_len =
-						0;
-					bsg_job->reply->result =
-						(DID_ERROR << 16);
+					bsg_reply->reply_payload_rcv_len = 0;
+					bsg_reply->result = (DID_ERROR << 16);
 					rval = -EPERM;
 					goto done_free_dma_req;
 				}
@@ -736,10 +741,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 				 */
 				if (qla81xx_reset_internal_loopback(vha,
 					config, 1)) {
-					bsg_job->reply->reply_payload_rcv_len =
-						0;
-					bsg_job->reply->result =
-						(DID_ERROR << 16);
+					bsg_reply->reply_payload_rcv_len = 0;
+					bsg_reply->result = (DID_ERROR << 16);
 					rval = -EPERM;
 					goto done_free_dma_req;
 				}
@@ -776,8 +779,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 					    vha->host_no);
 				}
 
-				bsg_job->reply->reply_payload_rcv_len = 0;
-				bsg_job->reply->result = (DID_ERROR << 16);
+				bsg_reply->reply_payload_rcv_len = 0;
+				bsg_reply->result = (DID_ERROR << 16);
 				rval = -EIO;
 				goto done_free_dma_req;
 			}
@@ -802,27 +805,28 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
 		fw_sts_ptr += sizeof(response);
 		*fw_sts_ptr = command_sent;
 		rval = 0;
-		bsg_job->reply->reply_payload_rcv_len = 0;
-		bsg_job->reply->result = (DID_ERROR << 16);
+		bsg_reply->reply_payload_rcv_len = 0;
+		bsg_reply->result = (DID_ERROR << 16);
 	} else {
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 			"request %s completed\n", vha->host_no, type));
 
 		bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
 			sizeof(response) + sizeof(uint8_t);
-		bsg_job->reply->reply_payload_rcv_len =
+		bsg_reply->reply_payload_rcv_len =
 			bsg_job->reply_payload.payload_len;
 		fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
 			sizeof(struct fc_bsg_reply);
 		memcpy(fw_sts_ptr, response, sizeof(response));
 		fw_sts_ptr += sizeof(response);
 		*fw_sts_ptr = command_sent;
-		bsg_job->reply->result = DID_OK;
+		bsg_reply->result = DID_OK;
 		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
 			bsg_job->reply_payload.sg_cnt, rsp_data,
 			rsp_data_len);
 	}
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 
 	dma_free_coherent(&ha->pdev->dev, rsp_data_len,
 		rsp_data, rsp_data_dma);
@@ -841,8 +845,10 @@ done_unmap_req_sg:
 }
 
 static int
-qla84xx_reset(struct fc_bsg_job *bsg_job)
+qla84xx_reset(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
@@ -860,29 +866,32 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
 		return -EINVAL;
 	}
 
-	flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+	flag = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 
 	rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
 
 	if (rval) {
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 		    "request 84xx reset failed\n", vha->host_no));
-		rval = bsg_job->reply->reply_payload_rcv_len = 0;
-		bsg_job->reply->result = (DID_ERROR << 16);
+		rval = bsg_reply->reply_payload_rcv_len = 0;
+		bsg_reply->result = (DID_ERROR << 16);
 
 	} else {
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 		    "request 84xx reset completed\n", vha->host_no));
-		bsg_job->reply->result = DID_OK;
+		bsg_reply->result = DID_OK;
 	}
 
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 	return rval;
 }
 
 static int
-qla84xx_updatefw(struct fc_bsg_job *bsg_job)
+qla84xx_updatefw(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
@@ -942,7 +951,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
 		goto done_free_fw_buf;
 	}
 
-	flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+	flag = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 	fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2)));
 
 	memset(mn, 0, sizeof(struct access_chip_84xx));
@@ -968,18 +977,19 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 			"request 84xx updatefw failed\n", vha->host_no));
 
-		rval = bsg_job->reply->reply_payload_rcv_len = 0;
-		bsg_job->reply->result = (DID_ERROR << 16);
+		rval = bsg_reply->reply_payload_rcv_len = 0;
+		bsg_reply->result = (DID_ERROR << 16);
 
 	} else {
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 			"request 84xx updatefw completed\n", vha->host_no));
 
 		bsg_job->reply_len = sizeof(struct fc_bsg_reply);
-		bsg_job->reply->result = DID_OK;
+		bsg_reply->result = DID_OK;
 	}
 
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 	dma_pool_free(ha->s_dma_pool, mn, mn_dma);
 
 done_free_fw_buf:
@@ -993,8 +1003,9 @@ done_unmap_sg:
 }
 
 static int
-qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
+qla84xx_mgmt_cmd(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
@@ -1159,19 +1170,19 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 			"request 84xx mgmt failed\n", vha->host_no));
 
-		rval = bsg_job->reply->reply_payload_rcv_len = 0;
-		bsg_job->reply->result = (DID_ERROR << 16);
+		rval = bsg_reply->reply_payload_rcv_len = 0;
+		bsg_reply->result = (DID_ERROR << 16);
 
 	} else {
 		DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
 			"request 84xx mgmt completed\n", vha->host_no));
 
 		bsg_job->reply_len = sizeof(struct fc_bsg_reply);
-		bsg_job->reply->result = DID_OK;
+		bsg_reply->result = DID_OK;
 
 		if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
 			(ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
-			bsg_job->reply->reply_payload_rcv_len =
+			bsg_reply->reply_payload_rcv_len =
 				bsg_job->reply_payload.payload_len;
 
 			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
@@ -1180,7 +1191,8 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
 		}
 	}
 
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 
 done_unmap_sg:
 	if (mgmt_b)
@@ -1200,8 +1212,9 @@ exit_mgmt:
 }
 
 static int
-qla24xx_iidma(struct fc_bsg_job *bsg_job)
+qla24xx_iidma(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
 	struct qla_hw_data *ha = vha->hw;
@@ -1211,7 +1224,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
 	uint8_t *rsp_ptr = NULL;
 
-	bsg_job->reply->reply_payload_rcv_len = 0;
+	bsg_reply->reply_payload_rcv_len = 0;
 
 	if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
 		test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
@@ -1285,7 +1298,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
 			fcport->port_name[6], fcport->port_name[7], rval,
 			fcport->fp_speed, mb[0], mb[1]));
 		rval = 0;
-		bsg_job->reply->result = (DID_ERROR << 16);
+		bsg_reply->result = (DID_ERROR << 16);
 
 	} else {
 		if (!port_param->mode) {
@@ -1299,26 +1312,29 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
 				sizeof(struct qla_port_param));
 		}
 
-		bsg_job->reply->result = DID_OK;
+		bsg_reply->result = DID_OK;
 	}
 
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 	return rval;
 }
 
 static int
-qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
+qla2x00_optrom_setup(struct scsi_bsg_job *bsg_job, struct qla_hw_data *ha,
 	uint8_t is_update)
 {
+	struct fc_bsg_request *bsg_req = bsg_job->request;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	uint32_t start = 0;
 	int valid = 0;
 
-	bsg_job->reply->reply_payload_rcv_len = 0;
+	bsg_reply->reply_payload_rcv_len = 0;
 
 	if (unlikely(pci_channel_offline(ha->pdev)))
 		return -EINVAL;
 
-	start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
+	start = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 	if (start > ha->optrom_size)
 		return -EINVAL;
 
@@ -1371,10 +1387,11 @@ qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
 }
 
 static int
-qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
+qla2x00_read_optrom(struct scsi_bsg_job *bsg_job)
 {
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	struct qla_hw_data *ha = vha->hw;
 	int rval = 0;
 
@@ -1389,20 +1406,22 @@ qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
 	    bsg_job->reply_payload.sg_cnt, ha->optrom_buffer,
 	    ha->optrom_region_size);
 
-	bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size;
-	bsg_job->reply->result = DID_OK;
+	bsg_reply->reply_payload_rcv_len = ha->optrom_region_size;
+	bsg_reply->result = DID_OK;
 	vfree(ha->optrom_buffer);
 	ha->optrom_buffer = NULL;
 	ha->optrom_state = QLA_SWAITING;
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 	return rval;
 }
 
 static int
-qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
+qla2x00_update_optrom(struct scsi_bsg_job *bsg_job)
 {
 	struct Scsi_Host *host = bsg_job->shost;
 	scsi_qla_host_t *vha = shost_priv(host);
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	struct qla_hw_data *ha = vha->hw;
 	int rval = 0;
 
@@ -1417,18 +1436,23 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
 	ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
 	    ha->optrom_region_start, ha->optrom_region_size);
 
-	bsg_job->reply->result = DID_OK;
+	bsg_reply->result = DID_OK;
+	bsg_reply->reply_payload_rcv_len = 0;
 	vfree(ha->optrom_buffer);
 	ha->optrom_buffer = NULL;
 	ha->optrom_state = QLA_SWAITING;
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 	return rval;
 }
 
 static int
-qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
+qla2x00_process_vendor_specific(struct scsi_bsg_job *bsg_job)
 {
-	switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
+	struct fc_bsg_request *bsg_req = bsg_job->request;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+
+	switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
 	case QL_VND_LOOPBACK:
 		return qla2x00_process_loopback(bsg_job);
 
@@ -1454,18 +1478,21 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
 		return qla2x00_update_optrom(bsg_job);
 
 	default:
-		bsg_job->reply->result = (DID_ERROR << 16);
-		bsg_job->job_done(bsg_job);
+		bsg_reply->result = (DID_ERROR << 16);
+		bsg_reply->reply_payload_rcv_len = 0;
+		bsg_job->job_done(bsg_job, bsg_reply->result,
+				  bsg_reply->reply_payload_rcv_len);
 		return -ENOSYS;
 	}
 }
 
 int
-qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
+qla24xx_bsg_request(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 	int ret = -EINVAL;
 
-	switch (bsg_job->request->msgcode) {
+	switch (bsg_req->msgcode) {
 	case FC_BSG_RPT_ELS:
 	case FC_BSG_HST_ELS_NOLOGIN:
 		ret = qla2x00_process_els(bsg_job);
@@ -1487,8 +1514,10 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
 }
 
 int
-qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
+qla24xx_bsg_timeout(struct scsi_bsg_job *bsg_job)
 {
+	struct fc_bsg_request *bsg_req = bsg_job->request;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
 	scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
@@ -1519,14 +1548,14 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
 						    "abort_command failed\n",
 						    vha->host_no));
 						bsg_job->req->errors =
-						bsg_job->reply->result = -EIO;
+						bsg_reply->result = -EIO;
 					} else {
 						DEBUG2(qla_printk(KERN_INFO, ha,
 						    "scsi(%ld): mbx "
 						    "abort_command success\n",
 						    vha->host_no));
 						bsg_job->req->errors =
-						bsg_job->reply->result = 0;
+						bsg_reply->result = 0;
 					}
 					spin_lock_irqsave(&ha->hardware_lock, flags);
 					goto done;
@@ -1537,12 +1566,12 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 	DEBUG2(qla_printk(KERN_INFO, ha,
 		"scsi(%ld) SRB not found to abort\n", vha->host_no));
-	bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
+	bsg_job->req->errors = bsg_reply->result = -ENXIO;
 	return 0;
 
 done:
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-	if (bsg_job->request->msgcode == FC_BSG_HST_CT)
+	if (bsg_req->msgcode == FC_BSG_HST_CT)
 		kfree(sp->fcport);
 	kfree(sp->ctx);
 	mempool_free(sp, ha->srb_mempool);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index cc5a792..82253c3 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -31,6 +31,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_bsg.h>
 #include <scsi/scsi_bsg_fc.h>
 
 #include "qla_bsg.h"
@@ -273,7 +274,7 @@ struct srb_ctx {
 	char *name;
 	union {
 		struct srb_iocb *iocb_cmd;
-		struct fc_bsg_job *bsg_job;
+		struct scsi_bsg_job *bsg_job;
 	} u;
 };
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 0b38122..6b6da33 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -568,8 +568,8 @@ extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
 extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *);
 
 /* BSG related functions */
-extern int qla24xx_bsg_request(struct fc_bsg_job *);
-extern int qla24xx_bsg_timeout(struct fc_bsg_job *);
+extern int qla24xx_bsg_request(struct scsi_bsg_job *);
+extern int qla24xx_bsg_timeout(struct scsi_bsg_job *);
 extern int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t);
 extern int qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *,
 	dma_addr_t, size_t, uint32_t);
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 7bac3cd..7eba83d 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1799,7 +1799,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
 static void
 qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
-	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
+	struct scsi_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
+	struct fc_bsg_request *bsg_req = bsg_job->request;
 
         els_iocb->entry_type = ELS_IOCB_TYPE;
         els_iocb->entry_count = 1;
@@ -1814,8 +1815,8 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 
 	els_iocb->opcode =
 	    (((struct srb_ctx *)sp->ctx)->type == SRB_ELS_CMD_RPT) ?
-	    bsg_job->request->rqst_data.r_els.els_code :
-	    bsg_job->request->rqst_data.h_els.command_code;
+	    bsg_req->rqst_data.r_els.els_code :
+	    bsg_req->rqst_data.h_els.command_code;
         els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
         els_iocb->port_id[1] = sp->fcport->d_id.b.area;
         els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
@@ -1850,7 +1851,7 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
 	uint16_t tot_dsds;
 	scsi_qla_host_t *vha = sp->fcport->vha;
 	struct qla_hw_data *ha = vha->hw;
-	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
+	struct scsi_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
 	int loop_iterartion = 0;
 	int cont_iocb_prsnt = 0;
 	int entry_count = 1;
@@ -1925,7 +1926,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
 	int index;
 	uint16_t tot_dsds;
         scsi_qla_host_t *vha = sp->fcport->vha;
-	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
+	struct scsi_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
 	int loop_iterartion = 0;
 	int cont_iocb_prsnt = 0;
 	int entry_count = 1;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 1b60a95..12f10e7 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1009,7 +1009,8 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
 	struct srb_ctx *sp_bsg;
-	struct fc_bsg_job *bsg_job;
+	struct scsi_bsg_job *bsg_job;
+	struct fc_bsg_reply *bsg_reply;
 	uint16_t comp_status;
 
 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
@@ -1018,6 +1019,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 
 	sp_bsg = sp->ctx;
 	bsg_job = sp_bsg->u.bsg_job;
+	bsg_reply = bsg_job->reply;
 
 	type = NULL;
 	switch (sp_bsg->type) {
@@ -1036,32 +1038,32 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
 	 * fc payload  to the caller
 	 */
-	bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+	bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
 
 	if (comp_status != CS_COMPLETE) {
 		if (comp_status == CS_DATA_UNDERRUN) {
-			bsg_job->reply->result = DID_OK << 16;
-			bsg_job->reply->reply_payload_rcv_len =
+			bsg_reply->result = DID_OK << 16;
+			bsg_reply->reply_payload_rcv_len =
 			    le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
 
 			DEBUG2(qla_printk(KERN_WARNING, ha,
 			    "scsi(%ld): CT pass-through-%s error "
 			    "comp_status-status=0x%x total_byte = 0x%x.\n",
 			    vha->host_no, type, comp_status,
-			    bsg_job->reply->reply_payload_rcv_len));
+			    bsg_reply->reply_payload_rcv_len));
 		} else {
 			DEBUG2(qla_printk(KERN_WARNING, ha,
 			    "scsi(%ld): CT pass-through-%s error "
 			    "comp_status-status=0x%x.\n",
 			    vha->host_no, type, comp_status));
-			bsg_job->reply->result = DID_ERROR << 16;
-			bsg_job->reply->reply_payload_rcv_len = 0;
+			bsg_reply->result = DID_ERROR << 16;
+			bsg_reply->reply_payload_rcv_len = 0;
 		}
 		DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
 	} else {
-		bsg_job->reply->result =  DID_OK << 16;
-		bsg_job->reply->reply_payload_rcv_len =
+		bsg_reply->result =  DID_OK << 16;;
+		bsg_reply->reply_payload_rcv_len =
 		    bsg_job->reply_payload.payload_len;
 		bsg_job->reply_len = 0;
 	}
@@ -1077,7 +1079,8 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 
 	kfree(sp->ctx);
 	mempool_free(sp, ha->srb_mempool);
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 }
 
 static void
@@ -1089,7 +1092,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	struct qla_hw_data *ha = vha->hw;
 	srb_t *sp;
 	struct srb_ctx *sp_bsg;
-	struct fc_bsg_job *bsg_job;
+	struct scsi_bsg_job *bsg_job;
+	struct fc_bsg_reply *bsg_reply;
 	uint16_t comp_status;
 	uint32_t fw_status[3];
 	uint8_t* fw_sts_ptr;
@@ -1099,6 +1103,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 		return;
 	sp_bsg = sp->ctx;
 	bsg_job = sp_bsg->u.bsg_job;
+	bsg_reply = bsg_job->reply;
 
 	type = NULL;
 	switch (sp_bsg->type) {
@@ -1123,13 +1128,13 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 	/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
 	 * fc payload  to the caller
 	 */
-	bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+	bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 	bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status);
 
 	if (comp_status != CS_COMPLETE) {
 		if (comp_status == CS_DATA_UNDERRUN) {
-			bsg_job->reply->result = DID_OK << 16;
-			bsg_job->reply->reply_payload_rcv_len =
+			bsg_reply->result = DID_OK << 16;
+			bsg_reply->reply_payload_rcv_len =
 				le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count);
 
 			DEBUG2(qla_printk(KERN_WARNING, ha,
@@ -1147,16 +1152,16 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 				vha->host_no, sp->handle, type, comp_status,
 				le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1),
 				le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2)));
-			bsg_job->reply->result = DID_ERROR << 16;
-			bsg_job->reply->reply_payload_rcv_len = 0;
+			bsg_reply->result = DID_ERROR << 16;
+			bsg_reply->reply_payload_rcv_len = 0;
 			fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
 			memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
 		}
 		DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt)));
 	}
 	else {
-		bsg_job->reply->result =  DID_OK << 16;
-		bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
+		bsg_reply->result =  DID_OK << 16;;
+		bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
 		bsg_job->reply_len = 0;
 	}
 
@@ -1171,7 +1176,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 		kfree(sp->fcport);
 	kfree(sp->ctx);
 	mempool_free(sp, ha->srb_mempool);
-	bsg_job->job_done(bsg_job);
+	bsg_job->job_done(bsg_job, bsg_reply->result,
+			  bsg_reply->reply_payload_rcv_len);
 }
 
 static void
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f461925..a940435 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1214,6 +1214,22 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
 	return QLA_SUCCESS;
 }
 
+static void qla2x00_abort_bsg_job(struct qla_hw_data *ha, srb_t *sp, int res)
+{
+	struct srb_ctx *ctx = sp->ctx;
+	struct scsi_bsg_job *bsg_job = ctx->u.bsg_job;
+	struct fc_bsg_request *bsg_req = bsg_job->request;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+
+	if (bsg_req->msgcode == FC_BSG_HST_CT)
+		kfree(sp->fcport);
+	bsg_job->req->errors = 0;
+	bsg_reply->result = res;
+	bsg_job->job_done(bsg_job, res,	bsg_reply->reply_payload_rcv_len);
+	kfree(sp->ctx);
+	mempool_free(sp, ha->srb_mempool);
+}
+
 void
 qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
 {
@@ -1243,19 +1259,9 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
 					if (ctx->type == SRB_LOGIN_CMD ||
 					    ctx->type == SRB_LOGOUT_CMD) {
 						ctx->u.iocb_cmd->free(sp);
-					} else {
-						struct fc_bsg_job *bsg_job =
-						    ctx->u.bsg_job;
-						if (bsg_job->request->msgcode
-						    == FC_BSG_HST_CT)
-							kfree(sp->fcport);
-						bsg_job->req->errors = 0;
-						bsg_job->reply->result = res;
-						bsg_job->job_done(bsg_job);
-						kfree(sp->ctx);
-						mempool_free(sp,
-							ha->srb_mempool);
-					}
+					} else
+						qla2x00_abort_bsg_job(ha, sp,
+								      res);
 				}
 			}
 		}
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 09/10] lpfc: convert lpfc to scsi bsg lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (7 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 08/10] qla2xxx: convert qla2xxx to scsi bsg lib michaelc
@ 2011-07-22 10:04 ` michaelc
  2011-07-22 10:05 ` [RFC PATCH 10/10] bfa: convert bfa " michaelc
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:04 UTC (permalink / raw)
  To: linux-scsi; +Cc: Vikas Chaudhary, Mike Christie

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

This patch converts lpfc to the scsi bsg lib. The differences
visible to the driver are:
- fc_bsg_job is now named scsi_bsg_job.
- no rport pointer. Can access it through the device pointer.
- the request and reply pointers on the scsi_bsg_job struct
  are now void pointers, so you cannot do bsg_job->request->some_field.

Patch is only compile tested and made over scsi-misc.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/lpfc/lpfc_bsg.c  |  383 ++++++++++++++++++++++++-----------------
 drivers/scsi/lpfc/lpfc_crtn.h |    4 +-
 2 files changed, 226 insertions(+), 161 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 7fb0ba4..e9778c8 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -64,7 +64,7 @@ struct lpfc_bsg_event {
 	struct list_head events_to_see;
 
 	/* job waiting for this event to finish */
-	struct fc_bsg_job *set_job;
+	struct scsi_bsg_job *set_job;
 };
 
 struct lpfc_bsg_iocb {
@@ -74,7 +74,7 @@ struct lpfc_bsg_iocb {
 	struct lpfc_nodelist *ndlp;
 
 	/* job waiting for this iocb to finish */
-	struct fc_bsg_job *set_job;
+	struct scsi_bsg_job *set_job;
 };
 
 struct lpfc_bsg_mbox {
@@ -87,7 +87,7 @@ struct lpfc_bsg_mbox {
 	uint32_t outExtWLen; /* from app */
 
 	/* job waiting for this mbox command to finish */
-	struct fc_bsg_job *set_job;
+	struct scsi_bsg_job *set_job;
 };
 
 #define MENLO_DID 0x0000FC0E
@@ -98,7 +98,7 @@ struct lpfc_bsg_menlo {
 	struct lpfc_dmabuf *bmp;
 
 	/* job waiting for this iocb to finish */
-	struct fc_bsg_job *set_job;
+	struct scsi_bsg_job *set_job;
 };
 
 #define TYPE_EVT 	1
@@ -163,7 +163,8 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 			struct lpfc_iocbq *rspiocbq)
 {
 	struct bsg_job_data *dd_data;
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 	IOCB_t *rsp;
 	struct lpfc_dmabuf *bmp;
 	struct lpfc_nodelist *ndlp;
@@ -182,6 +183,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 	iocb = &dd_data->context_un.iocb;
 	job = iocb->set_job;
 	job->dd_data = NULL; /* so timeout handler does not reply */
+	reply = job->reply;
 
 	bmp = iocb->bmp;
 	rsp = &rspiocbq->iocb;
@@ -208,7 +210,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 		} else
 			rc = -EACCES;
 	} else
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			rsp->un.genreq64.bdl.bdeSize;
 
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
@@ -217,23 +219,25 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 	kfree(bmp);
 	kfree(dd_data);
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	/* complete the job back to userspace */
-	job->job_done(job);
+	job->job_done(job, rc, reply->reply_payload_rcv_len);
 	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 	return;
 }
 
 /**
  * lpfc_bsg_send_mgmt_cmd - send a CT command from a bsg request
- * @job: fc_bsg_job to handle
+ * @job: scsi_bsg_job to handle
  **/
 static int
-lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
+lpfc_bsg_send_mgmt_cmd(struct scsi_bsg_job *job)
 {
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
-	struct lpfc_rport_data *rdata = job->rport->dd_data;
+	struct fc_rport *rport = fc_bsg_get_rport(job);
+	struct lpfc_rport_data *rdata = rport->dd_data;
+	struct fc_bsg_reply *reply = job->reply;
 	struct lpfc_nodelist *ndlp = rdata->pnode;
 	struct ulp_bde64 *bpl = NULL;
 	uint32_t timeout;
@@ -251,7 +255,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
 	int iocb_stat;
 
 	/* in case no data is transferred */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	/* allocate our bsg tracking structure */
 	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
@@ -386,7 +390,7 @@ no_ndlp:
 	kfree(dd_data);
 no_dd_data:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	return rc;
 }
@@ -414,7 +418,8 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 			struct lpfc_iocbq *rspiocbq)
 {
 	struct bsg_job_data *dd_data;
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 	IOCB_t *rsp;
 	struct lpfc_nodelist *ndlp;
 	struct lpfc_dmabuf *pbuflist = NULL;
@@ -437,6 +442,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 		       &rspiocbq->iocb, sizeof(IOCB_t));
 
 	job = dd_data->context_un.iocb.set_job;
+	reply = job->reply;
 	cmdiocbq = dd_data->context_un.iocb.cmdiocbq;
 	rspiocbq = dd_data->context_un.iocb.rspiocbq;
 	rsp = &rspiocbq->iocb;
@@ -447,17 +453,17 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 	pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
 		     job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
 
-	if (job->reply->result == -EAGAIN)
+	if (reply->result == -EAGAIN)
 		rc = -EAGAIN;
 	else if (rsp->ulpStatus == IOSTAT_SUCCESS)
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			rsp->un.elsreq64.bdl.bdeSize;
 	else if (rsp->ulpStatus == IOSTAT_LS_RJT) {
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			sizeof(struct fc_bsg_ctels_reply);
 		/* LS_RJT data returned in word 4 */
 		rjt_data = (uint8_t *)&rsp->un.ulpWord[4];
-		els_reply = &job->reply->reply_data.ctels_reply;
+		els_reply = &reply->reply_data.ctels_reply;
 		els_reply->status = FC_CTELS_STATUS_REJECT;
 		els_reply->rjt_data.action = rjt_data[3];
 		els_reply->rjt_data.reason_code = rjt_data[2];
@@ -473,24 +479,25 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 	lpfc_nlp_put(ndlp);
 	kfree(dd_data);
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	/* complete the job back to userspace */
-	job->job_done(job);
+	job->job_done(job, rc, reply->reply_payload_rcv_len);
 	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 	return;
 }
 
 /**
  * lpfc_bsg_rport_els - send an ELS command from a bsg request
- * @job: fc_bsg_job to handle
+ * @job: scsi_bsg_job to handle
  **/
 static int
-lpfc_bsg_rport_els(struct fc_bsg_job *job)
+lpfc_bsg_rport_els(struct scsi_bsg_job *job)
 {
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
-	struct lpfc_rport_data *rdata = job->rport->dd_data;
+	struct fc_rport *rport = fc_bsg_get_rport(job);
+	struct lpfc_rport_data *rdata = rport->dd_data;
 	struct lpfc_nodelist *ndlp = rdata->pnode;
 	uint32_t elscmd;
 	uint32_t cmdsize;
@@ -509,11 +516,13 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
 	int numbde;
 	dma_addr_t busaddr;
 	struct bsg_job_data *dd_data;
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	uint32_t creg_val;
 	int rc = 0;
 
 	/* in case no data is transferred */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	/* allocate our bsg tracking structure */
 	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
@@ -529,7 +538,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
 		goto free_dd_data;
 	}
 
-	elscmd = job->request->rqst_data.r_els.els_code;
+	elscmd = req->rqst_data.r_els.els_code;
 	cmdsize = job->request_payload.payload_len;
 	rspsize = job->reply_payload.payload_len;
 	rspiocbq = lpfc_sli_get_iocbq(phba);
@@ -639,7 +648,7 @@ free_dd_data:
 
 no_dd_data:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	return rc;
 }
@@ -784,7 +793,8 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 	struct lpfc_dmabuf *bdeBuf2 = piocbq->context3;
 	struct lpfc_hbq_entry *hbqe;
 	struct lpfc_sli_ct_request *ct_req;
-	struct fc_bsg_job *job = NULL;
+	struct scsi_bsg_job *job = NULL;
+	struct fc_bsg_reply *reply;
 	unsigned long flags;
 	int size = 0;
 
@@ -982,13 +992,15 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 		job = evt->set_job;
 		evt->set_job = NULL;
 		if (job) {
-			job->reply->reply_payload_rcv_len = size;
+			reply = job->reply;
+			reply->reply_payload_rcv_len = size;
+
 			/* make error code available to userspace */
-			job->reply->result = 0;
+			reply->result = 0;
 			job->dd_data = NULL;
 			/* complete the job back to userspace */
 			spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
-			job->job_done(job);
+			job->job_done(job, 0, size);
 			spin_lock_irqsave(&phba->ct_ev_lock, flags);
 		}
 	}
@@ -1004,16 +1016,17 @@ error_ct_unsol_exit:
 
 /**
  * lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command
- * @job: SET_EVENT fc_bsg_job
+ * @job: SET_EVENT scsi_bsg_job
  **/
 static int
-lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
+lpfc_bsg_hba_set_event(struct scsi_bsg_job *job)
 {
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct set_ct_event *event_req;
 	struct lpfc_bsg_event *evt;
 	int rc = 0;
+	struct fc_bsg_request *req = job->request;
 	struct bsg_job_data *dd_data = NULL;
 	uint32_t ev_mask;
 	unsigned long flags;
@@ -1036,7 +1049,7 @@ lpfc_bsg_hba_set_event(struct fc_bsg_job *job)
 	}
 
 	event_req = (struct set_ct_event *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 	ev_mask = ((uint32_t)(unsigned long)event_req->type_mask &
 				FC_REG_EVENT_MASK);
 	spin_lock_irqsave(&phba->ct_ev_lock, flags);
@@ -1087,11 +1100,13 @@ job_error:
 
 /**
  * lpfc_bsg_hba_get_event - process a GET_EVENT bsg vendor command
- * @job: GET_EVENT fc_bsg_job
+ * @job: GET_EVENT scsi_bsg_job
  **/
 static int
-lpfc_bsg_hba_get_event(struct fc_bsg_job *job)
+lpfc_bsg_hba_get_event(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct get_ct_event *event_req;
@@ -1111,10 +1126,10 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job)
 	}
 
 	event_req = (struct get_ct_event *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 
 	event_reply = (struct get_ct_event_reply *)
-		job->reply->reply_data.vendor_reply.vendor_rsp;
+		reply->reply_data.vendor_reply.vendor_rsp;
 	spin_lock_irqsave(&phba->ct_ev_lock, flags);
 	list_for_each_entry(evt, &phba->ct_ev_waiters, node) {
 		if (evt->reg_id == event_req->ev_reg_id) {
@@ -1134,7 +1149,7 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job)
 	 * an error indicating that there isn't anymore
 	 */
 	if (evt_dat == NULL) {
-		job->reply->reply_payload_rcv_len = 0;
+		reply->reply_payload_rcv_len = 0;
 		rc = -ENOENT;
 		goto job_error;
 	}
@@ -1150,12 +1165,12 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job)
 	event_reply->type = evt_dat->type;
 	event_reply->immed_data = evt_dat->immed_dat;
 	if (evt_dat->len > 0)
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			sg_copy_from_buffer(job->request_payload.sg_list,
 					    job->request_payload.sg_cnt,
 					    evt_dat->data, evt_dat->len);
 	else
-		job->reply->reply_payload_rcv_len = 0;
+		reply->reply_payload_rcv_len = 0;
 
 	if (evt_dat) {
 		kfree(evt_dat->data);
@@ -1166,13 +1181,13 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job)
 	lpfc_bsg_event_unref(evt);
 	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 	job->dd_data = NULL;
-	job->reply->result = 0;
-	job->job_done(job);
+	reply->result = 0;
+	job->job_done(job, 0, reply->reply_payload_rcv_len);
 	return 0;
 
 job_error:
 	job->dd_data = NULL;
-	job->reply->result = rc;
+	reply->result = rc;
 	return rc;
 }
 
@@ -1199,7 +1214,8 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
 			struct lpfc_iocbq *rspiocbq)
 {
 	struct bsg_job_data *dd_data;
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 	IOCB_t *rsp;
 	struct lpfc_dmabuf *bmp;
 	struct lpfc_nodelist *ndlp;
@@ -1218,6 +1234,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
 	bmp = dd_data->context_un.iocb.bmp;
 	rsp = &rspiocbq->iocb;
 	ndlp = dd_data->context_un.iocb.ndlp;
+	reply = job->reply;
 
 	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
 		     job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -1238,7 +1255,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
 		} else
 			rc = -EACCES;
 	} else
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			rsp->un.genreq64.bdl.bdeSize;
 
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
@@ -1247,10 +1264,10 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
 	kfree(bmp);
 	kfree(dd_data);
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	/* complete the job back to userspace */
-	job->job_done(job);
+	job->job_done(job, rc, reply->reply_payload_rcv_len);
 	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 	return;
 }
@@ -1264,8 +1281,8 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
  * @num_entry: Number of enties in the bde.
  **/
 static int
-lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
-		  struct lpfc_dmabuf *bmp, int num_entry)
+lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct scsi_bsg_job *job,
+		  uint32_t tag, struct lpfc_dmabuf *bmp, int num_entry)
 {
 	IOCB_t *icmd;
 	struct lpfc_iocbq *ctiocb = NULL;
@@ -1394,15 +1411,17 @@ no_dd_data:
 
 /**
  * lpfc_bsg_send_mgmt_rsp - process a SEND_MGMT_RESP bsg vendor command
- * @job: SEND_MGMT_RESP fc_bsg_job
+ * @job: SEND_MGMT_RESP scsi_bsg_job
  **/
 static int
-lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job)
+lpfc_bsg_send_mgmt_rsp(struct scsi_bsg_job *job)
 {
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	struct send_mgmt_resp *mgmt_resp = (struct send_mgmt_resp *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 	struct ulp_bde64 *bpl;
 	struct lpfc_dmabuf *bmp = NULL;
 	struct scatterlist *sgel = NULL;
@@ -1415,7 +1434,7 @@ lpfc_bsg_send_mgmt_rsp(struct fc_bsg_job *job)
 	int rc = 0;
 
 	/* in case no data is transferred */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	if (!reqbfrcnt || (reqbfrcnt > (80 * BUF_SZ_4K))) {
 		rc = -ERANGE;
@@ -1463,7 +1482,7 @@ send_mgmt_rsp_free_bmp:
 	kfree(bmp);
 send_mgmt_rsp_exit:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	return rc;
 }
@@ -1477,7 +1496,7 @@ send_mgmt_rsp_exit:
  * on device.
  */
 static int
-lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct fc_bsg_job *job)
+lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct scsi_bsg_job *job)
 {
 	struct lpfc_vport **vports;
 	struct Scsi_Host *shost;
@@ -1561,8 +1580,11 @@ lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba)
  * All of this is done in-line.
  */
 static int
-lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
+lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba,
+				 struct scsi_bsg_job *job)
 {
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct diag_mode_set *loopback_mode;
 	uint32_t link_flags;
 	uint32_t timeout;
@@ -1572,7 +1594,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
 	int rc = 0;
 
 	/* no data to return just the return code */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	if (job->request_len < sizeof(struct fc_bsg_request) +
 	    sizeof(struct diag_mode_set)) {
@@ -1592,7 +1614,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
 
 	/* bring the link to diagnostic mode */
 	loopback_mode = (struct diag_mode_set *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 	link_flags = loopback_mode->type;
 	timeout = loopback_mode->timeout * 100;
 
@@ -1664,10 +1686,11 @@ loopback_mode_exit:
 
 job_error:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	/* complete the job back to userspace if no error */
 	if (rc == 0)
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 	return rc;
 }
 
@@ -1735,8 +1758,11 @@ link_diag_state_set_out:
  * loopback mode in order to perform a diagnostic loopback test.
  */
 static int
-lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
+lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba,
+				 struct scsi_bsg_job *job)
 {
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct diag_mode_set *loopback_mode;
 	uint32_t link_flags, timeout, req_len, alloc_len;
 	struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
@@ -1744,7 +1770,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
 	int mbxstatus, i, rc = 0;
 
 	/* no data to return just the return code */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	if (job->request_len < sizeof(struct fc_bsg_request) +
 	    sizeof(struct diag_mode_set)) {
@@ -1764,7 +1790,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
 
 	/* bring the link to diagnostic mode */
 	loopback_mode = (struct diag_mode_set *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 	link_flags = loopback_mode->type;
 	timeout = loopback_mode->timeout * 100;
 
@@ -1838,10 +1864,11 @@ loopback_mode_exit:
 
 job_error:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	/* complete the job back to userspace if no error */
 	if (rc == 0)
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 	return rc;
 }
 
@@ -1853,7 +1880,7 @@ job_error:
  * command from the user to proper driver action routines.
  */
 static int
-lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job)
+lpfc_bsg_diag_loopback_mode(struct scsi_bsg_job *job)
 {
 	struct Scsi_Host *shost;
 	struct lpfc_vport *vport;
@@ -1890,7 +1917,7 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job)
  * command from the user to proper driver action routines.
  */
 static int
-lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job)
+lpfc_sli4_bsg_diag_mode_end(struct scsi_bsg_job *job)
 {
 	struct Scsi_Host *shost;
 	struct lpfc_vport *vport;
@@ -1929,8 +1956,10 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job)
  * applicaiton.
  */
 static int
-lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job)
+lpfc_sli4_bsg_link_diag_test(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct Scsi_Host *shost;
 	struct lpfc_vport *vport;
 	struct lpfc_hba *phba;
@@ -1987,7 +2016,7 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job)
 		goto job_error;
 
 	link_diag_test_cmd = (struct sli4_link_diag *)
-			 job->request->rqst_data.h_vendor.vendor_cmd;
+			     req->rqst_data.h_vendor.vendor_cmd;
 	timeout = link_diag_test_cmd->timeout * 100;
 
 	rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
@@ -2038,7 +2067,7 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job)
 	}
 
 	diag_status_reply = (struct diag_status *)
-			    job->reply->reply_data.vendor_reply.vendor_rsp;
+			    reply->reply_data.vendor_reply.vendor_rsp;
 
 	if (job->reply_len <
 	    sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) {
@@ -2066,10 +2095,11 @@ link_diag_test_exit:
 
 job_error:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	/* complete the job back to userspace if no error */
 	if (rc == 0)
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 	return rc;
 }
 
@@ -2618,8 +2648,10 @@ err_post_rxbufs_exit:
  * of loopback mode.
  **/
 static int
-lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
+lpfc_bsg_diag_loopback_run(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct diag_mode_test *diag_mode;
@@ -2649,7 +2681,7 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
 	uint32_t total_mem;
 
 	/* in case no data is returned return just the return code */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	if (job->request_len <
 	    sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_test)) {
@@ -2667,7 +2699,7 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
 	}
 
 	diag_mode = (struct diag_mode_test *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 
 	if ((phba->link_state == LPFC_HBA_ERROR) ||
 	    (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
@@ -2854,11 +2886,11 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
 			rc = IOCB_SUCCESS;
 			/* skip over elx loopback header */
 			rx_databuf += ELX_LOOPBACK_HEADER_SZ;
-			job->reply->reply_payload_rcv_len =
+			reply->reply_payload_rcv_len =
 				sg_copy_from_buffer(job->reply_payload.sg_list,
 						    job->reply_payload.sg_cnt,
 						    rx_databuf, size);
-			job->reply->reply_payload_rcv_len = size;
+			reply->reply_payload_rcv_len = size;
 		}
 	}
 
@@ -2888,21 +2920,24 @@ err_loopback_test_exit:
 loopback_test_exit:
 	kfree(dataout);
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	/* complete the job back to userspace if no error */
 	if (rc == 0)
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 	return rc;
 }
 
 /**
  * lpfc_bsg_get_dfc_rev - process a GET_DFC_REV bsg vendor command
- * @job: GET_DFC_REV fc_bsg_job
+ * @job: GET_DFC_REV scsi_bsg_job
  **/
 static int
-lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
+lpfc_bsg_get_dfc_rev(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_request *req = job->request;
+	struct fc_bsg_reply *reply = job->reply;
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct get_mgmt_rev *event_req;
@@ -2919,10 +2954,10 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
 	}
 
 	event_req = (struct get_mgmt_rev *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 
 	event_reply = (struct get_mgmt_rev_reply *)
-		job->reply->reply_data.vendor_reply.vendor_rsp;
+		reply->reply_data.vendor_reply.vendor_rsp;
 
 	if (job->reply_len <
 	    sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev_reply)) {
@@ -2936,9 +2971,10 @@ lpfc_bsg_get_dfc_rev(struct fc_bsg_job *job)
 	event_reply->info.a_Major = MANAGEMENT_MAJOR_REV;
 	event_reply->info.a_Minor = MANAGEMENT_MINOR_REV;
 job_error:
-	job->reply->result = rc;
+	reply->result = rc;
 	if (rc == 0)
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 	return rc;
 }
 
@@ -2957,7 +2993,8 @@ void
 lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 {
 	struct bsg_job_data *dd_data;
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 	uint32_t size;
 	unsigned long flags;
 	uint8_t *pmb, *pmb_buf;
@@ -2980,8 +3017,9 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 
 	job = dd_data->context_un.mbox.set_job;
 	if (job) {
+		reply = job->reply;
 		size = job->reply_payload.payload_len;
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			sg_copy_from_buffer(job->reply_payload.sg_list,
 					    job->reply_payload.sg_cnt,
 					    pmb_buf, size);
@@ -3002,8 +3040,9 @@ lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 	kfree(dd_data);
 
 	if (job) {
-		job->reply->result = 0;
-		job->job_done(job);
+		reply->result = 0;
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 	}
 	return;
 }
@@ -3131,11 +3170,12 @@ lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba)
  * This is routine handles BSG job for mailbox commands completions with
  * multiple external buffers.
  **/
-static struct fc_bsg_job *
+static struct scsi_bsg_job *
 lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 {
 	struct bsg_job_data *dd_data;
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 	uint8_t *pmb, *pmb_buf;
 	unsigned long flags;
 	uint32_t size;
@@ -3160,13 +3200,14 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 
 	job = dd_data->context_un.mbox.set_job;
 	if (job) {
+		reply = job->reply;
 		size = job->reply_payload.payload_len;
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			sg_copy_from_buffer(job->reply_payload.sg_list,
 					    job->reply_payload.sg_cnt,
 					    pmb_buf, size);
 		/* result for successful */
-		job->reply->result = 0;
+		reply->result = 0;
 		job->dd_data = NULL;
 		/* need to hold the lock util we set job->dd_data to NULL
 		 * to hold off the timeout handler from midlayer to take
@@ -3206,7 +3247,8 @@ job_done_out:
 static void
 lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 {
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 
 	/* handle the BSG job with mailbox command */
 	if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS)
@@ -3226,9 +3268,11 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 	mempool_free(pmboxq, phba->mbox_mem_pool);
 
 	/* complete the bsg job if we have it */
-	if (job)
-		job->job_done(job);
-
+	if (job) {
+		reply = job->reply;
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
+	}
 	return;
 }
 
@@ -3243,7 +3287,8 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 static void
 lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 {
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 
 	/* handle the BSG job with the mailbox command */
 	if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS)
@@ -3261,9 +3306,11 @@ lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 	lpfc_bsg_mbox_ext_session_reset(phba);
 
 	/* complete the bsg job if we have it */
-	if (job)
-		job->job_done(job);
-
+	if (job) {
+		reply = job->reply;
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
+	}
 	return;
 }
 
@@ -3371,10 +3418,11 @@ lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp,
  * non-embedded external bufffers.
  **/
 static int
-lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 			      enum nemb_type nemb_tp,
 			      struct lpfc_dmabuf *dmabuf)
 {
+	struct fc_bsg_request *req = job->request;
 	struct lpfc_sli_config_mbox *sli_cfg_mbx;
 	struct dfc_mbox_req *mbox_req;
 	struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf;
@@ -3387,7 +3435,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
 	int rc, i;
 
 	mbox_req =
-	   (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
+	   (struct dfc_mbox_req *)req->rqst_data.h_vendor.vendor_cmd;
 
 	/* pointer to the start of mailbox command */
 	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
@@ -3538,10 +3586,11 @@ job_error:
  * non-embedded external bufffers.
  **/
 static int
-lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 			       enum nemb_type nemb_tp,
 			       struct lpfc_dmabuf *dmabuf)
 {
+	struct fc_bsg_request *req = job->request;
 	struct dfc_mbox_req *mbox_req;
 	struct lpfc_sli_config_mbox *sli_cfg_mbx;
 	uint32_t ext_buf_cnt;
@@ -3552,7 +3601,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
 	int rc = 0, i;
 
 	mbox_req =
-	   (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
+	   (struct dfc_mbox_req *)req->rqst_data.h_vendor.vendor_cmd;
 
 	/* pointer to the start of mailbox command */
 	sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
@@ -3687,7 +3736,7 @@ job_error:
  * with embedded sussystem 0x1 and opcodes with external HBDs.
  **/
 static int
-lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 			     struct lpfc_dmabuf *dmabuf)
 {
 	struct lpfc_sli_config_mbox *sli_cfg_mbx;
@@ -3808,8 +3857,9 @@ lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba)
  * user space through BSG.
  **/
 static int
-lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
+lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
 	struct lpfc_sli_config_mbox *sli_cfg_mbx;
 	struct lpfc_dmabuf *dmabuf;
 	uint8_t *pbuf;
@@ -3841,7 +3891,7 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
 				  struct lpfc_dmabuf, list);
 	list_del_init(&dmabuf->list);
 	pbuf = (uint8_t *)dmabuf->virt;
-	job->reply->reply_payload_rcv_len =
+	reply->reply_payload_rcv_len =
 		sg_copy_from_buffer(job->reply_payload.sg_list,
 				    job->reply_payload.sg_cnt,
 				    pbuf, size);
@@ -3855,8 +3905,8 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
 		lpfc_bsg_mbox_ext_session_reset(phba);
 	}
 
-	job->reply->result = 0;
-	job->job_done(job);
+	reply->result = 0;
+	job->job_done(job, 0, reply->reply_payload_rcv_len);
 
 	return SLI_CONFIG_HANDLED;
 }
@@ -3870,9 +3920,10 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
  * from user space through BSG.
  **/
 static int
-lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 			struct lpfc_dmabuf *dmabuf)
 {
+	struct fc_bsg_reply *reply = job->reply;
 	struct lpfc_sli_config_mbox *sli_cfg_mbx;
 	struct bsg_job_data *dd_data = NULL;
 	LPFC_MBOXQ_t *pmboxq = NULL;
@@ -3969,8 +4020,8 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
 	}
 
 	/* wait for additoinal external buffers */
-	job->reply->result = 0;
-	job->job_done(job);
+	reply->result = 0;
+	job->job_done(job, 0, 0);
 	return SLI_CONFIG_HANDLED;
 
 job_error:
@@ -3990,7 +4041,7 @@ job_error:
  * command with multiple non-embedded external buffers.
  **/
 static int
-lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 			     struct lpfc_dmabuf *dmabuf)
 {
 	int rc;
@@ -4035,14 +4086,14 @@ lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job,
  * (0x9B) mailbox commands and external buffers.
  **/
 static int
-lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 			    struct lpfc_dmabuf *dmabuf)
 {
+	struct fc_bsg_request *req = job->request;
 	struct dfc_mbox_req *mbox_req;
 	int rc;
 
-	mbox_req =
-	   (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
+	mbox_req = (struct dfc_mbox_req *)req->rqst_data.h_vendor.vendor_cmd;
 
 	/* mbox command with/without single external buffer */
 	if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0)
@@ -4112,9 +4163,11 @@ sli_cfg_ext_error:
  * let our completion handler finish the command.
  **/
 static uint32_t
-lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
+lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct scsi_bsg_job *job,
 	struct lpfc_vport *vport)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */
 	MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */
 	/* a 4k buffer to hold the mb and extended data from/to the bsg */
@@ -4135,7 +4188,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
 
 
 	/* in case no data is transferred */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	/* sanity check to protect driver */
 	if (job->reply_payload.payload_len > BSG_MBOX_SIZE ||
@@ -4153,8 +4206,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
 		goto job_done;
 	}
 
-	mbox_req =
-	    (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd;
+	mbox_req = (struct dfc_mbox_req *)req->rqst_data.h_vendor.vendor_cmd;
 
 	/* check if requested extended data lengths are valid */
 	if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||
@@ -4374,7 +4426,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
 
 		/* job finished, copy the data */
 		memcpy(pmbx, pmb, sizeof(*pmb));
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			sg_copy_from_buffer(job->reply_payload.sg_list,
 					    job->reply_payload.sg_cnt,
 					    pmbx, size);
@@ -4403,15 +4455,17 @@ job_cont:
  * @job: MBOX fc_bsg_job for LPFC_BSG_VENDOR_MBOX.
  **/
 static int
-lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
+lpfc_bsg_mbox_cmd(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct dfc_mbox_req *mbox_req;
 	int rc = 0;
 
 	/* mix-and-match backward compatibility */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 	if (job->request_len <
 	    sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) {
 		lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
@@ -4422,7 +4476,7 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
 				      sizeof(struct fc_bsg_request)),
 				(int)sizeof(struct dfc_mbox_req));
 		mbox_req = (struct dfc_mbox_req *)
-				job->request->rqst_data.h_vendor.vendor_cmd;
+				req->rqst_data.h_vendor.vendor_cmd;
 		mbox_req->extMboxTag = 0;
 		mbox_req->extSeqNum = 0;
 	}
@@ -4431,15 +4485,15 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job)
 
 	if (rc == 0) {
 		/* job done */
-		job->reply->result = 0;
+		reply->result = 0;
 		job->dd_data = NULL;
-		job->job_done(job);
+		job->job_done(job, 0, reply->reply_payload_rcv_len);
 	} else if (rc == 1)
 		/* job submitted, will complete later*/
 		rc = 0; /* return zero, no error */
 	else {
 		/* some error occurred */
-		job->reply->result = rc;
+		reply->result = rc;
 		job->dd_data = NULL;
 	}
 
@@ -4469,7 +4523,8 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
 			struct lpfc_iocbq *rspiocbq)
 {
 	struct bsg_job_data *dd_data;
-	struct fc_bsg_job *job;
+	struct scsi_bsg_job *job;
+	struct fc_bsg_reply *reply;
 	IOCB_t *rsp;
 	struct lpfc_dmabuf *bmp;
 	struct lpfc_bsg_menlo *menlo;
@@ -4486,6 +4541,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
 
 	menlo = &dd_data->context_un.menlo;
 	job = menlo->set_job;
+	reply = job->reply;
 	job->dd_data = NULL; /* so timeout handler does not reply */
 
 	spin_lock(&phba->hbalock);
@@ -4509,7 +4565,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
 	 * of the exchange.
 	 */
 	menlo_resp = (struct menlo_response *)
-		job->reply->reply_data.vendor_reply.vendor_rsp;
+		reply->reply_data.vendor_reply.vendor_rsp;
 	menlo_resp->xri = rsp->ulpContext;
 	if (rsp->ulpStatus) {
 		if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
@@ -4527,7 +4583,7 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
 		} else
 			rc = -EACCES;
 	} else
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 			rsp->un.genreq64.bdl.bdeSize;
 
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
@@ -4536,16 +4592,16 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
 	kfree(bmp);
 	kfree(dd_data);
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	/* complete the job back to userspace */
-	job->job_done(job);
+	job->job_done(job, reply->result, reply->reply_payload_rcv_len);
 	spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 	return;
 }
 
 /**
  * lpfc_menlo_cmd - send an ioctl for menlo hardware
- * @job: fc_bsg_job to handle
+ * @job: scsi_bsg_job to handle
  *
  * This function issues a gen request 64 CR ioctl for all menlo cmd requests,
  * all the command completions will return the xri for the command.
@@ -4553,8 +4609,10 @@ lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
  * supplied in the menlo request header xri field.
  **/
 static int
-lpfc_menlo_cmd(struct fc_bsg_job *job)
+lpfc_menlo_cmd(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_iocbq *cmdiocbq, *rspiocbq;
@@ -4572,7 +4630,7 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
 	struct ulp_bde64 *bpl = NULL;
 
 	/* in case no data is returned return just the return code */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	if (job->request_len <
 	    sizeof(struct fc_bsg_request) +
@@ -4602,10 +4660,10 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
 	}
 
 	menlo_cmd = (struct menlo_command *)
-		job->request->rqst_data.h_vendor.vendor_cmd;
+		req->rqst_data.h_vendor.vendor_cmd;
 
 	menlo_resp = (struct menlo_response *)
-		job->reply->reply_data.vendor_reply.vendor_rsp;
+		reply->reply_data.vendor_reply.vendor_rsp;
 
 	/* allocate our bsg tracking structure */
 	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
@@ -4733,19 +4791,21 @@ free_dd:
 	kfree(dd_data);
 no_dd_data:
 	/* make error code available to userspace */
-	job->reply->result = rc;
+	reply->result = rc;
 	job->dd_data = NULL;
 	return rc;
 }
 
 /**
  * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
- * @job: fc_bsg_job to handle
+ * @job: scsi_bsg_job to handle
  **/
 static int
-lpfc_bsg_hst_vendor(struct fc_bsg_job *job)
+lpfc_bsg_hst_vendor(struct scsi_bsg_job *job)
 {
-	int command = job->request->rqst_data.h_vendor.vendor_cmd[0];
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
+	int command = req->rqst_data.h_vendor.vendor_cmd[0];
 	int rc;
 
 	switch (command) {
@@ -4782,9 +4842,9 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job)
 		break;
 	default:
 		rc = -EINVAL;
-		job->reply->reply_payload_rcv_len = 0;
+		reply->reply_payload_rcv_len = 0;
 		/* make error code available to userspace */
-		job->reply->result = rc;
+		reply->result = rc;
 		break;
 	}
 
@@ -4793,15 +4853,17 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job)
 
 /**
  * lpfc_bsg_request - handle a bsg request from the FC transport
- * @job: fc_bsg_job to handle
+ * @job: scsi_bsg_job to handle
  **/
 int
-lpfc_bsg_request(struct fc_bsg_job *job)
+lpfc_bsg_request(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	uint32_t msgcode;
 	int rc;
 
-	msgcode = job->request->msgcode;
+	msgcode = req->msgcode;
 	switch (msgcode) {
 	case FC_BSG_HST_VENDOR:
 		rc = lpfc_bsg_hst_vendor(job);
@@ -4814,9 +4876,9 @@ lpfc_bsg_request(struct fc_bsg_job *job)
 		break;
 	default:
 		rc = -EINVAL;
-		job->reply->reply_payload_rcv_len = 0;
+		reply->reply_payload_rcv_len = 0;
 		/* make error code available to userspace */
-		job->reply->result = rc;
+		reply->result = rc;
 		break;
 	}
 
@@ -4825,14 +4887,15 @@ lpfc_bsg_request(struct fc_bsg_job *job)
 
 /**
  * lpfc_bsg_timeout - handle timeout of a bsg request from the FC transport
- * @job: fc_bsg_job that has timed out
+ * @job: scsi_bsg_job that has timed out
  *
  * This function just aborts the job's IOCB.  The aborted IOCB will return to
  * the waiting function which will handle passing the error back to userspace
  **/
 int
-lpfc_bsg_timeout(struct fc_bsg_job *job)
+lpfc_bsg_timeout(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
 	struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
 	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_iocbq *cmdiocb;
@@ -4857,7 +4920,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
 		iocb = &dd_data->context_un.iocb;
 		cmdiocb = iocb->cmdiocbq;
 		/* hint to completion handler that the job timed out */
-		job->reply->result = -EAGAIN;
+		reply->result = -EAGAIN;
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 		/* this will call our completion handler */
 		spin_lock_irq(&phba->hbalock);
@@ -4869,24 +4932,26 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
 		/* this event has no job anymore */
 		evt->set_job = NULL;
 		job->dd_data = NULL;
-		job->reply->reply_payload_rcv_len = 0;
+		reply->reply_payload_rcv_len = 0;
 		/* Return -EAGAIN which is our way of signallying the
 		 * app to retry.
 		 */
-		job->reply->result = -EAGAIN;
+		reply->result = -EAGAIN;
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 		break;
 	case TYPE_MBOX:
 		mbox = &dd_data->context_un.mbox;
 		/* this mbox has no job anymore */
 		mbox->set_job = NULL;
 		job->dd_data = NULL;
-		job->reply->reply_payload_rcv_len = 0;
-		job->reply->result = -EAGAIN;
+		reply->reply_payload_rcv_len = 0;
+		reply->result = -EAGAIN;
 		/* the mbox completion handler can now be run */
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
-		job->job_done(job);
+		job->job_done(job, reply->result,
+			      reply->reply_payload_rcv_len);
 		if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT)
 			phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
 		break;
@@ -4894,7 +4959,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
 		menlo = &dd_data->context_un.menlo;
 		cmdiocb = menlo->cmdiocbq;
 		/* hint to completion handler that the job timed out */
-		job->reply->result = -EAGAIN;
+		reply->result = -EAGAIN;
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 		/* this will call our completion handler */
 		spin_lock_irq(&phba->hbalock);
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index fc20c24..cb71efb 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -415,8 +415,8 @@ struct lpfc_sglq *__lpfc_get_active_sglq(struct lpfc_hba *, uint16_t);
 #define HBA_EVENT_LINK_DOWN              3
 
 /* functions to support SGIOv4/bsg interface */
-int lpfc_bsg_request(struct fc_bsg_job *);
-int lpfc_bsg_timeout(struct fc_bsg_job *);
+int lpfc_bsg_request(struct scsi_bsg_job *);
+int lpfc_bsg_timeout(struct scsi_bsg_job *);
 int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
 			     struct lpfc_iocbq *);
 void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *,
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC PATCH 10/10] bfa: convert bfa to scsi bsg lib
  2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
                   ` (8 preceding siblings ...)
  2011-07-22 10:04 ` [RFC PATCH 09/10] lpfc: convert lpfc " michaelc
@ 2011-07-22 10:05 ` michaelc
  9 siblings, 0 replies; 13+ messages in thread
From: michaelc @ 2011-07-22 10:05 UTC (permalink / raw)
  To: linux-scsi; +Cc: Vikas Chaudhary, Mike Christie

From: Vikas Chaudhary <vikas.chaudhary@qlogic.com>

Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
 drivers/scsi/bfa/bfad_bsg.c |   52 ++++++++++++++++++++++++-------------------
 drivers/scsi/bfa/bfad_im.h  |    4 +-
 2 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 89f863e..ba6f8f2 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -1710,9 +1710,11 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
 }
 
 static int
-bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
+bfad_im_bsg_vendor_request(struct scsi_bsg_job *job)
 {
-	uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0];
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
+	uint32_t vendor_cmd = req->rqst_data.h_vendor.vendor_cmd[0];
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) job->shost->hostdata[0];
 	struct bfad_s *bfad = im_port->bfad;
@@ -1748,18 +1750,18 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
 
 	/* Fill the BSG job reply data */
 	job->reply_len = job->reply_payload.payload_len;
-	job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
-	job->reply->result = rc;
+	reply->reply_payload_rcv_len = job->reply_payload.payload_len;
+	reply->result = rc;
 
-	job->job_done(job);
+	job->job_done(job, reply->result, reply->reply_payload_rcv_len);
 	return rc;
 error:
 	/* free the command buffer */
 	kfree(payload_kbuf);
 out:
-	job->reply->result = rc;
+	reply->result = rc;
 	job->reply_len = sizeof(uint32_t);
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 	return rc;
 }
 
@@ -1885,7 +1887,7 @@ bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base,
 }
 
 int
-bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
+bfad_fcxp_bsg_send(struct scsi_bsg_job *job, struct bfad_fcxp *drv_fcxp,
 		   bfa_bsg_fcpt_t *bsg_fcpt)
 {
 	struct bfa_fcxp_s *hal_fcxp;
@@ -1925,8 +1927,10 @@ bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
 }
 
 int
-bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
+bfad_im_bsg_els_ct_request(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	struct bfa_bsg_data *bsg_data;
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) job->shost->hostdata[0];
@@ -1935,17 +1939,17 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
 	struct bfad_fcxp    *drv_fcxp;
 	struct bfa_fcs_lport_s *fcs_port;
 	struct bfa_fcs_rport_s *fcs_rport;
-	uint32_t command_type = job->request->msgcode;
+	uint32_t command_type = req->msgcode;
 	unsigned long flags;
 	struct bfad_buf_info *rsp_buf_info;
 	void *req_kbuf = NULL, *rsp_kbuf = NULL;
 	int rc = -EINVAL;
 
 	job->reply_len  = sizeof(uint32_t);	/* Atleast uint32_t reply_len */
-	job->reply->reply_payload_rcv_len = 0;
+	reply->reply_payload_rcv_len = 0;
 
 	/* Get the payload passed in from userspace */
-	bsg_data = (struct bfa_bsg_data *) (((char *)job->request) +
+	bsg_data = (struct bfa_bsg_data *) (((char *)req) +
 					sizeof(struct fc_bsg_request));
 	if (bsg_data == NULL)
 		goto out;
@@ -2086,13 +2090,13 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
 	/* fill the job->reply data */
 	if (drv_fcxp->req_status == BFA_STATUS_OK) {
 		job->reply_len = drv_fcxp->rsp_len;
-		job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len;
-		job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+		reply->reply_payload_rcv_len = drv_fcxp->rsp_len;
+		reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 	} else {
-		job->reply->reply_payload_rcv_len =
+		reply->reply_payload_rcv_len =
 					sizeof(struct fc_bsg_ctels_reply);
 		job->reply_len = sizeof(uint32_t);
-		job->reply->reply_data.ctels_reply.status =
+		reply->reply_data.ctels_reply.status =
 						FC_CTELS_STATUS_REJECT;
 	}
 
@@ -2118,20 +2122,22 @@ out_free_mem:
 	kfree(bsg_fcpt);
 	kfree(drv_fcxp);
 out:
-	job->reply->result = rc;
+	reply->result = rc;
 
 	if (rc == BFA_STATUS_OK)
-		job->job_done(job);
+		job->job_done(job, reply->result, reply->reply_payload_rcv_len);
 
 	return rc;
 }
 
 int
-bfad_im_bsg_request(struct fc_bsg_job *job)
+bfad_im_bsg_request(struct scsi_bsg_job *job)
 {
+	struct fc_bsg_reply *reply = job->reply;
+	struct fc_bsg_request *req = job->request;
 	uint32_t rc = BFA_STATUS_OK;
 
-	switch (job->request->msgcode) {
+	switch (req->msgcode) {
 	case FC_BSG_HST_VENDOR:
 		/* Process BSG HST Vendor requests */
 		rc = bfad_im_bsg_vendor_request(job);
@@ -2144,8 +2150,8 @@ bfad_im_bsg_request(struct fc_bsg_job *job)
 		rc = bfad_im_bsg_els_ct_request(job);
 		break;
 	default:
-		job->reply->result = rc = -EINVAL;
-		job->reply->reply_payload_rcv_len = 0;
+		reply->result = rc = -EINVAL;
+		reply->reply_payload_rcv_len = 0;
 		break;
 	}
 
@@ -2153,7 +2159,7 @@ bfad_im_bsg_request(struct fc_bsg_job *job)
 }
 
 int
-bfad_im_bsg_timeout(struct fc_bsg_job *job)
+bfad_im_bsg_timeout(struct scsi_bsg_job *job)
 {
 	/* Don't complete the BSG job request - return -EAGAIN
 	 * to reset bsg job timeout : for ELS/CT pass thru we
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index 4fe34d5..2b78735 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -141,7 +141,7 @@ extern struct device_attribute *bfad_im_vport_attrs[];
 
 irqreturn_t bfad_intx(int irq, void *dev_id);
 
-int bfad_im_bsg_request(struct fc_bsg_job *job);
-int bfad_im_bsg_timeout(struct fc_bsg_job *job);
+int bfad_im_bsg_request(struct scsi_bsg_job *job);
+int bfad_im_bsg_timeout(struct scsi_bsg_job *job);
 
 #endif
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib
  2011-07-22 10:04 ` [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib michaelc
@ 2011-07-22 16:31   ` FUJITA Tomonori
  2011-07-23  3:19     ` Mike Christie
  0 siblings, 1 reply; 13+ messages in thread
From: FUJITA Tomonori @ 2011-07-22 16:31 UTC (permalink / raw)
  To: michaelc; +Cc: linux-scsi

On Fri, 22 Jul 2011 05:04:52 -0500
michaelc@cs.wisc.edu wrote:

> From: Mike Christie <michaelc@cs.wisc.edu>
> 
> This moves the FC class bsg code to a scsi lib, so
> all drivers and classes do not have to duplicate common
> bits.
> 
> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
> ---
>  drivers/scsi/Kconfig    |    6 +
>  drivers/scsi/Makefile   |    1 +
>  drivers/scsi/scsi_bsg.c |  374 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/scsi/Kbuild     |    1 +
>  include/scsi/scsi_bsg.h |   83 +++++++++++
>  5 files changed, 465 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/scsi/scsi_bsg.c
>  create mode 100644 include/scsi/scsi_bsg.h

Nice. Seems more llds need bsg support so I think that this is a good
idea.


> diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
> index 4a1f029..327ec7e 100644
> --- a/drivers/scsi/Kconfig
> +++ b/drivers/scsi/Kconfig
> @@ -47,6 +47,11 @@ config SCSI_TGT
>  	  If you want to use SCSI target mode drivers enable this option.
>  	  If you choose M, the module will be called scsi_tgt.
>  
> +config SCSI_BSG
> +	bool
> +	default	n
> +	select BLK_DEV_BSG
> +
>  config SCSI_NETLINK
>  	bool
>  	default	n
> @@ -294,6 +299,7 @@ config SCSI_FC_ATTRS
>  	tristate "FiberChannel Transport Attributes"
>  	depends on SCSI
>  	select SCSI_NETLINK
> +	select SCSI_BSG
>  	help
>  	  If you wish to export transport-specific information about
>  	  each attached FiberChannel device to sysfs, say Y.
> diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
> index 7ad0b8a..0cdb572 100644
> --- a/drivers/scsi/Makefile
> +++ b/drivers/scsi/Makefile
> @@ -162,6 +162,7 @@ scsi_mod-y			+= scsi.o hosts.o scsi_ioctl.o constants.o \
>  				   scsicam.o scsi_error.o scsi_lib.o
>  scsi_mod-$(CONFIG_SCSI_DMA)	+= scsi_lib_dma.o
>  scsi_mod-y			+= scsi_scan.o scsi_sysfs.o scsi_devinfo.o
> +scsi_mod-$(CONFIG_SCSI_BSG)	+= scsi_bsg.o
>  scsi_mod-$(CONFIG_SCSI_NETLINK)	+= scsi_netlink.o
>  scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
>  scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
> diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
> new file mode 100644
> index 0000000..89b507e
> --- /dev/null
> +++ b/drivers/scsi/scsi_bsg.c
> @@ -0,0 +1,374 @@
> +/*
> + *  BSG helper library for scsi classes
> + *
> + *  Copyright (C) 2008   James Smart, Emulex Corporation
> + *  Copyright (C) 2010   Red Hat, Inc.  All rights reserved.
> + *  Copyright (C) 2010   Mike Christie
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +#include <linux/slab.h>
> +#include <linux/blkdev.h>
> +#include <linux/delay.h>
> +#include <scsi/scsi_bsg.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_transport.h>
> +
> +/**
> + * scsi_destroy_bsg_job - routine to teardown/delete a bsg job
> + * @job: scsi_bsg_job that is to be torn down
> + */
> +static void scsi_destroy_bsg_job(struct scsi_bsg_job *job)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&job->job_lock, flags);
> +	if (job->ref_cnt) {
> +		spin_unlock_irqrestore(&job->job_lock, flags);
> +		return;
> +	}
> +	spin_unlock_irqrestore(&job->job_lock, flags);

Is this actually a reference counter? Doesn't look like how we use a
reference counter? If scsi_bsg_job needs it, it would be better to
just put kref in it?


> +	put_device(job->dev);	/* release reference for the request */
> +
> +	kfree(job->request_payload.sg_list);
> +	kfree(job->reply_payload.sg_list);
> +	kfree(job);
> +}
> +
> +/**
> + * scsi_bsg_job_done - completion routine for bsg requests
> + * @job: scsi_bsg_job that is complete
> + * @result: job reply result
> + * @reply_payload_rcv_len: length of payload recvd
> + */
> +void scsi_bsg_job_done(struct scsi_bsg_job *job, int result,
> +		       unsigned int reply_payload_rcv_len)
> +{
> +	struct request *req = job->req;
> +	struct request *rsp = req->next_rq;
> +	int err;
> +
> +	err = job->req->errors = result;
> +	if (err < 0)
> +		/* we're only returning the result field in the reply */
> +		job->req->sense_len = sizeof(u32);
> +	else
> +		job->req->sense_len = job->reply_len;
> +	/* we assume all request payload was transferred, residual == 0 */
> +	req->resid_len = 0;
> +
> +	if (rsp) {
> +		WARN_ON(reply_payload_rcv_len > rsp->resid_len);
> +
> +		/* set reply (bidi) residual */
> +		rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len);
> +	}
> +	blk_complete_request(req);
> +}
> +EXPORT_SYMBOL_GPL(scsi_bsg_job_done);
> +
> +/**
> + * scsi_bsg_softirq_done - softirq done routine for destroying the bsg requests
> + * @rq: BSG request that holds the job to be destroyed
> + */
> +static void scsi_bsg_softirq_done(struct request *rq)
> +{
> +	struct scsi_bsg_job *job = rq->special;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&job->job_lock, flags);
> +	job->state_flags |= SCSI_RQST_STATE_DONE;
> +	job->ref_cnt--;
> +	spin_unlock_irqrestore(&job->job_lock, flags);
> +
> +	blk_end_request_all(rq, rq->errors);
> +	scsi_destroy_bsg_job(job);
> +}
> +
> +/**
> + * scsi_bsg_job_timeout - handler for when a bsg request timesout
> + * @req: request that timed out
> + */
> +static enum blk_eh_timer_return scsi_bsg_job_timeout(struct request *req)
> +{
> +	struct scsi_bsg_job *job = req->special;
> +	struct Scsi_Host *shost = job->shost;
> +	unsigned long flags;
> +	int err = 0, done = 0;
> +
> +	spin_lock_irqsave(&job->job_lock, flags);
> +	if (job->state_flags & SCSI_RQST_STATE_DONE)
> +		done = 1;
> +	else
> +		job->ref_cnt++;
> +	spin_unlock_irqrestore(&job->job_lock, flags);
> +
> +	if (!done && shost->transportt->eh_bsg_job_timed_out) {
> +		/* call LLDD to abort the i/o as it has timed out */
> +		err = shost->transportt->eh_bsg_job_timed_out(job);
> +		if (err == -EAGAIN) {
> +			job->ref_cnt--;
> +			return BLK_EH_RESET_TIMER;
> +		} else if (err)
> +			printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
> +				"abort failed with status %d\n", err);
> +	}
> +
> +	/* the blk_end_sync_io() doesn't check the error */
> +	if (done)
> +		return BLK_EH_NOT_HANDLED;
> +	else
> +		return BLK_EH_HANDLED;
> +}
> +
> +static int scsi_bsg_map_buffer(struct scsi_bsg_buffer *buf, struct request *req)
> +{

Might be simpler to use scsi_data_buffer instead of inventing
scsi_bsg_buffer. Not sure.

> +	size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
> +
> +	BUG_ON(!req->nr_phys_segments);
> +
> +	buf->sg_list = kzalloc(sz, GFP_KERNEL);
> +	if (!buf->sg_list)
> +		return -ENOMEM;
> +	sg_init_table(buf->sg_list, req->nr_phys_segments);
> +	buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
> +	buf->payload_len = blk_rq_bytes(req);
> +	return 0;
> +}
> +
> +/**
> + * scsi_bsg_create_job - create the scsi_bsg_job structure for the bsg request
> + * @shost: SCSI Host corresponding to the bsg object
> + * @dev: device that is being sent the bsg request
> + * @req: BSG request that needs a job structure
> + */
> +static int scsi_bsg_create_job(struct Scsi_Host *shost, struct device *dev,
> +			       struct request *req)
> +{
> +	struct request *rsp = req->next_rq;
> +	struct scsi_bsg_job *job;
> +	int ret;
> +
> +	BUG_ON(req->special);
> +
> +	job = kzalloc(sizeof(struct scsi_bsg_job) +
> +		      shost->transportt->bsg_job_size, GFP_KERNEL);
> +	if (!job)
> +		return -ENOMEM;
> +
> +	/*
> +	 * Note: this is a bit silly.
> +	 * The request gets formatted as a SGIO v4 ioctl request, which
> +	 * then gets reformatted as a blk request, which then gets
> +	 * reformatted as a scsi bsg request. And on completion, we have

Yeah. We could modify bsg to support formatting SGIO to scsi bsg
request (killing the blk request formatting). But it means that bsg
can't use nice blk functions like blk_rq_map|unmap_user. I guess that
the code might be simpler with the intermediate blk request
formatting.


> +	 * to wrap return results such that SGIO v4 thinks it was a scsi
> +	 * status.  I hope this was all worth it.
> +	 */
> +
> +	req->special = job;
> +	job->shost = shost;
> +	job->req = req;
> +	if (shost->transportt->bsg_job_size)
> +		job->dd_data = (void *)&job[1];
> +	spin_lock_init(&job->job_lock);
> +	job->request = req->cmd;
> +	job->request_len = req->cmd_len;
> +	job->reply = req->sense;
> +	job->reply_len = SCSI_SENSE_BUFFERSIZE;	/* Size of sense buffer
> +						 * allocated */
> +	if (req->bio) {
> +		ret = scsi_bsg_map_buffer(&job->request_payload, req);
> +		if (ret)
> +			goto failjob_rls_job;
> +	}
> +	if (rsp && rsp->bio) {
> +		ret = scsi_bsg_map_buffer(&job->reply_payload, rsp);
> +		if (ret)
> +			goto failjob_rls_rqst_payload;
> +	}
> +	job->job_done = scsi_bsg_job_done;
> +	job->dev = dev;
> +	/* take a reference for the request */
> +	get_device(job->dev);
> +	job->ref_cnt = 1;
> +	return 0;
> +
> +failjob_rls_rqst_payload:
> +	kfree(job->request_payload.sg_list);
> +failjob_rls_job:
> +	kfree(job);
> +	return -ENOMEM;
> +}
> +
> +/*
> + * scsi_bsg_goose_queue - restart queue in case it was stopped
> + * @dev: device that owns queue
> + * @q: request q to be restarted
> + */
> +void scsi_bsg_goose_queue(struct device *dev, struct request_queue *q)
> +{
> +	if (!q)
> +		return;
> +
> +	/*
> +	 * This get/put dance makes no sense
> +	 */
> +
> +	get_device(dev);
> +	blk_run_queue_async(q);
> +	put_device(dev);
> +}
> +EXPORT_SYMBOL_GPL(scsi_bsg_goose_queue);
> +
> +/**
> + * scsi_bsg_request_fn - generic handler for bsg requests
> + * @q: request queue to manage
> + *
> + * On error the create_bsg_job function should return a -Exyz error value
> + * that will be set to the req->errors.
> + */
> +static void scsi_bsg_request_fn(struct request_queue *q)
> +{
> +	struct device *dev = q->queuedata;
> +	struct Scsi_Host *shost = dev_to_shost(dev);
> +	struct request *req;
> +	struct scsi_bsg_job *job;
> +	int ret;
> +
> +	if (!shost)
> +		return;
> +
> +	if (!get_device(dev))
> +		return;
> +
> +	while (1) {
> +		req = blk_fetch_request(q);
> +		if (!req)
> +			break;
> +		spin_unlock_irq(q->queue_lock);
> +
> +		ret = scsi_bsg_create_job(shost, dev, req);
> +		if (ret) {
> +			req->errors = ret;
> +			blk_end_request_all(req, ret);
> +			spin_lock_irq(q->queue_lock);
> +			continue;
> +		}
> +
> +		job = req->special;
> +		/* the dispatch routines will unlock the queue_lock */
> +		ret = shost->transportt->queue_bsg_job(job);
> +		spin_lock_irq(q->queue_lock);
> +		if (ret)
> +			break;
> +	}
> +
> +	spin_unlock_irq(q->queue_lock);
> +	put_device(dev);
> +	spin_lock_irq(q->queue_lock);
> +}
> +
> +/**
> + * scsi_bsg_add - Create and add the bsg hooks so we can receive requests
> + * @dev: device to attach bsg device to
> + */
> +struct request_queue *scsi_bsg_add(struct device *dev, char *name)
> +{
> +	struct Scsi_Host *shost = dev_to_shost(dev);
> +	struct request_queue *q;
> +
> +	if (!shost)
> +		return NULL;
> +
> +	q = __scsi_alloc_queue(shost, scsi_bsg_request_fn);
> +	if (!q) {
> +		printk(KERN_ERR "%s: bsg interface failed to "
> +				"initialize - no request queue\n",
> +				 dev->kobj.name);
> +		return NULL;
> +	}
> +	q->queuedata = dev;
> +
> +	queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
> +	blk_queue_softirq_done(q, scsi_bsg_softirq_done);
> +	blk_queue_rq_timed_out(q, scsi_bsg_job_timeout);
> +	blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
> +
> +	if (bsg_register_queue(q, dev, name, NULL)) {
> +		printk(KERN_ERR "%s: bsg interface failed to "
> +		       "initialize - register queue\n", dev->kobj.name);
> +		blk_cleanup_queue(q);
> +		return NULL;
> +	}
> +
> +	return q;
> +}
> +EXPORT_SYMBOL_GPL(scsi_bsg_add);
> +
> +/**
> + * scsi_bsg_remove - Deletes the bsg dev from the q
> + * @q:	the request_queue that is to be torn down.
> + *
> + * Notes:
> + *   Before unregistering the queue empty any requests that are blocked
> + */
> +void scsi_bsg_remove(struct request_queue *q)
> +{
> +	struct request *req; /* block request */
> +	int counts; /* totals for request_list count and starved */

This function looks hacky a bit (e.g. peeking at the queue internal
values such as count and starved). Can we do this in a different way
(less hacky way)?

> +	if (q) {
> +		/* Stop taking in new requests */
> +		spin_lock_irq(q->queue_lock);
> +		blk_stop_queue(q);
> +
> +		/* drain all requests in the queue */
> +		while (1) {
> +			/* need the lock to fetch a request
> +			 * this may fetch the same reqeust as the previous pass
> +			 */
> +			req = blk_fetch_request(q);
> +			/* save requests in use and starved */
> +			counts = q->rq.count[0] + q->rq.count[1] +
> +				 q->rq.starved[0] + q->rq.starved[1];
> +			spin_unlock_irq(q->queue_lock);
> +			/* any requests still outstanding? */
> +			if (counts == 0)
> +				break;
> +
> +			/* This may be the same req as the previous iteration,
> +			 * always send the blk_end_request_all after a prefetch.
> +			 * It is not okay to not end the request because the
> +			 * prefetch started the request.
> +			 */
> +			if (req) {
> +				/* return -ENXIO to indicate that this queue is
> +				 * going away
> +				 */
> +				req->errors = -ENXIO;
> +				blk_end_request_all(req, -ENXIO);
> +			}
> +
> +			msleep(200); /* allow bsg to possibly finish */

Hmm, what's it? Do we need to fix something about bsg?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib
  2011-07-22 16:31   ` FUJITA Tomonori
@ 2011-07-23  3:19     ` Mike Christie
  0 siblings, 0 replies; 13+ messages in thread
From: Mike Christie @ 2011-07-23  3:19 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linux-scsi

On 07/22/2011 11:31 AM, FUJITA Tomonori wrote:
>> +/**
>> + * scsi_destroy_bsg_job - routine to teardown/delete a bsg job
>> + * @job: scsi_bsg_job that is to be torn down
>> + */
>> +static void scsi_destroy_bsg_job(struct scsi_bsg_job *job)
>> +{
>> +	unsigned long flags;
>> +
>> +	spin_lock_irqsave(&job->job_lock, flags);
>> +	if (job->ref_cnt) {
>> +		spin_unlock_irqrestore(&job->job_lock, flags);
>> +		return;
>> +	}
>> +	spin_unlock_irqrestore(&job->job_lock, flags);
> 
> Is this actually a reference counter? Doesn't look like how we use a
> reference counter? If scsi_bsg_job needs it, it would be better to
> just put kref in it?

Yeah, I do not think it is needed. That and the state_flags should not
be needed (state flag seems to duplicate the request state handling). I
have patches to remove that code. I was going to send them separately
though, so just in case I/we are wrong it can be git reverted. I guess
it can just be merged in this patch though.



>> +void scsi_bsg_remove(struct request_queue *q)
>> +{
>> +	struct request *req; /* block request */
>> +	int counts; /* totals for request_list count and starved */
> 
> This function looks hacky a bit (e.g. peeking at the queue internal
> values such as count and starved). Can we do this in a different way
> (less hacky way)?
> 


>> +			}
>> +
>> +			msleep(200); /* allow bsg to possibly finish */
> 
> Hmm, what's it? Do we need to fix something about bsg?

James Smart had added this in 78d16341facf829a71b6f7c68ec5511b9c168060.
I do not think it can be easily fixed. I think he is working on a better
long term fix.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-07-23  3:19 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-22 10:04 [RFC PATCH 00/10] create scsi bsg lib michaelc
2011-07-22 10:04 ` [RFC PATCH 01/10] scsi transport: add bsg callouts michaelc
2011-07-22 10:04 ` [RFC PATCH 02/10] scsi bsg: add scsi bsg helper lib michaelc
2011-07-22 16:31   ` FUJITA Tomonori
2011-07-23  3:19     ` Mike Christie
2011-07-22 10:04 ` [RFC PATCH 03/10] FC class: convert to scsi bsg lib michaelc
2011-07-22 10:04 ` [RFC PATCH 04/10] iscsi class: add bsg support to iscsi class michaelc
2011-07-22 10:04 ` [RFC PATCH 05/10] ibmvfc: convert ibmvfc to scsi bsg lib michaelc
2011-07-22 10:04 ` [RFC PATCH 06/10] libfc: convert " michaelc
2011-07-22 10:04 ` [RFC PATCH 07/10] zfcp: convert zfcp to scsi bsg lib V2 michaelc
2011-07-22 10:04 ` [RFC PATCH 08/10] qla2xxx: convert qla2xxx to scsi bsg lib michaelc
2011-07-22 10:04 ` [RFC PATCH 09/10] lpfc: convert lpfc " michaelc
2011-07-22 10:05 ` [RFC PATCH 10/10] bfa: convert bfa " michaelc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox