aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-11-26 03:55:48 -0500
committerJens Axboe <axboe@fb.com>2015-12-01 12:59:38 -0500
commitbf7d3ebbd219d8ad948e812d03e1decfd96c97d0 (patch)
tree922044b551e96c9291bb92419a5d98933a166675
parent7a67cbea653e444d04d7e850ab9631a14a196422 (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.c135
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
603static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr, 603static 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);
643out_free_id:
644 kfree(id_ns);
645 return res;
646}
647
648static 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
678static 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
669static int nvme_trans_ext_inq_page(struct nvme_ns *ns, struct sg_io_hdr *hdr, 692static int nvme_trans_ext_inq_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,