diff options
author | Christoph Hellwig <hch@lst.de> | 2015-11-26 03:55:48 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-12-01 12:59:38 -0500 |
commit | bf7d3ebbd219d8ad948e812d03e1decfd96c97d0 (patch) | |
tree | 922044b551e96c9291bb92419a5d98933a166675 | |
parent | 7a67cbea653e444d04d7e850ab9631a14a196422 (diff) |
nvme: split nvme_trans_device_id_page
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/nvme/host/scsi.c | 135 |
1 files changed, 79 insertions, 56 deletions
diff --git a/drivers/nvme/host/scsi.c b/drivers/nvme/host/scsi.c index 85869946d226..b42cf448a55e 100644 --- a/drivers/nvme/host/scsi.c +++ b/drivers/nvme/host/scsi.c | |||
@@ -600,70 +600,93 @@ static int nvme_trans_unit_serial_page(struct nvme_ns *ns, | |||
600 | return nvme_trans_copy_to_user(hdr, inq_response, xfer_len); | 600 | return nvme_trans_copy_to_user(hdr, inq_response, xfer_len); |
601 | } | 601 | } |
602 | 602 | ||
603 | static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr, | 603 | static int nvme_fill_device_id_eui64(struct nvme_ns *ns, struct sg_io_hdr *hdr, |
604 | u8 *inq_response, int alloc_len) | 604 | u8 *inq_response, int alloc_len) |
605 | { | 605 | { |
606 | struct nvme_dev *dev = ns->dev; | 606 | struct nvme_id_ns *id_ns; |
607 | int res; | 607 | int nvme_sc, res; |
608 | int nvme_sc; | 608 | size_t len; |
609 | int xfer_len; | 609 | void *eui; |
610 | __be32 tmp_id = cpu_to_be32(ns->ns_id); | ||
611 | 610 | ||
612 | memset(inq_response, 0, alloc_len); | 611 | nvme_sc = nvme_identify_ns(ns->dev, ns->ns_id, &id_ns); |
613 | inq_response[1] = INQ_DEVICE_IDENTIFICATION_PAGE; /* Page Code */ | 612 | res = nvme_trans_status_code(hdr, nvme_sc); |
614 | if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1)) { | 613 | if (res) |
615 | struct nvme_id_ns *id_ns; | 614 | return res; |
616 | void *eui; | ||
617 | int len; | ||
618 | 615 | ||
619 | nvme_sc = nvme_identify_ns(dev, ns->ns_id, &id_ns); | 616 | eui = id_ns->eui64; |
620 | res = nvme_trans_status_code(hdr, nvme_sc); | 617 | len = sizeof(id_ns->eui64); |
621 | if (res) | ||
622 | return res; | ||
623 | 618 | ||
624 | eui = id_ns->eui64; | 619 | if (readl(ns->dev->bar + NVME_REG_VS) >= NVME_VS(1, 2)) { |
625 | len = sizeof(id_ns->eui64); | ||
626 | if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2)) { | ||
627 | if (bitmap_empty(eui, len * 8)) { | ||
628 | eui = id_ns->nguid; | ||
629 | len = sizeof(id_ns->nguid); | ||
630 | } | ||
631 | } | ||
632 | if (bitmap_empty(eui, len * 8)) { | 620 | if (bitmap_empty(eui, len * 8)) { |
633 | kfree(id_ns); | 621 | eui = id_ns->nguid; |
634 | goto scsi_string; | 622 | len = sizeof(id_ns->nguid); |
635 | } | 623 | } |
624 | } | ||
636 | 625 | ||
637 | inq_response[3] = 4 + len; /* Page Length */ | 626 | if (bitmap_empty(eui, len * 8)) { |
638 | /* Designation Descriptor start */ | 627 | res = -EOPNOTSUPP; |
639 | inq_response[4] = 0x01; /* Proto ID=0h | Code set=1h */ | 628 | goto out_free_id; |
640 | inq_response[5] = 0x02; /* PIV=0b | Asso=00b | Designator Type=2h */ | ||
641 | inq_response[6] = 0x00; /* Rsvd */ | ||
642 | inq_response[7] = len; /* Designator Length */ | ||
643 | memcpy(&inq_response[8], eui, len); | ||
644 | kfree(id_ns); | ||
645 | } else { | ||
646 | scsi_string: | ||
647 | if (alloc_len < 72) { | ||
648 | return nvme_trans_completion(hdr, | ||
649 | SAM_STAT_CHECK_CONDITION, | ||
650 | ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB, | ||
651 | SCSI_ASCQ_CAUSE_NOT_REPORTABLE); | ||
652 | } | ||
653 | inq_response[3] = 0x48; /* Page Length */ | ||
654 | /* Designation Descriptor start */ | ||
655 | inq_response[4] = 0x03; /* Proto ID=0h | Code set=3h */ | ||
656 | inq_response[5] = 0x08; /* PIV=0b | Asso=00b | Designator Type=8h */ | ||
657 | inq_response[6] = 0x00; /* Rsvd */ | ||
658 | inq_response[7] = 0x44; /* Designator Length */ | ||
659 | |||
660 | sprintf(&inq_response[8], "%04x", to_pci_dev(dev->dev)->vendor); | ||
661 | memcpy(&inq_response[12], dev->model, sizeof(dev->model)); | ||
662 | sprintf(&inq_response[52], "%04x", tmp_id); | ||
663 | memcpy(&inq_response[56], dev->serial, sizeof(dev->serial)); | ||
664 | } | 629 | } |
665 | xfer_len = alloc_len; | 630 | |
666 | return nvme_trans_copy_to_user(hdr, inq_response, xfer_len); | 631 | memset(inq_response, 0, alloc_len); |
632 | inq_response[1] = INQ_DEVICE_IDENTIFICATION_PAGE; | ||
633 | inq_response[3] = 4 + len; /* Page Length */ | ||
634 | |||
635 | /* Designation Descriptor start */ | ||
636 | inq_response[4] = 0x01; /* Proto ID=0h | Code set=1h */ | ||
637 | inq_response[5] = 0x02; /* PIV=0b | Asso=00b | Designator Type=2h */ | ||
638 | inq_response[6] = 0x00; /* Rsvd */ | ||
639 | inq_response[7] = len; /* Designator Length */ | ||
640 | memcpy(&inq_response[8], eui, len); | ||
641 | |||
642 | res = nvme_trans_copy_to_user(hdr, inq_response, alloc_len); | ||
643 | out_free_id: | ||
644 | kfree(id_ns); | ||
645 | return res; | ||
646 | } | ||
647 | |||
648 | static int nvme_fill_device_id_scsi_string(struct nvme_ns *ns, | ||
649 | struct sg_io_hdr *hdr, u8 *inq_response, int alloc_len) | ||
650 | { | ||
651 | struct nvme_dev *dev = ns->dev; | ||
652 | |||
653 | if (alloc_len < 72) { | ||
654 | return nvme_trans_completion(hdr, | ||
655 | SAM_STAT_CHECK_CONDITION, | ||
656 | ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB, | ||
657 | SCSI_ASCQ_CAUSE_NOT_REPORTABLE); | ||
658 | } | ||
659 | |||
660 | memset(inq_response, 0, alloc_len); | ||
661 | inq_response[1] = INQ_DEVICE_IDENTIFICATION_PAGE; | ||
662 | inq_response[3] = 0x48; /* Page Length */ | ||
663 | |||
664 | /* Designation Descriptor start */ | ||
665 | inq_response[4] = 0x03; /* Proto ID=0h | Code set=3h */ | ||
666 | inq_response[5] = 0x08; /* PIV=0b | Asso=00b | Designator Type=8h */ | ||
667 | inq_response[6] = 0x00; /* Rsvd */ | ||
668 | inq_response[7] = 0x44; /* Designator Length */ | ||
669 | |||
670 | sprintf(&inq_response[8], "%04x", to_pci_dev(dev->dev)->vendor); | ||
671 | memcpy(&inq_response[12], dev->model, sizeof(dev->model)); | ||
672 | sprintf(&inq_response[52], "%04x", cpu_to_be32(ns->ns_id)); | ||
673 | memcpy(&inq_response[56], dev->serial, sizeof(dev->serial)); | ||
674 | |||
675 | return nvme_trans_copy_to_user(hdr, inq_response, alloc_len); | ||
676 | } | ||
677 | |||
678 | static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr, | ||
679 | u8 *resp, int alloc_len) | ||
680 | { | ||
681 | int res; | ||
682 | |||
683 | if (readl(ns->dev->bar + NVME_REG_VS) >= NVME_VS(1, 1)) { | ||
684 | res = nvme_fill_device_id_eui64(ns, hdr, resp, alloc_len); | ||
685 | if (res != -EOPNOTSUPP) | ||
686 | return res; | ||
687 | } | ||
688 | |||
689 | return nvme_fill_device_id_scsi_string(ns, hdr, resp, alloc_len); | ||
667 | } | 690 | } |
668 | 691 | ||
669 | static int nvme_trans_ext_inq_page(struct nvme_ns *ns, struct sg_io_hdr *hdr, | 692 | static int nvme_trans_ext_inq_page(struct nvme_ns *ns, struct sg_io_hdr *hdr, |