aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2011-07-25 14:48:50 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:36:21 -0400
commit90eeb01a038e5fec0efdea4df008f3c18f67b82c (patch)
tree9977dd9000374e1162f56934efcf0e5b8c7c7155
parent6ac73e8cb02e65abeb2f8d43f0fe48e485444b44 (diff)
[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>
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c114
-rw-r--r--include/scsi/scsi_bsg_iscsi.h110
-rw-r--r--include/scsi/scsi_transport_iscsi.h7
4 files changed, 230 insertions, 2 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8d9dae89f06..4a79b9d8615 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -309,6 +309,7 @@ config SCSI_FC_TGT_ATTRS
309config SCSI_ISCSI_ATTRS 309config SCSI_ISCSI_ATTRS
310 tristate "iSCSI Transport Attributes" 310 tristate "iSCSI Transport Attributes"
311 depends on SCSI && NET 311 depends on SCSI && NET
312 select BLK_DEV_BSGLIB
312 help 313 help
313 If you wish to export transport-specific information about 314 If you wish to export transport-specific information about
314 each attached iSCSI device to sysfs, say Y. 315 each attached iSCSI device to sysfs, say Y.
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 13f90515ff6..cde679f1b01 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -23,6 +23,7 @@
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/bsg-lib.h>
26#include <net/tcp.h> 27#include <net/tcp.h>
27#include <scsi/scsi.h> 28#include <scsi/scsi.h>
28#include <scsi/scsi_host.h> 29#include <scsi/scsi_host.h>
@@ -31,6 +32,7 @@
31#include <scsi/scsi_transport_iscsi.h> 32#include <scsi/scsi_transport_iscsi.h>
32#include <scsi/iscsi_if.h> 33#include <scsi/iscsi_if.h>
33#include <scsi/scsi_cmnd.h> 34#include <scsi/scsi_cmnd.h>
35#include <scsi/scsi_bsg_iscsi.h>
34 36
35#define ISCSI_TRANSPORT_VERSION "2.0-870" 37#define ISCSI_TRANSPORT_VERSION "2.0-870"
36 38
@@ -447,6 +449,99 @@ void iscsi_destroy_iface(struct iscsi_iface *iface)
447} 449}
448EXPORT_SYMBOL_GPL(iscsi_destroy_iface); 450EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
449 451
452/*
453 * BSG support
454 */
455/**
456 * iscsi_bsg_host_dispatch - Dispatch command to LLD.
457 * @job: bsg job to be processed
458 */
459static int iscsi_bsg_host_dispatch(struct bsg_job *job)
460{
461 struct Scsi_Host *shost = iscsi_job_to_shost(job);
462 struct iscsi_bsg_request *req = job->request;
463 struct iscsi_bsg_reply *reply = job->reply;
464 struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
465 int cmdlen = sizeof(uint32_t); /* start with length of msgcode */
466 int ret;
467
468 /* check if we have the msgcode value at least */
469 if (job->request_len < sizeof(uint32_t)) {
470 ret = -ENOMSG;
471 goto fail_host_msg;
472 }
473
474 /* Validate the host command */
475 switch (req->msgcode) {
476 case ISCSI_BSG_HST_VENDOR:
477 cmdlen += sizeof(struct iscsi_bsg_host_vendor);
478 if ((shost->hostt->vendor_id == 0L) ||
479 (req->rqst_data.h_vendor.vendor_id !=
480 shost->hostt->vendor_id)) {
481 ret = -ESRCH;
482 goto fail_host_msg;
483 }
484 break;
485 default:
486 ret = -EBADR;
487 goto fail_host_msg;
488 }
489
490 /* check if we really have all the request data needed */
491 if (job->request_len < cmdlen) {
492 ret = -ENOMSG;
493 goto fail_host_msg;
494 }
495
496 ret = i->iscsi_transport->bsg_request(job);
497 if (!ret)
498 return 0;
499
500fail_host_msg:
501 /* return the errno failure code as the only status */
502 BUG_ON(job->reply_len < sizeof(uint32_t));
503 reply->reply_payload_rcv_len = 0;
504 reply->result = ret;
505 job->reply_len = sizeof(uint32_t);
506 bsg_job_done(job, ret, 0);
507 return 0;
508}
509
510/**
511 * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
512 * @shost: shost for iscsi_host
513 * @cls_host: iscsi_cls_host adding the structures to
514 */
515static int
516iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
517{
518 struct device *dev = &shost->shost_gendev;
519 struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
520 struct request_queue *q;
521 char bsg_name[20];
522 int ret;
523
524 if (!i->iscsi_transport->bsg_request)
525 return -ENOTSUPP;
526
527 snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
528
529 q = __scsi_alloc_queue(shost, bsg_request_fn);
530 if (!q)
531 return -ENOMEM;
532
533 ret = bsg_setup_queue(dev, q, bsg_name, iscsi_bsg_host_dispatch, 0);
534 if (ret) {
535 shost_printk(KERN_ERR, shost, "bsg interface failed to "
536 "initialize - no request queue\n");
537 blk_cleanup_queue(q);
538 return ret;
539 }
540
541 ihost->bsg_q = q;
542 return 0;
543}
544
450static int iscsi_setup_host(struct transport_container *tc, struct device *dev, 545static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
451 struct device *cdev) 546 struct device *cdev)
452{ 547{
@@ -456,13 +551,30 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
456 memset(ihost, 0, sizeof(*ihost)); 551 memset(ihost, 0, sizeof(*ihost));
457 atomic_set(&ihost->nr_scans, 0); 552 atomic_set(&ihost->nr_scans, 0);
458 mutex_init(&ihost->mutex); 553 mutex_init(&ihost->mutex);
554
555 iscsi_bsg_host_add(shost, ihost);
556 /* ignore any bsg add error - we just can't do sgio */
557
558 return 0;
559}
560
561static int iscsi_remove_host(struct transport_container *tc,
562 struct device *dev, struct device *cdev)
563{
564 struct Scsi_Host *shost = dev_to_shost(dev);
565 struct iscsi_cls_host *ihost = shost->shost_data;
566
567 if (ihost->bsg_q) {
568 bsg_remove_queue(ihost->bsg_q);
569 blk_cleanup_queue(ihost->bsg_q);
570 }
459 return 0; 571 return 0;
460} 572}
461 573
462static DECLARE_TRANSPORT_CLASS(iscsi_host_class, 574static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
463 "iscsi_host", 575 "iscsi_host",
464 iscsi_setup_host, 576 iscsi_setup_host,
465 NULL, 577 iscsi_remove_host,
466 NULL); 578 NULL);
467 579
468static DECLARE_TRANSPORT_CLASS(iscsi_session_class, 580static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
diff --git a/include/scsi/scsi_bsg_iscsi.h b/include/scsi/scsi_bsg_iscsi.h
new file mode 100644
index 00000000000..fd5689d4c05
--- /dev/null
+++ b/include/scsi/scsi_bsg_iscsi.h
@@ -0,0 +1,110 @@
1/*
2 * iSCSI Transport BSG Interface
3 *
4 * Copyright (C) 2009 James Smart, Emulex Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#ifndef SCSI_BSG_ISCSI_H
23#define SCSI_BSG_ISCSI_H
24
25/*
26 * This file intended to be included by both kernel and user space
27 */
28
29#include <scsi/scsi.h>
30
31/*
32 * iSCSI Transport SGIO v4 BSG Message Support
33 */
34
35/* Default BSG request timeout (in seconds) */
36#define ISCSI_DEFAULT_BSG_TIMEOUT (10 * HZ)
37
38
39/*
40 * Request Message Codes supported by the iSCSI Transport
41 */
42
43/* define the class masks for the message codes */
44#define ISCSI_BSG_CLS_MASK 0xF0000000 /* find object class */
45#define ISCSI_BSG_HST_MASK 0x80000000 /* iscsi host class */
46
47/* iscsi host Message Codes */
48#define ISCSI_BSG_HST_VENDOR (ISCSI_BSG_HST_MASK | 0x000000FF)
49
50
51/*
52 * iSCSI Host Messages
53 */
54
55/* ISCSI_BSG_HST_VENDOR : */
56
57/* Request:
58 * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
59 * formatting requirements specified in scsi_netlink.h
60 */
61struct iscsi_bsg_host_vendor {
62 /*
63 * Identifies the vendor that the message is formatted for. This
64 * should be the recipient of the message.
65 */
66 uint64_t vendor_id;
67
68 /* start of vendor command area */
69 uint32_t vendor_cmd[0];
70};
71
72/* Response:
73 */
74struct iscsi_bsg_host_vendor_reply {
75 /* start of vendor response area */
76 uint32_t vendor_rsp[0];
77};
78
79
80/* request (CDB) structure of the sg_io_v4 */
81struct iscsi_bsg_request {
82 uint32_t msgcode;
83 union {
84 struct iscsi_bsg_host_vendor h_vendor;
85 } rqst_data;
86} __attribute__((packed));
87
88
89/* response (request sense data) structure of the sg_io_v4 */
90struct iscsi_bsg_reply {
91 /*
92 * The completion result. Result exists in two forms:
93 * if negative, it is an -Exxx system errno value. There will
94 * be no further reply information supplied.
95 * else, it's the 4-byte scsi error result, with driver, host,
96 * msg and status fields. The per-msgcode reply structure
97 * will contain valid data.
98 */
99 uint32_t result;
100
101 /* If there was reply_payload, how much was recevied ? */
102 uint32_t reply_payload_rcv_len;
103
104 union {
105 struct iscsi_bsg_host_vendor_reply vendor_reply;
106 } reply_data;
107};
108
109
110#endif /* SCSI_BSG_ISCSI_H */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 77e6dd60fb4..4a3edeeae8f 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -38,6 +38,7 @@ struct iscsi_conn;
38struct iscsi_task; 38struct iscsi_task;
39struct sockaddr; 39struct sockaddr;
40struct iscsi_iface; 40struct iscsi_iface;
41struct bsg_job;
41 42
42/** 43/**
43 * struct iscsi_transport - iSCSI Transport template 44 * struct iscsi_transport - iSCSI Transport template
@@ -141,9 +142,9 @@ struct iscsi_transport {
141 enum iscsi_param_type param_type, 142 enum iscsi_param_type param_type,
142 int param, char *buf); 143 int param, char *buf);
143 mode_t (*attr_is_visible)(int param_type, int param); 144 mode_t (*attr_is_visible)(int param_type, int param);
145 int (*bsg_request)(struct bsg_job *job);
144}; 146};
145 147
146
147/* 148/*
148 * transport registration upcalls 149 * transport registration upcalls
149 */ 150 */
@@ -227,8 +228,12 @@ struct iscsi_cls_session {
227struct iscsi_cls_host { 228struct iscsi_cls_host {
228 atomic_t nr_scans; 229 atomic_t nr_scans;
229 struct mutex mutex; 230 struct mutex mutex;
231 struct request_queue *bsg_q;
230}; 232};
231 233
234#define iscsi_job_to_shost(_job) \
235 dev_to_shost(_job->dev)
236
232extern void iscsi_host_for_each_session(struct Scsi_Host *shost, 237extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
233 void (*fn)(struct iscsi_cls_session *)); 238 void (*fn)(struct iscsi_cls_session *));
234 239