Merge tag 'gcc-plugins-v4.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / lightnvm / sysfs.c
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>
6
7 #include "lightnvm.h"
8
9 static ssize_t nvm_dev_attr_show(struct device *dev,
10                                  struct device_attribute *dattr, char *page)
11 {
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;
16
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) {
26                 if (!ndev->mt)
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);
77         } else {
78                 return scnprintf(page,
79                                  PAGE_SIZE,
80                                  "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
81                                  attr->name);
82         }
83 }
84
85 #define NVM_DEV_ATTR_RO(_name)                                          \
86         DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show, NULL)
87
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);
94
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);
114
115 #define NVM_DEV_ATTR(_name) (dev_attr_##_name##)
116
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,
123
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,
144         NULL,
145 };
146
147 static struct attribute_group nvm_dev_attr_group = {
148         .name = "lightnvm",
149         .attrs = nvm_dev_attrs,
150 };
151
152 static const struct attribute_group *nvm_dev_attr_groups[] = {
153         &nvm_dev_attr_group,
154         NULL,
155 };
156
157 static void nvm_dev_release(struct device *device)
158 {
159         struct nvm_dev *dev = container_of(device, struct nvm_dev, dev);
160         struct request_queue *q = dev->q;
161
162         pr_debug("nvm/sysfs: `nvm_dev_release`\n");
163
164         blk_mq_unregister_dev(device, q);
165
166         nvm_free(dev);
167 }
168
169 static struct device_type nvm_type = {
170         .name           = "lightnvm",
171         .groups         = nvm_dev_attr_groups,
172         .release        = nvm_dev_release,
173 };
174
175 int nvm_sysfs_register_dev(struct nvm_dev *dev)
176 {
177         int ret;
178
179         if (!dev->parent_dev)
180                 return 0;
181
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);
187
188         if (!ret)
189                 blk_mq_register_dev(&dev->dev, dev->q);
190
191         return ret;
192 }
193
194 void nvm_sysfs_unregister_dev(struct nvm_dev *dev)
195 {
196         if (dev && dev->parent_dev)
197                 kobject_put(&dev->dev.kobj);
198 }