.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * nvme-lightnvm.c - LightNVM NVMe device |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2014-2015 IT University of Copenhagen |
---|
5 | 6 | * Initial release: Matias Bjorling <mb@lightnvm.io> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License version |
---|
9 | | - * 2 as published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, but |
---|
12 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
14 | | - * 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; see the file COPYING. If not, write to |
---|
18 | | - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, |
---|
19 | | - * USA. |
---|
20 | | - * |
---|
21 | 7 | */ |
---|
22 | 8 | |
---|
23 | 9 | #include "nvme.h" |
---|
.. | .. |
---|
185 | 171 | __le32 tdresv; |
---|
186 | 172 | __le32 thresv; |
---|
187 | 173 | __le32 rsvd2[8]; |
---|
188 | | - __u8 blk[0]; |
---|
| 174 | + __u8 blk[]; |
---|
189 | 175 | }; |
---|
190 | 176 | |
---|
191 | 177 | struct nvme_nvm_id20_addrf { |
---|
.. | .. |
---|
567 | 553 | * Expect the lba in device format |
---|
568 | 554 | */ |
---|
569 | 555 | static int nvme_nvm_get_chk_meta(struct nvm_dev *ndev, |
---|
570 | | - struct nvm_chk_meta *meta, |
---|
571 | | - sector_t slba, int nchks) |
---|
| 556 | + sector_t slba, int nchks, |
---|
| 557 | + struct nvm_chk_meta *meta) |
---|
572 | 558 | { |
---|
573 | 559 | struct nvm_geo *geo = &ndev->geo; |
---|
574 | 560 | struct nvme_ns *ns = ndev->q->queuedata; |
---|
575 | 561 | struct nvme_ctrl *ctrl = ns->ctrl; |
---|
576 | | - struct nvme_nvm_chk_meta *dev_meta = (struct nvme_nvm_chk_meta *)meta; |
---|
| 562 | + struct nvme_nvm_chk_meta *dev_meta, *dev_meta_off; |
---|
577 | 563 | struct ppa_addr ppa; |
---|
578 | 564 | size_t left = nchks * sizeof(struct nvme_nvm_chk_meta); |
---|
579 | 565 | size_t log_pos, offset, len; |
---|
580 | | - int ret, i, max_len; |
---|
| 566 | + int i, max_len; |
---|
| 567 | + int ret = 0; |
---|
581 | 568 | |
---|
582 | 569 | /* |
---|
583 | 570 | * limit requests to maximum 256K to avoid issuing arbitrary large |
---|
584 | 571 | * requests when the device does not specific a maximum transfer size. |
---|
585 | 572 | */ |
---|
586 | 573 | max_len = min_t(unsigned int, ctrl->max_hw_sectors << 9, 256 * 1024); |
---|
| 574 | + |
---|
| 575 | + dev_meta = kmalloc(max_len, GFP_KERNEL); |
---|
| 576 | + if (!dev_meta) |
---|
| 577 | + return -ENOMEM; |
---|
587 | 578 | |
---|
588 | 579 | /* Normalize lba address space to obtain log offset */ |
---|
589 | 580 | ppa.ppa = slba; |
---|
.. | .. |
---|
598 | 589 | while (left) { |
---|
599 | 590 | len = min_t(unsigned int, left, max_len); |
---|
600 | 591 | |
---|
| 592 | + memset(dev_meta, 0, max_len); |
---|
| 593 | + dev_meta_off = dev_meta; |
---|
| 594 | + |
---|
601 | 595 | ret = nvme_get_log(ctrl, ns->head->ns_id, |
---|
602 | | - NVME_NVM_LOG_REPORT_CHUNK, 0, dev_meta, len, |
---|
603 | | - offset); |
---|
| 596 | + NVME_NVM_LOG_REPORT_CHUNK, 0, NVME_CSI_NVM, |
---|
| 597 | + dev_meta, len, offset); |
---|
604 | 598 | if (ret) { |
---|
605 | 599 | dev_err(ctrl->device, "Get REPORT CHUNK log error\n"); |
---|
606 | 600 | break; |
---|
607 | 601 | } |
---|
608 | 602 | |
---|
609 | 603 | for (i = 0; i < len; i += sizeof(struct nvme_nvm_chk_meta)) { |
---|
610 | | - meta->state = dev_meta->state; |
---|
611 | | - meta->type = dev_meta->type; |
---|
612 | | - meta->wi = dev_meta->wi; |
---|
613 | | - meta->slba = le64_to_cpu(dev_meta->slba); |
---|
614 | | - meta->cnlb = le64_to_cpu(dev_meta->cnlb); |
---|
615 | | - meta->wp = le64_to_cpu(dev_meta->wp); |
---|
| 604 | + meta->state = dev_meta_off->state; |
---|
| 605 | + meta->type = dev_meta_off->type; |
---|
| 606 | + meta->wi = dev_meta_off->wi; |
---|
| 607 | + meta->slba = le64_to_cpu(dev_meta_off->slba); |
---|
| 608 | + meta->cnlb = le64_to_cpu(dev_meta_off->cnlb); |
---|
| 609 | + meta->wp = le64_to_cpu(dev_meta_off->wp); |
---|
616 | 610 | |
---|
617 | 611 | meta++; |
---|
618 | | - dev_meta++; |
---|
| 612 | + dev_meta_off++; |
---|
619 | 613 | } |
---|
620 | 614 | |
---|
621 | 615 | offset += len; |
---|
622 | 616 | left -= len; |
---|
623 | 617 | } |
---|
| 618 | + |
---|
| 619 | + kfree(dev_meta); |
---|
624 | 620 | |
---|
625 | 621 | return ret; |
---|
626 | 622 | } |
---|
.. | .. |
---|
657 | 653 | |
---|
658 | 654 | nvme_nvm_rqtocmd(rqd, ns, cmd); |
---|
659 | 655 | |
---|
660 | | - rq = nvme_alloc_request(q, (struct nvme_command *)cmd, 0, NVME_QID_ANY); |
---|
| 656 | + rq = nvme_alloc_request(q, (struct nvme_command *)cmd, 0); |
---|
661 | 657 | if (IS_ERR(rq)) |
---|
662 | 658 | return rq; |
---|
663 | 659 | |
---|
664 | 660 | rq->cmd_flags &= ~REQ_FAILFAST_DRIVER; |
---|
665 | 661 | |
---|
666 | 662 | if (rqd->bio) |
---|
667 | | - blk_init_request_from_bio(rq, rqd->bio); |
---|
| 663 | + blk_rq_append_bio(rq, &rqd->bio); |
---|
668 | 664 | else |
---|
669 | 665 | rq->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); |
---|
670 | 666 | |
---|
671 | 667 | return rq; |
---|
672 | 668 | } |
---|
673 | 669 | |
---|
674 | | -static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) |
---|
| 670 | +static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd, |
---|
| 671 | + void *buf) |
---|
675 | 672 | { |
---|
| 673 | + struct nvm_geo *geo = &dev->geo; |
---|
676 | 674 | struct request_queue *q = dev->q; |
---|
677 | 675 | struct nvme_nvm_command *cmd; |
---|
678 | 676 | struct request *rq; |
---|
| 677 | + int ret; |
---|
679 | 678 | |
---|
680 | 679 | cmd = kzalloc(sizeof(struct nvme_nvm_command), GFP_KERNEL); |
---|
681 | 680 | if (!cmd) |
---|
.. | .. |
---|
683 | 682 | |
---|
684 | 683 | rq = nvme_nvm_alloc_request(q, rqd, cmd); |
---|
685 | 684 | if (IS_ERR(rq)) { |
---|
686 | | - kfree(cmd); |
---|
687 | | - return PTR_ERR(rq); |
---|
| 685 | + ret = PTR_ERR(rq); |
---|
| 686 | + goto err_free_cmd; |
---|
| 687 | + } |
---|
| 688 | + |
---|
| 689 | + if (buf) { |
---|
| 690 | + ret = blk_rq_map_kern(q, rq, buf, geo->csecs * rqd->nr_ppas, |
---|
| 691 | + GFP_KERNEL); |
---|
| 692 | + if (ret) |
---|
| 693 | + goto err_free_cmd; |
---|
688 | 694 | } |
---|
689 | 695 | |
---|
690 | 696 | rq->end_io_data = rqd; |
---|
.. | .. |
---|
692 | 698 | blk_execute_rq_nowait(q, NULL, rq, 0, nvme_nvm_end_io); |
---|
693 | 699 | |
---|
694 | 700 | return 0; |
---|
695 | | -} |
---|
696 | 701 | |
---|
697 | | -static int nvme_nvm_submit_io_sync(struct nvm_dev *dev, struct nvm_rq *rqd) |
---|
698 | | -{ |
---|
699 | | - struct request_queue *q = dev->q; |
---|
700 | | - struct request *rq; |
---|
701 | | - struct nvme_nvm_command cmd; |
---|
702 | | - int ret = 0; |
---|
703 | | - |
---|
704 | | - memset(&cmd, 0, sizeof(struct nvme_nvm_command)); |
---|
705 | | - |
---|
706 | | - rq = nvme_nvm_alloc_request(q, rqd, &cmd); |
---|
707 | | - if (IS_ERR(rq)) |
---|
708 | | - return PTR_ERR(rq); |
---|
709 | | - |
---|
710 | | - /* I/Os can fail and the error is signaled through rqd. Callers must |
---|
711 | | - * handle the error accordingly. |
---|
712 | | - */ |
---|
713 | | - blk_execute_rq(q, NULL, rq, 0); |
---|
714 | | - if (nvme_req(rq)->flags & NVME_REQ_CANCELLED) |
---|
715 | | - ret = -EINTR; |
---|
716 | | - |
---|
717 | | - rqd->ppa_status = le64_to_cpu(nvme_req(rq)->result.u64); |
---|
718 | | - rqd->error = nvme_req(rq)->status; |
---|
719 | | - |
---|
720 | | - blk_mq_free_request(rq); |
---|
721 | | - |
---|
| 702 | +err_free_cmd: |
---|
| 703 | + kfree(cmd); |
---|
722 | 704 | return ret; |
---|
723 | 705 | } |
---|
724 | 706 | |
---|
725 | | -static void *nvme_nvm_create_dma_pool(struct nvm_dev *nvmdev, char *name) |
---|
| 707 | +static void *nvme_nvm_create_dma_pool(struct nvm_dev *nvmdev, char *name, |
---|
| 708 | + int size) |
---|
726 | 709 | { |
---|
727 | 710 | struct nvme_ns *ns = nvmdev->q->queuedata; |
---|
728 | 711 | |
---|
729 | | - return dma_pool_create(name, ns->ctrl->dev, PAGE_SIZE, PAGE_SIZE, 0); |
---|
| 712 | + return dma_pool_create(name, ns->ctrl->dev, size, PAGE_SIZE, 0); |
---|
730 | 713 | } |
---|
731 | 714 | |
---|
732 | 715 | static void nvme_nvm_destroy_dma_pool(void *pool) |
---|
.. | .. |
---|
757 | 740 | .get_chk_meta = nvme_nvm_get_chk_meta, |
---|
758 | 741 | |
---|
759 | 742 | .submit_io = nvme_nvm_submit_io, |
---|
760 | | - .submit_io_sync = nvme_nvm_submit_io_sync, |
---|
761 | 743 | |
---|
762 | 744 | .create_dma_pool = nvme_nvm_create_dma_pool, |
---|
763 | 745 | .destroy_dma_pool = nvme_nvm_destroy_dma_pool, |
---|
.. | .. |
---|
785 | 767 | DECLARE_COMPLETION_ONSTACK(wait); |
---|
786 | 768 | int ret = 0; |
---|
787 | 769 | |
---|
788 | | - rq = nvme_alloc_request(q, (struct nvme_command *)vcmd, 0, |
---|
789 | | - NVME_QID_ANY); |
---|
| 770 | + rq = nvme_alloc_request(q, (struct nvme_command *)vcmd, 0); |
---|
790 | 771 | if (IS_ERR(rq)) { |
---|
791 | 772 | ret = -ENOMEM; |
---|
792 | 773 | goto err_cmd; |
---|
793 | 774 | } |
---|
794 | 775 | |
---|
795 | | - rq->timeout = timeout ? timeout : ADMIN_TIMEOUT; |
---|
| 776 | + if (timeout) |
---|
| 777 | + rq->timeout = timeout; |
---|
796 | 778 | |
---|
797 | 779 | if (ppa_buf && ppa_len) { |
---|
798 | 780 | ppa_list = dma_pool_alloc(dev->dma_pool, GFP_KERNEL, &ppa_dma); |
---|
.. | .. |
---|
926 | 908 | /* cdw11-12 */ |
---|
927 | 909 | c.ph_rw.length = cpu_to_le16(vcmd.nppas); |
---|
928 | 910 | c.ph_rw.control = cpu_to_le16(vcmd.control); |
---|
929 | | - c.common.cdw10[3] = cpu_to_le32(vcmd.cdw13); |
---|
930 | | - c.common.cdw10[4] = cpu_to_le32(vcmd.cdw14); |
---|
931 | | - c.common.cdw10[5] = cpu_to_le32(vcmd.cdw15); |
---|
| 911 | + c.common.cdw13 = cpu_to_le32(vcmd.cdw13); |
---|
| 912 | + c.common.cdw14 = cpu_to_le32(vcmd.cdw14); |
---|
| 913 | + c.common.cdw15 = cpu_to_le32(vcmd.cdw15); |
---|
932 | 914 | |
---|
933 | 915 | if (vcmd.timeout_ms) |
---|
934 | 916 | timeout = msecs_to_jiffies(vcmd.timeout_ms); |
---|
.. | .. |
---|
963 | 945 | } |
---|
964 | 946 | } |
---|
965 | 947 | |
---|
966 | | -void nvme_nvm_update_nvm_info(struct nvme_ns *ns) |
---|
967 | | -{ |
---|
968 | | - struct nvm_dev *ndev = ns->ndev; |
---|
969 | | - struct nvm_geo *geo = &ndev->geo; |
---|
970 | | - |
---|
971 | | - if (geo->version == NVM_OCSSD_SPEC_12) |
---|
972 | | - return; |
---|
973 | | - |
---|
974 | | - geo->csecs = 1 << ns->lba_shift; |
---|
975 | | - geo->sos = ns->ms; |
---|
976 | | -} |
---|
977 | | - |
---|
978 | 948 | int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node) |
---|
979 | 949 | { |
---|
980 | 950 | struct request_queue *q = ns->queue; |
---|
981 | 951 | struct nvm_dev *dev; |
---|
| 952 | + struct nvm_geo *geo; |
---|
982 | 953 | |
---|
983 | 954 | _nvme_nvm_check_size(); |
---|
984 | 955 | |
---|
985 | 956 | dev = nvm_alloc_dev(node); |
---|
986 | 957 | if (!dev) |
---|
987 | 958 | return -ENOMEM; |
---|
| 959 | + |
---|
| 960 | + /* Note that csecs and sos will be overridden if it is a 1.2 drive. */ |
---|
| 961 | + geo = &dev->geo; |
---|
| 962 | + geo->csecs = 1 << ns->lba_shift; |
---|
| 963 | + geo->sos = ns->ms; |
---|
| 964 | + if (ns->features & NVME_NS_EXT_LBAS) |
---|
| 965 | + geo->ext = true; |
---|
| 966 | + else |
---|
| 967 | + geo->ext = false; |
---|
| 968 | + geo->mdts = ns->ctrl->max_hw_sectors; |
---|
988 | 969 | |
---|
989 | 970 | dev->q = q; |
---|
990 | 971 | memcpy(dev->name, disk_name, DISK_NAME_LEN); |
---|
.. | .. |
---|
1193 | 1174 | static NVM_DEV_ATTR_12_RO(media_capabilities); |
---|
1194 | 1175 | static NVM_DEV_ATTR_12_RO(max_phys_secs); |
---|
1195 | 1176 | |
---|
1196 | | -static struct attribute *nvm_dev_attrs_12[] = { |
---|
1197 | | - &dev_attr_version.attr, |
---|
1198 | | - &dev_attr_capabilities.attr, |
---|
1199 | | - |
---|
1200 | | - &dev_attr_vendor_opcode.attr, |
---|
1201 | | - &dev_attr_device_mode.attr, |
---|
1202 | | - &dev_attr_media_manager.attr, |
---|
1203 | | - &dev_attr_ppa_format.attr, |
---|
1204 | | - &dev_attr_media_type.attr, |
---|
1205 | | - &dev_attr_flash_media_type.attr, |
---|
1206 | | - &dev_attr_num_channels.attr, |
---|
1207 | | - &dev_attr_num_luns.attr, |
---|
1208 | | - &dev_attr_num_planes.attr, |
---|
1209 | | - &dev_attr_num_blocks.attr, |
---|
1210 | | - &dev_attr_num_pages.attr, |
---|
1211 | | - &dev_attr_page_size.attr, |
---|
1212 | | - &dev_attr_hw_sector_size.attr, |
---|
1213 | | - &dev_attr_oob_sector_size.attr, |
---|
1214 | | - &dev_attr_read_typ.attr, |
---|
1215 | | - &dev_attr_read_max.attr, |
---|
1216 | | - &dev_attr_prog_typ.attr, |
---|
1217 | | - &dev_attr_prog_max.attr, |
---|
1218 | | - &dev_attr_erase_typ.attr, |
---|
1219 | | - &dev_attr_erase_max.attr, |
---|
1220 | | - &dev_attr_multiplane_modes.attr, |
---|
1221 | | - &dev_attr_media_capabilities.attr, |
---|
1222 | | - &dev_attr_max_phys_secs.attr, |
---|
1223 | | - |
---|
1224 | | - NULL, |
---|
1225 | | -}; |
---|
1226 | | - |
---|
1227 | | -static const struct attribute_group nvm_dev_attr_group_12 = { |
---|
1228 | | - .name = "lightnvm", |
---|
1229 | | - .attrs = nvm_dev_attrs_12, |
---|
1230 | | -}; |
---|
1231 | | - |
---|
1232 | 1177 | /* 2.0 values */ |
---|
1233 | 1178 | static NVM_DEV_ATTR_20_RO(groups); |
---|
1234 | 1179 | static NVM_DEV_ATTR_20_RO(punits); |
---|
.. | .. |
---|
1244 | 1189 | static NVM_DEV_ATTR_20_RO(reset_typ); |
---|
1245 | 1190 | static NVM_DEV_ATTR_20_RO(reset_max); |
---|
1246 | 1191 | |
---|
1247 | | -static struct attribute *nvm_dev_attrs_20[] = { |
---|
| 1192 | +static struct attribute *nvm_dev_attrs[] = { |
---|
| 1193 | + /* version agnostic attrs */ |
---|
1248 | 1194 | &dev_attr_version.attr, |
---|
1249 | 1195 | &dev_attr_capabilities.attr, |
---|
| 1196 | + &dev_attr_read_typ.attr, |
---|
| 1197 | + &dev_attr_read_max.attr, |
---|
1250 | 1198 | |
---|
| 1199 | + /* 1.2 attrs */ |
---|
| 1200 | + &dev_attr_vendor_opcode.attr, |
---|
| 1201 | + &dev_attr_device_mode.attr, |
---|
| 1202 | + &dev_attr_media_manager.attr, |
---|
| 1203 | + &dev_attr_ppa_format.attr, |
---|
| 1204 | + &dev_attr_media_type.attr, |
---|
| 1205 | + &dev_attr_flash_media_type.attr, |
---|
| 1206 | + &dev_attr_num_channels.attr, |
---|
| 1207 | + &dev_attr_num_luns.attr, |
---|
| 1208 | + &dev_attr_num_planes.attr, |
---|
| 1209 | + &dev_attr_num_blocks.attr, |
---|
| 1210 | + &dev_attr_num_pages.attr, |
---|
| 1211 | + &dev_attr_page_size.attr, |
---|
| 1212 | + &dev_attr_hw_sector_size.attr, |
---|
| 1213 | + &dev_attr_oob_sector_size.attr, |
---|
| 1214 | + &dev_attr_prog_typ.attr, |
---|
| 1215 | + &dev_attr_prog_max.attr, |
---|
| 1216 | + &dev_attr_erase_typ.attr, |
---|
| 1217 | + &dev_attr_erase_max.attr, |
---|
| 1218 | + &dev_attr_multiplane_modes.attr, |
---|
| 1219 | + &dev_attr_media_capabilities.attr, |
---|
| 1220 | + &dev_attr_max_phys_secs.attr, |
---|
| 1221 | + |
---|
| 1222 | + /* 2.0 attrs */ |
---|
1251 | 1223 | &dev_attr_groups.attr, |
---|
1252 | 1224 | &dev_attr_punits.attr, |
---|
1253 | 1225 | &dev_attr_chunks.attr, |
---|
.. | .. |
---|
1258 | 1230 | &dev_attr_maxocpu.attr, |
---|
1259 | 1231 | &dev_attr_mw_cunits.attr, |
---|
1260 | 1232 | |
---|
1261 | | - &dev_attr_read_typ.attr, |
---|
1262 | | - &dev_attr_read_max.attr, |
---|
1263 | 1233 | &dev_attr_write_typ.attr, |
---|
1264 | 1234 | &dev_attr_write_max.attr, |
---|
1265 | 1235 | &dev_attr_reset_typ.attr, |
---|
.. | .. |
---|
1268 | 1238 | NULL, |
---|
1269 | 1239 | }; |
---|
1270 | 1240 | |
---|
1271 | | -static const struct attribute_group nvm_dev_attr_group_20 = { |
---|
1272 | | - .name = "lightnvm", |
---|
1273 | | - .attrs = nvm_dev_attrs_20, |
---|
1274 | | -}; |
---|
1275 | | - |
---|
1276 | | -int nvme_nvm_register_sysfs(struct nvme_ns *ns) |
---|
| 1241 | +static umode_t nvm_dev_attrs_visible(struct kobject *kobj, |
---|
| 1242 | + struct attribute *attr, int index) |
---|
1277 | 1243 | { |
---|
| 1244 | + struct device *dev = container_of(kobj, struct device, kobj); |
---|
| 1245 | + struct gendisk *disk = dev_to_disk(dev); |
---|
| 1246 | + struct nvme_ns *ns = disk->private_data; |
---|
1278 | 1247 | struct nvm_dev *ndev = ns->ndev; |
---|
1279 | | - struct nvm_geo *geo = &ndev->geo; |
---|
| 1248 | + struct device_attribute *dev_attr = |
---|
| 1249 | + container_of(attr, typeof(*dev_attr), attr); |
---|
1280 | 1250 | |
---|
1281 | 1251 | if (!ndev) |
---|
1282 | | - return -EINVAL; |
---|
| 1252 | + return 0; |
---|
1283 | 1253 | |
---|
1284 | | - switch (geo->major_ver_id) { |
---|
| 1254 | + if (dev_attr->show == nvm_dev_attr_show) |
---|
| 1255 | + return attr->mode; |
---|
| 1256 | + |
---|
| 1257 | + switch (ndev->geo.major_ver_id) { |
---|
1285 | 1258 | case 1: |
---|
1286 | | - return sysfs_create_group(&disk_to_dev(ns->disk)->kobj, |
---|
1287 | | - &nvm_dev_attr_group_12); |
---|
1288 | | - case 2: |
---|
1289 | | - return sysfs_create_group(&disk_to_dev(ns->disk)->kobj, |
---|
1290 | | - &nvm_dev_attr_group_20); |
---|
1291 | | - } |
---|
1292 | | - |
---|
1293 | | - return -EINVAL; |
---|
1294 | | -} |
---|
1295 | | - |
---|
1296 | | -void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) |
---|
1297 | | -{ |
---|
1298 | | - struct nvm_dev *ndev = ns->ndev; |
---|
1299 | | - struct nvm_geo *geo = &ndev->geo; |
---|
1300 | | - |
---|
1301 | | - switch (geo->major_ver_id) { |
---|
1302 | | - case 1: |
---|
1303 | | - sysfs_remove_group(&disk_to_dev(ns->disk)->kobj, |
---|
1304 | | - &nvm_dev_attr_group_12); |
---|
| 1259 | + if (dev_attr->show == nvm_dev_attr_show_12) |
---|
| 1260 | + return attr->mode; |
---|
1305 | 1261 | break; |
---|
1306 | 1262 | case 2: |
---|
1307 | | - sysfs_remove_group(&disk_to_dev(ns->disk)->kobj, |
---|
1308 | | - &nvm_dev_attr_group_20); |
---|
| 1263 | + if (dev_attr->show == nvm_dev_attr_show_20) |
---|
| 1264 | + return attr->mode; |
---|
1309 | 1265 | break; |
---|
1310 | 1266 | } |
---|
| 1267 | + |
---|
| 1268 | + return 0; |
---|
1311 | 1269 | } |
---|
| 1270 | + |
---|
| 1271 | +const struct attribute_group nvme_nvm_attr_group = { |
---|
| 1272 | + .name = "lightnvm", |
---|
| 1273 | + .attrs = nvm_dev_attrs, |
---|
| 1274 | + .is_visible = nvm_dev_attrs_visible, |
---|
| 1275 | +}; |
---|