mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
[SCSI] iscsi class: add bsg support to iscsi class
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. This patch is made over this one http://marc.info/?l=linux-scsi&m=131149780020992&w=2 Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
6ac73e8cb0
commit
90eeb01a03
4 changed files with 230 additions and 2 deletions
|
@ -309,6 +309,7 @@ config SCSI_FC_TGT_ATTRS
|
||||||
config SCSI_ISCSI_ATTRS
|
config SCSI_ISCSI_ATTRS
|
||||||
tristate "iSCSI Transport Attributes"
|
tristate "iSCSI Transport Attributes"
|
||||||
depends on SCSI && NET
|
depends on SCSI && NET
|
||||||
|
select BLK_DEV_BSGLIB
|
||||||
help
|
help
|
||||||
If you wish to export transport-specific information about
|
If you wish to export transport-specific information about
|
||||||
each attached iSCSI device to sysfs, say Y.
|
each attached iSCSI device to sysfs, say Y.
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/bsg-lib.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/scsi_host.h>
|
#include <scsi/scsi_host.h>
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
#include <scsi/scsi_transport_iscsi.h>
|
#include <scsi/scsi_transport_iscsi.h>
|
||||||
#include <scsi/iscsi_if.h>
|
#include <scsi/iscsi_if.h>
|
||||||
#include <scsi/scsi_cmnd.h>
|
#include <scsi/scsi_cmnd.h>
|
||||||
|
#include <scsi/scsi_bsg_iscsi.h>
|
||||||
|
|
||||||
#define ISCSI_TRANSPORT_VERSION "2.0-870"
|
#define ISCSI_TRANSPORT_VERSION "2.0-870"
|
||||||
|
|
||||||
|
@ -447,6 +449,99 @@ void iscsi_destroy_iface(struct iscsi_iface *iface)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
|
EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BSG support
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* iscsi_bsg_host_dispatch - Dispatch command to LLD.
|
||||||
|
* @job: bsg job to be processed
|
||||||
|
*/
|
||||||
|
static int iscsi_bsg_host_dispatch(struct bsg_job *job)
|
||||||
|
{
|
||||||
|
struct Scsi_Host *shost = iscsi_job_to_shost(job);
|
||||||
|
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);
|
||||||
|
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];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!i->iscsi_transport->bsg_request)
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
|
||||||
|
|
||||||
|
q = __scsi_alloc_queue(shost, bsg_request_fn);
|
||||||
|
if (!q)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = bsg_setup_queue(dev, q, bsg_name, iscsi_bsg_host_dispatch, 0);
|
||||||
|
if (ret) {
|
||||||
|
shost_printk(KERN_ERR, shost, "bsg interface failed to "
|
||||||
|
"initialize - no request queue\n");
|
||||||
|
blk_cleanup_queue(q);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ihost->bsg_q = q;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
|
static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
|
||||||
struct device *cdev)
|
struct device *cdev)
|
||||||
{
|
{
|
||||||
|
@ -456,13 +551,30 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
|
||||||
memset(ihost, 0, sizeof(*ihost));
|
memset(ihost, 0, sizeof(*ihost));
|
||||||
atomic_set(&ihost->nr_scans, 0);
|
atomic_set(&ihost->nr_scans, 0);
|
||||||
mutex_init(&ihost->mutex);
|
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;
|
||||||
|
|
||||||
|
if (ihost->bsg_q) {
|
||||||
|
bsg_remove_queue(ihost->bsg_q);
|
||||||
|
blk_cleanup_queue(ihost->bsg_q);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
|
static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
|
||||||
"iscsi_host",
|
"iscsi_host",
|
||||||
iscsi_setup_host,
|
iscsi_setup_host,
|
||||||
NULL,
|
iscsi_remove_host,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
|
static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
|
||||||
|
|
110
include/scsi/scsi_bsg_iscsi.h
Normal file
110
include/scsi/scsi_bsg_iscsi.h
Normal file
|
@ -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 */
|
|
@ -38,6 +38,7 @@ struct iscsi_conn;
|
||||||
struct iscsi_task;
|
struct iscsi_task;
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
struct iscsi_iface;
|
struct iscsi_iface;
|
||||||
|
struct bsg_job;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iscsi_transport - iSCSI Transport template
|
* struct iscsi_transport - iSCSI Transport template
|
||||||
|
@ -141,9 +142,9 @@ struct iscsi_transport {
|
||||||
enum iscsi_param_type param_type,
|
enum iscsi_param_type param_type,
|
||||||
int param, char *buf);
|
int param, char *buf);
|
||||||
mode_t (*attr_is_visible)(int param_type, int param);
|
mode_t (*attr_is_visible)(int param_type, int param);
|
||||||
|
int (*bsg_request)(struct bsg_job *job);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* transport registration upcalls
|
* transport registration upcalls
|
||||||
*/
|
*/
|
||||||
|
@ -227,8 +228,12 @@ struct iscsi_cls_session {
|
||||||
struct iscsi_cls_host {
|
struct iscsi_cls_host {
|
||||||
atomic_t nr_scans;
|
atomic_t nr_scans;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
struct request_queue *bsg_q;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define iscsi_job_to_shost(_job) \
|
||||||
|
dev_to_shost(_job->dev)
|
||||||
|
|
||||||
extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
|
extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
|
||||||
void (*fn)(struct iscsi_cls_session *));
|
void (*fn)(struct iscsi_cls_session *));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue