diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2011-07-25 14:48:50 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-08-27 10:36:21 -0400 |
commit | 90eeb01a038e5fec0efdea4df008f3c18f67b82c (patch) | |
tree | 9977dd9000374e1162f56934efcf0e5b8c7c7155 /drivers/scsi/scsi_transport_iscsi.c | |
parent | 6ac73e8cb02e65abeb2f8d43f0fe48e485444b44 (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>
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 13f90515ff6e..cde679f1b01d 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 | } |
448 | EXPORT_SYMBOL_GPL(iscsi_destroy_iface); | 450 | EXPORT_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 | */ | ||
459 | static 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 | |||
500 | fail_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 | */ | ||
515 | static int | ||
516 | iscsi_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 | |||
450 | static int iscsi_setup_host(struct transport_container *tc, struct device *dev, | 545 | static 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 | |||
561 | static 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 | ||
462 | static DECLARE_TRANSPORT_CLASS(iscsi_host_class, | 574 | static 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 | ||
468 | static DECLARE_TRANSPORT_CLASS(iscsi_session_class, | 580 | static DECLARE_TRANSPORT_CLASS(iscsi_session_class, |