1 #include <linux/kernel.h>
2 #include <linux/lightnvm.h>
3 #include <linux/miscdevice.h>
4 #include <linux/kobject.h>
5 #include <linux/blk-mq.h>
9 static ssize_t
nvm_dev_attr_show(struct device
*dev
,
10 struct device_attribute
*dattr
, char *page
)
12 struct nvm_dev
*ndev
= container_of(dev
, struct nvm_dev
, dev
);
13 struct nvm_id
*id
= &ndev
->identity
;
14 struct nvm_id_group
*grp
= &id
->groups
[0];
15 struct attribute
*attr
= &dattr
->attr
;
17 if (strcmp(attr
->name
, "version") == 0) {
18 return scnprintf(page
, PAGE_SIZE
, "%u\n", id
->ver_id
);
19 } else if (strcmp(attr
->name
, "vendor_opcode") == 0) {
20 return scnprintf(page
, PAGE_SIZE
, "%u\n", id
->vmnt
);
21 } else if (strcmp(attr
->name
, "capabilities") == 0) {
22 return scnprintf(page
, PAGE_SIZE
, "%u\n", id
->cap
);
23 } else if (strcmp(attr
->name
, "device_mode") == 0) {
24 return scnprintf(page
, PAGE_SIZE
, "%u\n", id
->dom
);
25 } else if (strcmp(attr
->name
, "media_manager") == 0) {
27 return scnprintf(page
, PAGE_SIZE
, "%s\n", "none");
28 return scnprintf(page
, PAGE_SIZE
, "%s\n", ndev
->mt
->name
);
29 } else if (strcmp(attr
->name
, "ppa_format") == 0) {
30 return scnprintf(page
, PAGE_SIZE
,
31 "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
32 id
->ppaf
.ch_offset
, id
->ppaf
.ch_len
,
33 id
->ppaf
.lun_offset
, id
->ppaf
.lun_len
,
34 id
->ppaf
.pln_offset
, id
->ppaf
.pln_len
,
35 id
->ppaf
.blk_offset
, id
->ppaf
.blk_len
,
36 id
->ppaf
.pg_offset
, id
->ppaf
.pg_len
,
37 id
->ppaf
.sect_offset
, id
->ppaf
.sect_len
);
38 } else if (strcmp(attr
->name
, "media_type") == 0) { /* u8 */
39 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->mtype
);
40 } else if (strcmp(attr
->name
, "flash_media_type") == 0) {
41 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->fmtype
);
42 } else if (strcmp(attr
->name
, "num_channels") == 0) {
43 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->num_ch
);
44 } else if (strcmp(attr
->name
, "num_luns") == 0) {
45 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->num_lun
);
46 } else if (strcmp(attr
->name
, "num_planes") == 0) {
47 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->num_pln
);
48 } else if (strcmp(attr
->name
, "num_blocks") == 0) { /* u16 */
49 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->num_blk
);
50 } else if (strcmp(attr
->name
, "num_pages") == 0) {
51 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->num_pg
);
52 } else if (strcmp(attr
->name
, "page_size") == 0) {
53 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->fpg_sz
);
54 } else if (strcmp(attr
->name
, "hw_sector_size") == 0) {
55 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->csecs
);
56 } else if (strcmp(attr
->name
, "oob_sector_size") == 0) {/* u32 */
57 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->sos
);
58 } else if (strcmp(attr
->name
, "read_typ") == 0) {
59 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->trdt
);
60 } else if (strcmp(attr
->name
, "read_max") == 0) {
61 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->trdm
);
62 } else if (strcmp(attr
->name
, "prog_typ") == 0) {
63 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->tprt
);
64 } else if (strcmp(attr
->name
, "prog_max") == 0) {
65 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->tprm
);
66 } else if (strcmp(attr
->name
, "erase_typ") == 0) {
67 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->tbet
);
68 } else if (strcmp(attr
->name
, "erase_max") == 0) {
69 return scnprintf(page
, PAGE_SIZE
, "%u\n", grp
->tbem
);
70 } else if (strcmp(attr
->name
, "multiplane_modes") == 0) {
71 return scnprintf(page
, PAGE_SIZE
, "0x%08x\n", grp
->mpos
);
72 } else if (strcmp(attr
->name
, "media_capabilities") == 0) {
73 return scnprintf(page
, PAGE_SIZE
, "0x%08x\n", grp
->mccap
);
74 } else if (strcmp(attr
->name
, "max_phys_secs") == 0) {
75 return scnprintf(page
, PAGE_SIZE
, "%u\n",
76 ndev
->ops
->max_phys_sect
);
78 return scnprintf(page
,
80 "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
85 #define NVM_DEV_ATTR_RO(_name) \
86 DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show, NULL)
88 static NVM_DEV_ATTR_RO(version
);
89 static NVM_DEV_ATTR_RO(vendor_opcode
);
90 static NVM_DEV_ATTR_RO(capabilities
);
91 static NVM_DEV_ATTR_RO(device_mode
);
92 static NVM_DEV_ATTR_RO(ppa_format
);
93 static NVM_DEV_ATTR_RO(media_manager
);
95 static NVM_DEV_ATTR_RO(media_type
);
96 static NVM_DEV_ATTR_RO(flash_media_type
);
97 static NVM_DEV_ATTR_RO(num_channels
);
98 static NVM_DEV_ATTR_RO(num_luns
);
99 static NVM_DEV_ATTR_RO(num_planes
);
100 static NVM_DEV_ATTR_RO(num_blocks
);
101 static NVM_DEV_ATTR_RO(num_pages
);
102 static NVM_DEV_ATTR_RO(page_size
);
103 static NVM_DEV_ATTR_RO(hw_sector_size
);
104 static NVM_DEV_ATTR_RO(oob_sector_size
);
105 static NVM_DEV_ATTR_RO(read_typ
);
106 static NVM_DEV_ATTR_RO(read_max
);
107 static NVM_DEV_ATTR_RO(prog_typ
);
108 static NVM_DEV_ATTR_RO(prog_max
);
109 static NVM_DEV_ATTR_RO(erase_typ
);
110 static NVM_DEV_ATTR_RO(erase_max
);
111 static NVM_DEV_ATTR_RO(multiplane_modes
);
112 static NVM_DEV_ATTR_RO(media_capabilities
);
113 static NVM_DEV_ATTR_RO(max_phys_secs
);
115 #define NVM_DEV_ATTR(_name) (dev_attr_##_name##)
117 static struct attribute
*nvm_dev_attrs
[] = {
118 &dev_attr_version
.attr
,
119 &dev_attr_vendor_opcode
.attr
,
120 &dev_attr_capabilities
.attr
,
121 &dev_attr_device_mode
.attr
,
122 &dev_attr_media_manager
.attr
,
124 &dev_attr_ppa_format
.attr
,
125 &dev_attr_media_type
.attr
,
126 &dev_attr_flash_media_type
.attr
,
127 &dev_attr_num_channels
.attr
,
128 &dev_attr_num_luns
.attr
,
129 &dev_attr_num_planes
.attr
,
130 &dev_attr_num_blocks
.attr
,
131 &dev_attr_num_pages
.attr
,
132 &dev_attr_page_size
.attr
,
133 &dev_attr_hw_sector_size
.attr
,
134 &dev_attr_oob_sector_size
.attr
,
135 &dev_attr_read_typ
.attr
,
136 &dev_attr_read_max
.attr
,
137 &dev_attr_prog_typ
.attr
,
138 &dev_attr_prog_max
.attr
,
139 &dev_attr_erase_typ
.attr
,
140 &dev_attr_erase_max
.attr
,
141 &dev_attr_multiplane_modes
.attr
,
142 &dev_attr_media_capabilities
.attr
,
143 &dev_attr_max_phys_secs
.attr
,
147 static struct attribute_group nvm_dev_attr_group
= {
149 .attrs
= nvm_dev_attrs
,
152 static const struct attribute_group
*nvm_dev_attr_groups
[] = {
157 static void nvm_dev_release(struct device
*device
)
159 struct nvm_dev
*dev
= container_of(device
, struct nvm_dev
, dev
);
160 struct request_queue
*q
= dev
->q
;
162 pr_debug("nvm/sysfs: `nvm_dev_release`\n");
164 blk_mq_unregister_dev(device
, q
);
169 static struct device_type nvm_type
= {
171 .groups
= nvm_dev_attr_groups
,
172 .release
= nvm_dev_release
,
175 int nvm_sysfs_register_dev(struct nvm_dev
*dev
)
179 if (!dev
->parent_dev
)
182 dev
->dev
.parent
= dev
->parent_dev
;
183 dev_set_name(&dev
->dev
, "%s", dev
->name
);
184 dev
->dev
.type
= &nvm_type
;
185 device_initialize(&dev
->dev
);
186 ret
= device_add(&dev
->dev
);
189 blk_mq_register_dev(&dev
->dev
, dev
->q
);
194 void nvm_sysfs_unregister_dev(struct nvm_dev
*dev
)
196 if (dev
&& dev
->parent_dev
)
197 kobject_put(&dev
->dev
.kobj
);