xref: /openbmc/linux/drivers/nvme/host/sysfs.c (revision b718ae83)
1942e21c0SMax Gurtovoy // SPDX-License-Identifier: GPL-2.0
2942e21c0SMax Gurtovoy /*
3942e21c0SMax Gurtovoy  * Sysfs interface for the NVMe core driver.
4942e21c0SMax Gurtovoy  *
5942e21c0SMax Gurtovoy  * Copyright (c) 2011-2014, Intel Corporation.
6942e21c0SMax Gurtovoy  */
7942e21c0SMax Gurtovoy 
8942e21c0SMax Gurtovoy #include <linux/nvme-auth.h>
9942e21c0SMax Gurtovoy 
10942e21c0SMax Gurtovoy #include "nvme.h"
11942e21c0SMax Gurtovoy #include "fabrics.h"
12942e21c0SMax Gurtovoy 
nvme_sysfs_reset(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)13942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_reset(struct device *dev,
14942e21c0SMax Gurtovoy 				struct device_attribute *attr, const char *buf,
15942e21c0SMax Gurtovoy 				size_t count)
16942e21c0SMax Gurtovoy {
17942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
18942e21c0SMax Gurtovoy 	int ret;
19942e21c0SMax Gurtovoy 
20942e21c0SMax Gurtovoy 	ret = nvme_reset_ctrl_sync(ctrl);
21942e21c0SMax Gurtovoy 	if (ret < 0)
22942e21c0SMax Gurtovoy 		return ret;
23942e21c0SMax Gurtovoy 	return count;
24942e21c0SMax Gurtovoy }
25942e21c0SMax Gurtovoy static DEVICE_ATTR(reset_controller, S_IWUSR, NULL, nvme_sysfs_reset);
26942e21c0SMax Gurtovoy 
nvme_sysfs_rescan(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)27942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_rescan(struct device *dev,
28942e21c0SMax Gurtovoy 				struct device_attribute *attr, const char *buf,
29942e21c0SMax Gurtovoy 				size_t count)
30942e21c0SMax Gurtovoy {
31942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
32942e21c0SMax Gurtovoy 
33942e21c0SMax Gurtovoy 	nvme_queue_scan(ctrl);
34942e21c0SMax Gurtovoy 	return count;
35942e21c0SMax Gurtovoy }
36942e21c0SMax Gurtovoy static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan);
37942e21c0SMax Gurtovoy 
dev_to_ns_head(struct device * dev)38942e21c0SMax Gurtovoy static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev)
39942e21c0SMax Gurtovoy {
40942e21c0SMax Gurtovoy 	struct gendisk *disk = dev_to_disk(dev);
41942e21c0SMax Gurtovoy 
42942e21c0SMax Gurtovoy 	if (disk->fops == &nvme_bdev_ops)
43942e21c0SMax Gurtovoy 		return nvme_get_ns_from_dev(dev)->head;
44942e21c0SMax Gurtovoy 	else
45942e21c0SMax Gurtovoy 		return disk->private_data;
46942e21c0SMax Gurtovoy }
47942e21c0SMax Gurtovoy 
wwid_show(struct device * dev,struct device_attribute * attr,char * buf)48942e21c0SMax Gurtovoy static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
49942e21c0SMax Gurtovoy 		char *buf)
50942e21c0SMax Gurtovoy {
51942e21c0SMax Gurtovoy 	struct nvme_ns_head *head = dev_to_ns_head(dev);
52942e21c0SMax Gurtovoy 	struct nvme_ns_ids *ids = &head->ids;
53942e21c0SMax Gurtovoy 	struct nvme_subsystem *subsys = head->subsys;
54942e21c0SMax Gurtovoy 	int serial_len = sizeof(subsys->serial);
55942e21c0SMax Gurtovoy 	int model_len = sizeof(subsys->model);
56942e21c0SMax Gurtovoy 
57942e21c0SMax Gurtovoy 	if (!uuid_is_null(&ids->uuid))
58942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "uuid.%pU\n", &ids->uuid);
59942e21c0SMax Gurtovoy 
60942e21c0SMax Gurtovoy 	if (memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
61942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "eui.%16phN\n", ids->nguid);
62942e21c0SMax Gurtovoy 
63942e21c0SMax Gurtovoy 	if (memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
64942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "eui.%8phN\n", ids->eui64);
65942e21c0SMax Gurtovoy 
66942e21c0SMax Gurtovoy 	while (serial_len > 0 && (subsys->serial[serial_len - 1] == ' ' ||
67942e21c0SMax Gurtovoy 				  subsys->serial[serial_len - 1] == '\0'))
68942e21c0SMax Gurtovoy 		serial_len--;
69942e21c0SMax Gurtovoy 	while (model_len > 0 && (subsys->model[model_len - 1] == ' ' ||
70942e21c0SMax Gurtovoy 				 subsys->model[model_len - 1] == '\0'))
71942e21c0SMax Gurtovoy 		model_len--;
72942e21c0SMax Gurtovoy 
73942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "nvme.%04x-%*phN-%*phN-%08x\n", subsys->vendor_id,
74942e21c0SMax Gurtovoy 		serial_len, subsys->serial, model_len, subsys->model,
75942e21c0SMax Gurtovoy 		head->ns_id);
76942e21c0SMax Gurtovoy }
77942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(wwid);
78942e21c0SMax Gurtovoy 
nguid_show(struct device * dev,struct device_attribute * attr,char * buf)79942e21c0SMax Gurtovoy static ssize_t nguid_show(struct device *dev, struct device_attribute *attr,
80942e21c0SMax Gurtovoy 		char *buf)
81942e21c0SMax Gurtovoy {
82942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%pU\n", dev_to_ns_head(dev)->ids.nguid);
83942e21c0SMax Gurtovoy }
84942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(nguid);
85942e21c0SMax Gurtovoy 
uuid_show(struct device * dev,struct device_attribute * attr,char * buf)86942e21c0SMax Gurtovoy static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
87942e21c0SMax Gurtovoy 		char *buf)
88942e21c0SMax Gurtovoy {
89942e21c0SMax Gurtovoy 	struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids;
90942e21c0SMax Gurtovoy 
91942e21c0SMax Gurtovoy 	/* For backward compatibility expose the NGUID to userspace if
92942e21c0SMax Gurtovoy 	 * we have no UUID set
93942e21c0SMax Gurtovoy 	 */
94942e21c0SMax Gurtovoy 	if (uuid_is_null(&ids->uuid)) {
95*b718ae83SKeith Busch 		dev_warn_once(dev,
96942e21c0SMax Gurtovoy 			"No UUID available providing old NGUID\n");
97942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "%pU\n", ids->nguid);
98942e21c0SMax Gurtovoy 	}
99942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%pU\n", &ids->uuid);
100942e21c0SMax Gurtovoy }
101942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(uuid);
102942e21c0SMax Gurtovoy 
eui_show(struct device * dev,struct device_attribute * attr,char * buf)103942e21c0SMax Gurtovoy static ssize_t eui_show(struct device *dev, struct device_attribute *attr,
104942e21c0SMax Gurtovoy 		char *buf)
105942e21c0SMax Gurtovoy {
106942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%8ph\n", dev_to_ns_head(dev)->ids.eui64);
107942e21c0SMax Gurtovoy }
108942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(eui);
109942e21c0SMax Gurtovoy 
nsid_show(struct device * dev,struct device_attribute * attr,char * buf)110942e21c0SMax Gurtovoy static ssize_t nsid_show(struct device *dev, struct device_attribute *attr,
111942e21c0SMax Gurtovoy 		char *buf)
112942e21c0SMax Gurtovoy {
113942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%d\n", dev_to_ns_head(dev)->ns_id);
114942e21c0SMax Gurtovoy }
115942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(nsid);
116942e21c0SMax Gurtovoy 
117942e21c0SMax Gurtovoy static struct attribute *nvme_ns_id_attrs[] = {
118942e21c0SMax Gurtovoy 	&dev_attr_wwid.attr,
119942e21c0SMax Gurtovoy 	&dev_attr_uuid.attr,
120942e21c0SMax Gurtovoy 	&dev_attr_nguid.attr,
121942e21c0SMax Gurtovoy 	&dev_attr_eui.attr,
122942e21c0SMax Gurtovoy 	&dev_attr_nsid.attr,
123942e21c0SMax Gurtovoy #ifdef CONFIG_NVME_MULTIPATH
124942e21c0SMax Gurtovoy 	&dev_attr_ana_grpid.attr,
125942e21c0SMax Gurtovoy 	&dev_attr_ana_state.attr,
126942e21c0SMax Gurtovoy #endif
127942e21c0SMax Gurtovoy 	NULL,
128942e21c0SMax Gurtovoy };
129942e21c0SMax Gurtovoy 
nvme_ns_id_attrs_are_visible(struct kobject * kobj,struct attribute * a,int n)130942e21c0SMax Gurtovoy static umode_t nvme_ns_id_attrs_are_visible(struct kobject *kobj,
131942e21c0SMax Gurtovoy 		struct attribute *a, int n)
132942e21c0SMax Gurtovoy {
133942e21c0SMax Gurtovoy 	struct device *dev = container_of(kobj, struct device, kobj);
134942e21c0SMax Gurtovoy 	struct nvme_ns_ids *ids = &dev_to_ns_head(dev)->ids;
135942e21c0SMax Gurtovoy 
136942e21c0SMax Gurtovoy 	if (a == &dev_attr_uuid.attr) {
137942e21c0SMax Gurtovoy 		if (uuid_is_null(&ids->uuid) &&
138942e21c0SMax Gurtovoy 		    !memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
139942e21c0SMax Gurtovoy 			return 0;
140942e21c0SMax Gurtovoy 	}
141942e21c0SMax Gurtovoy 	if (a == &dev_attr_nguid.attr) {
142942e21c0SMax Gurtovoy 		if (!memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
143942e21c0SMax Gurtovoy 			return 0;
144942e21c0SMax Gurtovoy 	}
145942e21c0SMax Gurtovoy 	if (a == &dev_attr_eui.attr) {
146942e21c0SMax Gurtovoy 		if (!memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
147942e21c0SMax Gurtovoy 			return 0;
148942e21c0SMax Gurtovoy 	}
149942e21c0SMax Gurtovoy #ifdef CONFIG_NVME_MULTIPATH
150942e21c0SMax Gurtovoy 	if (a == &dev_attr_ana_grpid.attr || a == &dev_attr_ana_state.attr) {
151942e21c0SMax Gurtovoy 		if (dev_to_disk(dev)->fops != &nvme_bdev_ops) /* per-path attr */
152942e21c0SMax Gurtovoy 			return 0;
153942e21c0SMax Gurtovoy 		if (!nvme_ctrl_use_ana(nvme_get_ns_from_dev(dev)->ctrl))
154942e21c0SMax Gurtovoy 			return 0;
155942e21c0SMax Gurtovoy 	}
156942e21c0SMax Gurtovoy #endif
157942e21c0SMax Gurtovoy 	return a->mode;
158942e21c0SMax Gurtovoy }
159942e21c0SMax Gurtovoy 
160942e21c0SMax Gurtovoy static const struct attribute_group nvme_ns_id_attr_group = {
161942e21c0SMax Gurtovoy 	.attrs		= nvme_ns_id_attrs,
162942e21c0SMax Gurtovoy 	.is_visible	= nvme_ns_id_attrs_are_visible,
163942e21c0SMax Gurtovoy };
164942e21c0SMax Gurtovoy 
165942e21c0SMax Gurtovoy const struct attribute_group *nvme_ns_id_attr_groups[] = {
166942e21c0SMax Gurtovoy 	&nvme_ns_id_attr_group,
167942e21c0SMax Gurtovoy 	NULL,
168942e21c0SMax Gurtovoy };
169942e21c0SMax Gurtovoy 
170942e21c0SMax Gurtovoy #define nvme_show_str_function(field)						\
171942e21c0SMax Gurtovoy static ssize_t  field##_show(struct device *dev,				\
172942e21c0SMax Gurtovoy 			    struct device_attribute *attr, char *buf)		\
173942e21c0SMax Gurtovoy {										\
174942e21c0SMax Gurtovoy         struct nvme_ctrl *ctrl = dev_get_drvdata(dev);				\
175942e21c0SMax Gurtovoy         return sysfs_emit(buf, "%.*s\n",					\
176942e21c0SMax Gurtovoy 		(int)sizeof(ctrl->subsys->field), ctrl->subsys->field);		\
177942e21c0SMax Gurtovoy }										\
178942e21c0SMax Gurtovoy static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
179942e21c0SMax Gurtovoy 
180942e21c0SMax Gurtovoy nvme_show_str_function(model);
181942e21c0SMax Gurtovoy nvme_show_str_function(serial);
182942e21c0SMax Gurtovoy nvme_show_str_function(firmware_rev);
183942e21c0SMax Gurtovoy 
184942e21c0SMax Gurtovoy #define nvme_show_int_function(field)						\
185942e21c0SMax Gurtovoy static ssize_t  field##_show(struct device *dev,				\
186942e21c0SMax Gurtovoy 			    struct device_attribute *attr, char *buf)		\
187942e21c0SMax Gurtovoy {										\
188942e21c0SMax Gurtovoy         struct nvme_ctrl *ctrl = dev_get_drvdata(dev);				\
189942e21c0SMax Gurtovoy         return sysfs_emit(buf, "%d\n", ctrl->field);				\
190942e21c0SMax Gurtovoy }										\
191942e21c0SMax Gurtovoy static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
192942e21c0SMax Gurtovoy 
193942e21c0SMax Gurtovoy nvme_show_int_function(cntlid);
194942e21c0SMax Gurtovoy nvme_show_int_function(numa_node);
195942e21c0SMax Gurtovoy nvme_show_int_function(queue_count);
196942e21c0SMax Gurtovoy nvme_show_int_function(sqsize);
197942e21c0SMax Gurtovoy nvme_show_int_function(kato);
198942e21c0SMax Gurtovoy 
nvme_sysfs_delete(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)199942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_delete(struct device *dev,
200942e21c0SMax Gurtovoy 				struct device_attribute *attr, const char *buf,
201942e21c0SMax Gurtovoy 				size_t count)
202942e21c0SMax Gurtovoy {
203942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
204942e21c0SMax Gurtovoy 
2051c606f7fSKeith Busch 	if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags))
2061c606f7fSKeith Busch 		return -EBUSY;
2071c606f7fSKeith Busch 
208942e21c0SMax Gurtovoy 	if (device_remove_file_self(dev, attr))
209942e21c0SMax Gurtovoy 		nvme_delete_ctrl_sync(ctrl);
210942e21c0SMax Gurtovoy 	return count;
211942e21c0SMax Gurtovoy }
212942e21c0SMax Gurtovoy static DEVICE_ATTR(delete_controller, S_IWUSR, NULL, nvme_sysfs_delete);
213942e21c0SMax Gurtovoy 
nvme_sysfs_show_transport(struct device * dev,struct device_attribute * attr,char * buf)214942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_show_transport(struct device *dev,
215942e21c0SMax Gurtovoy 					 struct device_attribute *attr,
216942e21c0SMax Gurtovoy 					 char *buf)
217942e21c0SMax Gurtovoy {
218942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
219942e21c0SMax Gurtovoy 
220942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%s\n", ctrl->ops->name);
221942e21c0SMax Gurtovoy }
222942e21c0SMax Gurtovoy static DEVICE_ATTR(transport, S_IRUGO, nvme_sysfs_show_transport, NULL);
223942e21c0SMax Gurtovoy 
nvme_sysfs_show_state(struct device * dev,struct device_attribute * attr,char * buf)224942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_show_state(struct device *dev,
225942e21c0SMax Gurtovoy 				     struct device_attribute *attr,
226942e21c0SMax Gurtovoy 				     char *buf)
227942e21c0SMax Gurtovoy {
228942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
229942e21c0SMax Gurtovoy 	static const char *const state_name[] = {
230942e21c0SMax Gurtovoy 		[NVME_CTRL_NEW]		= "new",
231942e21c0SMax Gurtovoy 		[NVME_CTRL_LIVE]	= "live",
232942e21c0SMax Gurtovoy 		[NVME_CTRL_RESETTING]	= "resetting",
233942e21c0SMax Gurtovoy 		[NVME_CTRL_CONNECTING]	= "connecting",
234942e21c0SMax Gurtovoy 		[NVME_CTRL_DELETING]	= "deleting",
235942e21c0SMax Gurtovoy 		[NVME_CTRL_DELETING_NOIO]= "deleting (no IO)",
236942e21c0SMax Gurtovoy 		[NVME_CTRL_DEAD]	= "dead",
237942e21c0SMax Gurtovoy 	};
238942e21c0SMax Gurtovoy 
239942e21c0SMax Gurtovoy 	if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) &&
240942e21c0SMax Gurtovoy 	    state_name[ctrl->state])
241942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "%s\n", state_name[ctrl->state]);
242942e21c0SMax Gurtovoy 
243942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "unknown state\n");
244942e21c0SMax Gurtovoy }
245942e21c0SMax Gurtovoy 
246942e21c0SMax Gurtovoy static DEVICE_ATTR(state, S_IRUGO, nvme_sysfs_show_state, NULL);
247942e21c0SMax Gurtovoy 
nvme_sysfs_show_subsysnqn(struct device * dev,struct device_attribute * attr,char * buf)248942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev,
249942e21c0SMax Gurtovoy 					 struct device_attribute *attr,
250942e21c0SMax Gurtovoy 					 char *buf)
251942e21c0SMax Gurtovoy {
252942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
253942e21c0SMax Gurtovoy 
254942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%s\n", ctrl->subsys->subnqn);
255942e21c0SMax Gurtovoy }
256942e21c0SMax Gurtovoy static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL);
257942e21c0SMax Gurtovoy 
nvme_sysfs_show_hostnqn(struct device * dev,struct device_attribute * attr,char * buf)258942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_show_hostnqn(struct device *dev,
259942e21c0SMax Gurtovoy 					struct device_attribute *attr,
260942e21c0SMax Gurtovoy 					char *buf)
261942e21c0SMax Gurtovoy {
262942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
263942e21c0SMax Gurtovoy 
264942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%s\n", ctrl->opts->host->nqn);
265942e21c0SMax Gurtovoy }
266942e21c0SMax Gurtovoy static DEVICE_ATTR(hostnqn, S_IRUGO, nvme_sysfs_show_hostnqn, NULL);
267942e21c0SMax Gurtovoy 
nvme_sysfs_show_hostid(struct device * dev,struct device_attribute * attr,char * buf)268942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_show_hostid(struct device *dev,
269942e21c0SMax Gurtovoy 					struct device_attribute *attr,
270942e21c0SMax Gurtovoy 					char *buf)
271942e21c0SMax Gurtovoy {
272942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
273942e21c0SMax Gurtovoy 
274942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%pU\n", &ctrl->opts->host->id);
275942e21c0SMax Gurtovoy }
276942e21c0SMax Gurtovoy static DEVICE_ATTR(hostid, S_IRUGO, nvme_sysfs_show_hostid, NULL);
277942e21c0SMax Gurtovoy 
nvme_sysfs_show_address(struct device * dev,struct device_attribute * attr,char * buf)278942e21c0SMax Gurtovoy static ssize_t nvme_sysfs_show_address(struct device *dev,
279942e21c0SMax Gurtovoy 					 struct device_attribute *attr,
280942e21c0SMax Gurtovoy 					 char *buf)
281942e21c0SMax Gurtovoy {
282942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
283942e21c0SMax Gurtovoy 
284942e21c0SMax Gurtovoy 	return ctrl->ops->get_address(ctrl, buf, PAGE_SIZE);
285942e21c0SMax Gurtovoy }
286942e21c0SMax Gurtovoy static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL);
287942e21c0SMax Gurtovoy 
nvme_ctrl_loss_tmo_show(struct device * dev,struct device_attribute * attr,char * buf)288942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_loss_tmo_show(struct device *dev,
289942e21c0SMax Gurtovoy 		struct device_attribute *attr, char *buf)
290942e21c0SMax Gurtovoy {
291942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
292942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
293942e21c0SMax Gurtovoy 
294942e21c0SMax Gurtovoy 	if (ctrl->opts->max_reconnects == -1)
295942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "off\n");
296942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%d\n",
297942e21c0SMax Gurtovoy 			  opts->max_reconnects * opts->reconnect_delay);
298942e21c0SMax Gurtovoy }
299942e21c0SMax Gurtovoy 
nvme_ctrl_loss_tmo_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)300942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_loss_tmo_store(struct device *dev,
301942e21c0SMax Gurtovoy 		struct device_attribute *attr, const char *buf, size_t count)
302942e21c0SMax Gurtovoy {
303942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
304942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
305942e21c0SMax Gurtovoy 	int ctrl_loss_tmo, err;
306942e21c0SMax Gurtovoy 
307942e21c0SMax Gurtovoy 	err = kstrtoint(buf, 10, &ctrl_loss_tmo);
308942e21c0SMax Gurtovoy 	if (err)
309942e21c0SMax Gurtovoy 		return -EINVAL;
310942e21c0SMax Gurtovoy 
311942e21c0SMax Gurtovoy 	if (ctrl_loss_tmo < 0)
312942e21c0SMax Gurtovoy 		opts->max_reconnects = -1;
313942e21c0SMax Gurtovoy 	else
314942e21c0SMax Gurtovoy 		opts->max_reconnects = DIV_ROUND_UP(ctrl_loss_tmo,
315942e21c0SMax Gurtovoy 						opts->reconnect_delay);
316942e21c0SMax Gurtovoy 	return count;
317942e21c0SMax Gurtovoy }
318942e21c0SMax Gurtovoy static DEVICE_ATTR(ctrl_loss_tmo, S_IRUGO | S_IWUSR,
319942e21c0SMax Gurtovoy 	nvme_ctrl_loss_tmo_show, nvme_ctrl_loss_tmo_store);
320942e21c0SMax Gurtovoy 
nvme_ctrl_reconnect_delay_show(struct device * dev,struct device_attribute * attr,char * buf)321942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_reconnect_delay_show(struct device *dev,
322942e21c0SMax Gurtovoy 		struct device_attribute *attr, char *buf)
323942e21c0SMax Gurtovoy {
324942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
325942e21c0SMax Gurtovoy 
326942e21c0SMax Gurtovoy 	if (ctrl->opts->reconnect_delay == -1)
327942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "off\n");
328942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%d\n", ctrl->opts->reconnect_delay);
329942e21c0SMax Gurtovoy }
330942e21c0SMax Gurtovoy 
nvme_ctrl_reconnect_delay_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)331942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_reconnect_delay_store(struct device *dev,
332942e21c0SMax Gurtovoy 		struct device_attribute *attr, const char *buf, size_t count)
333942e21c0SMax Gurtovoy {
334942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
335942e21c0SMax Gurtovoy 	unsigned int v;
336942e21c0SMax Gurtovoy 	int err;
337942e21c0SMax Gurtovoy 
338942e21c0SMax Gurtovoy 	err = kstrtou32(buf, 10, &v);
339942e21c0SMax Gurtovoy 	if (err)
340942e21c0SMax Gurtovoy 		return err;
341942e21c0SMax Gurtovoy 
342942e21c0SMax Gurtovoy 	ctrl->opts->reconnect_delay = v;
343942e21c0SMax Gurtovoy 	return count;
344942e21c0SMax Gurtovoy }
345942e21c0SMax Gurtovoy static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR,
346942e21c0SMax Gurtovoy 	nvme_ctrl_reconnect_delay_show, nvme_ctrl_reconnect_delay_store);
347942e21c0SMax Gurtovoy 
nvme_ctrl_fast_io_fail_tmo_show(struct device * dev,struct device_attribute * attr,char * buf)348942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_fast_io_fail_tmo_show(struct device *dev,
349942e21c0SMax Gurtovoy 		struct device_attribute *attr, char *buf)
350942e21c0SMax Gurtovoy {
351942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
352942e21c0SMax Gurtovoy 
353942e21c0SMax Gurtovoy 	if (ctrl->opts->fast_io_fail_tmo == -1)
354942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "off\n");
355942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%d\n", ctrl->opts->fast_io_fail_tmo);
356942e21c0SMax Gurtovoy }
357942e21c0SMax Gurtovoy 
nvme_ctrl_fast_io_fail_tmo_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)358942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_fast_io_fail_tmo_store(struct device *dev,
359942e21c0SMax Gurtovoy 		struct device_attribute *attr, const char *buf, size_t count)
360942e21c0SMax Gurtovoy {
361942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
362942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
363942e21c0SMax Gurtovoy 	int fast_io_fail_tmo, err;
364942e21c0SMax Gurtovoy 
365942e21c0SMax Gurtovoy 	err = kstrtoint(buf, 10, &fast_io_fail_tmo);
366942e21c0SMax Gurtovoy 	if (err)
367942e21c0SMax Gurtovoy 		return -EINVAL;
368942e21c0SMax Gurtovoy 
369942e21c0SMax Gurtovoy 	if (fast_io_fail_tmo < 0)
370942e21c0SMax Gurtovoy 		opts->fast_io_fail_tmo = -1;
371942e21c0SMax Gurtovoy 	else
372942e21c0SMax Gurtovoy 		opts->fast_io_fail_tmo = fast_io_fail_tmo;
373942e21c0SMax Gurtovoy 	return count;
374942e21c0SMax Gurtovoy }
375942e21c0SMax Gurtovoy static DEVICE_ATTR(fast_io_fail_tmo, S_IRUGO | S_IWUSR,
376942e21c0SMax Gurtovoy 	nvme_ctrl_fast_io_fail_tmo_show, nvme_ctrl_fast_io_fail_tmo_store);
377942e21c0SMax Gurtovoy 
cntrltype_show(struct device * dev,struct device_attribute * attr,char * buf)378942e21c0SMax Gurtovoy static ssize_t cntrltype_show(struct device *dev,
379942e21c0SMax Gurtovoy 			      struct device_attribute *attr, char *buf)
380942e21c0SMax Gurtovoy {
381942e21c0SMax Gurtovoy 	static const char * const type[] = {
382942e21c0SMax Gurtovoy 		[NVME_CTRL_IO] = "io\n",
383942e21c0SMax Gurtovoy 		[NVME_CTRL_DISC] = "discovery\n",
384942e21c0SMax Gurtovoy 		[NVME_CTRL_ADMIN] = "admin\n",
385942e21c0SMax Gurtovoy 	};
386942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
387942e21c0SMax Gurtovoy 
388942e21c0SMax Gurtovoy 	if (ctrl->cntrltype > NVME_CTRL_ADMIN || !type[ctrl->cntrltype])
389942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "reserved\n");
390942e21c0SMax Gurtovoy 
391942e21c0SMax Gurtovoy 	return sysfs_emit(buf, type[ctrl->cntrltype]);
392942e21c0SMax Gurtovoy }
393942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(cntrltype);
394942e21c0SMax Gurtovoy 
dctype_show(struct device * dev,struct device_attribute * attr,char * buf)395942e21c0SMax Gurtovoy static ssize_t dctype_show(struct device *dev,
396942e21c0SMax Gurtovoy 			   struct device_attribute *attr, char *buf)
397942e21c0SMax Gurtovoy {
398942e21c0SMax Gurtovoy 	static const char * const type[] = {
399942e21c0SMax Gurtovoy 		[NVME_DCTYPE_NOT_REPORTED] = "none\n",
400942e21c0SMax Gurtovoy 		[NVME_DCTYPE_DDC] = "ddc\n",
401942e21c0SMax Gurtovoy 		[NVME_DCTYPE_CDC] = "cdc\n",
402942e21c0SMax Gurtovoy 	};
403942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
404942e21c0SMax Gurtovoy 
405942e21c0SMax Gurtovoy 	if (ctrl->dctype > NVME_DCTYPE_CDC || !type[ctrl->dctype])
406942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "reserved\n");
407942e21c0SMax Gurtovoy 
408942e21c0SMax Gurtovoy 	return sysfs_emit(buf, type[ctrl->dctype]);
409942e21c0SMax Gurtovoy }
410942e21c0SMax Gurtovoy static DEVICE_ATTR_RO(dctype);
411942e21c0SMax Gurtovoy 
412942e21c0SMax Gurtovoy #ifdef CONFIG_NVME_AUTH
nvme_ctrl_dhchap_secret_show(struct device * dev,struct device_attribute * attr,char * buf)413942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev,
414942e21c0SMax Gurtovoy 		struct device_attribute *attr, char *buf)
415942e21c0SMax Gurtovoy {
416942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
417942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
418942e21c0SMax Gurtovoy 
419942e21c0SMax Gurtovoy 	if (!opts->dhchap_secret)
420942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "none\n");
421942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%s\n", opts->dhchap_secret);
422942e21c0SMax Gurtovoy }
423942e21c0SMax Gurtovoy 
nvme_ctrl_dhchap_secret_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)424942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
425942e21c0SMax Gurtovoy 		struct device_attribute *attr, const char *buf, size_t count)
426942e21c0SMax Gurtovoy {
427942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
428942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
429942e21c0SMax Gurtovoy 	char *dhchap_secret;
430942e21c0SMax Gurtovoy 
431942e21c0SMax Gurtovoy 	if (!ctrl->opts->dhchap_secret)
432942e21c0SMax Gurtovoy 		return -EINVAL;
433942e21c0SMax Gurtovoy 	if (count < 7)
434942e21c0SMax Gurtovoy 		return -EINVAL;
435942e21c0SMax Gurtovoy 	if (memcmp(buf, "DHHC-1:", 7))
436942e21c0SMax Gurtovoy 		return -EINVAL;
437942e21c0SMax Gurtovoy 
438942e21c0SMax Gurtovoy 	dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
439942e21c0SMax Gurtovoy 	if (!dhchap_secret)
440942e21c0SMax Gurtovoy 		return -ENOMEM;
441942e21c0SMax Gurtovoy 	memcpy(dhchap_secret, buf, count);
442942e21c0SMax Gurtovoy 	nvme_auth_stop(ctrl);
443942e21c0SMax Gurtovoy 	if (strcmp(dhchap_secret, opts->dhchap_secret)) {
444942e21c0SMax Gurtovoy 		struct nvme_dhchap_key *key, *host_key;
445942e21c0SMax Gurtovoy 		int ret;
446942e21c0SMax Gurtovoy 
447942e21c0SMax Gurtovoy 		ret = nvme_auth_generate_key(dhchap_secret, &key);
448942e21c0SMax Gurtovoy 		if (ret) {
449942e21c0SMax Gurtovoy 			kfree(dhchap_secret);
450942e21c0SMax Gurtovoy 			return ret;
451942e21c0SMax Gurtovoy 		}
452942e21c0SMax Gurtovoy 		kfree(opts->dhchap_secret);
453942e21c0SMax Gurtovoy 		opts->dhchap_secret = dhchap_secret;
454942e21c0SMax Gurtovoy 		host_key = ctrl->host_key;
455942e21c0SMax Gurtovoy 		mutex_lock(&ctrl->dhchap_auth_mutex);
456942e21c0SMax Gurtovoy 		ctrl->host_key = key;
457942e21c0SMax Gurtovoy 		mutex_unlock(&ctrl->dhchap_auth_mutex);
458942e21c0SMax Gurtovoy 		nvme_auth_free_key(host_key);
459942e21c0SMax Gurtovoy 	} else
460942e21c0SMax Gurtovoy 		kfree(dhchap_secret);
461942e21c0SMax Gurtovoy 	/* Start re-authentication */
462942e21c0SMax Gurtovoy 	dev_info(ctrl->device, "re-authenticating controller\n");
463942e21c0SMax Gurtovoy 	queue_work(nvme_wq, &ctrl->dhchap_auth_work);
464942e21c0SMax Gurtovoy 
465942e21c0SMax Gurtovoy 	return count;
466942e21c0SMax Gurtovoy }
467942e21c0SMax Gurtovoy 
468942e21c0SMax Gurtovoy static DEVICE_ATTR(dhchap_secret, S_IRUGO | S_IWUSR,
469942e21c0SMax Gurtovoy 	nvme_ctrl_dhchap_secret_show, nvme_ctrl_dhchap_secret_store);
470942e21c0SMax Gurtovoy 
nvme_ctrl_dhchap_ctrl_secret_show(struct device * dev,struct device_attribute * attr,char * buf)471942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_dhchap_ctrl_secret_show(struct device *dev,
472942e21c0SMax Gurtovoy 		struct device_attribute *attr, char *buf)
473942e21c0SMax Gurtovoy {
474942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
475942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
476942e21c0SMax Gurtovoy 
477942e21c0SMax Gurtovoy 	if (!opts->dhchap_ctrl_secret)
478942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "none\n");
479942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%s\n", opts->dhchap_ctrl_secret);
480942e21c0SMax Gurtovoy }
481942e21c0SMax Gurtovoy 
nvme_ctrl_dhchap_ctrl_secret_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)482942e21c0SMax Gurtovoy static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev,
483942e21c0SMax Gurtovoy 		struct device_attribute *attr, const char *buf, size_t count)
484942e21c0SMax Gurtovoy {
485942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
486942e21c0SMax Gurtovoy 	struct nvmf_ctrl_options *opts = ctrl->opts;
487942e21c0SMax Gurtovoy 	char *dhchap_secret;
488942e21c0SMax Gurtovoy 
489942e21c0SMax Gurtovoy 	if (!ctrl->opts->dhchap_ctrl_secret)
490942e21c0SMax Gurtovoy 		return -EINVAL;
491942e21c0SMax Gurtovoy 	if (count < 7)
492942e21c0SMax Gurtovoy 		return -EINVAL;
493942e21c0SMax Gurtovoy 	if (memcmp(buf, "DHHC-1:", 7))
494942e21c0SMax Gurtovoy 		return -EINVAL;
495942e21c0SMax Gurtovoy 
496942e21c0SMax Gurtovoy 	dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
497942e21c0SMax Gurtovoy 	if (!dhchap_secret)
498942e21c0SMax Gurtovoy 		return -ENOMEM;
499942e21c0SMax Gurtovoy 	memcpy(dhchap_secret, buf, count);
500942e21c0SMax Gurtovoy 	nvme_auth_stop(ctrl);
501942e21c0SMax Gurtovoy 	if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) {
502942e21c0SMax Gurtovoy 		struct nvme_dhchap_key *key, *ctrl_key;
503942e21c0SMax Gurtovoy 		int ret;
504942e21c0SMax Gurtovoy 
505942e21c0SMax Gurtovoy 		ret = nvme_auth_generate_key(dhchap_secret, &key);
506942e21c0SMax Gurtovoy 		if (ret) {
507942e21c0SMax Gurtovoy 			kfree(dhchap_secret);
508942e21c0SMax Gurtovoy 			return ret;
509942e21c0SMax Gurtovoy 		}
510942e21c0SMax Gurtovoy 		kfree(opts->dhchap_ctrl_secret);
511942e21c0SMax Gurtovoy 		opts->dhchap_ctrl_secret = dhchap_secret;
512942e21c0SMax Gurtovoy 		ctrl_key = ctrl->ctrl_key;
513942e21c0SMax Gurtovoy 		mutex_lock(&ctrl->dhchap_auth_mutex);
514942e21c0SMax Gurtovoy 		ctrl->ctrl_key = key;
515942e21c0SMax Gurtovoy 		mutex_unlock(&ctrl->dhchap_auth_mutex);
516942e21c0SMax Gurtovoy 		nvme_auth_free_key(ctrl_key);
517942e21c0SMax Gurtovoy 	} else
518942e21c0SMax Gurtovoy 		kfree(dhchap_secret);
519942e21c0SMax Gurtovoy 	/* Start re-authentication */
520942e21c0SMax Gurtovoy 	dev_info(ctrl->device, "re-authenticating controller\n");
521942e21c0SMax Gurtovoy 	queue_work(nvme_wq, &ctrl->dhchap_auth_work);
522942e21c0SMax Gurtovoy 
523942e21c0SMax Gurtovoy 	return count;
524942e21c0SMax Gurtovoy }
525942e21c0SMax Gurtovoy 
526942e21c0SMax Gurtovoy static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR,
527942e21c0SMax Gurtovoy 	nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store);
528942e21c0SMax Gurtovoy #endif
529942e21c0SMax Gurtovoy 
530942e21c0SMax Gurtovoy static struct attribute *nvme_dev_attrs[] = {
531942e21c0SMax Gurtovoy 	&dev_attr_reset_controller.attr,
532942e21c0SMax Gurtovoy 	&dev_attr_rescan_controller.attr,
533942e21c0SMax Gurtovoy 	&dev_attr_model.attr,
534942e21c0SMax Gurtovoy 	&dev_attr_serial.attr,
535942e21c0SMax Gurtovoy 	&dev_attr_firmware_rev.attr,
536942e21c0SMax Gurtovoy 	&dev_attr_cntlid.attr,
537942e21c0SMax Gurtovoy 	&dev_attr_delete_controller.attr,
538942e21c0SMax Gurtovoy 	&dev_attr_transport.attr,
539942e21c0SMax Gurtovoy 	&dev_attr_subsysnqn.attr,
540942e21c0SMax Gurtovoy 	&dev_attr_address.attr,
541942e21c0SMax Gurtovoy 	&dev_attr_state.attr,
542942e21c0SMax Gurtovoy 	&dev_attr_numa_node.attr,
543942e21c0SMax Gurtovoy 	&dev_attr_queue_count.attr,
544942e21c0SMax Gurtovoy 	&dev_attr_sqsize.attr,
545942e21c0SMax Gurtovoy 	&dev_attr_hostnqn.attr,
546942e21c0SMax Gurtovoy 	&dev_attr_hostid.attr,
547942e21c0SMax Gurtovoy 	&dev_attr_ctrl_loss_tmo.attr,
548942e21c0SMax Gurtovoy 	&dev_attr_reconnect_delay.attr,
549942e21c0SMax Gurtovoy 	&dev_attr_fast_io_fail_tmo.attr,
550942e21c0SMax Gurtovoy 	&dev_attr_kato.attr,
551942e21c0SMax Gurtovoy 	&dev_attr_cntrltype.attr,
552942e21c0SMax Gurtovoy 	&dev_attr_dctype.attr,
553942e21c0SMax Gurtovoy #ifdef CONFIG_NVME_AUTH
554942e21c0SMax Gurtovoy 	&dev_attr_dhchap_secret.attr,
555942e21c0SMax Gurtovoy 	&dev_attr_dhchap_ctrl_secret.attr,
556942e21c0SMax Gurtovoy #endif
557942e21c0SMax Gurtovoy 	NULL
558942e21c0SMax Gurtovoy };
559942e21c0SMax Gurtovoy 
nvme_dev_attrs_are_visible(struct kobject * kobj,struct attribute * a,int n)560942e21c0SMax Gurtovoy static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
561942e21c0SMax Gurtovoy 		struct attribute *a, int n)
562942e21c0SMax Gurtovoy {
563942e21c0SMax Gurtovoy 	struct device *dev = container_of(kobj, struct device, kobj);
564942e21c0SMax Gurtovoy 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
565942e21c0SMax Gurtovoy 
566942e21c0SMax Gurtovoy 	if (a == &dev_attr_delete_controller.attr && !ctrl->ops->delete_ctrl)
567942e21c0SMax Gurtovoy 		return 0;
568942e21c0SMax Gurtovoy 	if (a == &dev_attr_address.attr && !ctrl->ops->get_address)
569942e21c0SMax Gurtovoy 		return 0;
570942e21c0SMax Gurtovoy 	if (a == &dev_attr_hostnqn.attr && !ctrl->opts)
571942e21c0SMax Gurtovoy 		return 0;
572942e21c0SMax Gurtovoy 	if (a == &dev_attr_hostid.attr && !ctrl->opts)
573942e21c0SMax Gurtovoy 		return 0;
574942e21c0SMax Gurtovoy 	if (a == &dev_attr_ctrl_loss_tmo.attr && !ctrl->opts)
575942e21c0SMax Gurtovoy 		return 0;
576942e21c0SMax Gurtovoy 	if (a == &dev_attr_reconnect_delay.attr && !ctrl->opts)
577942e21c0SMax Gurtovoy 		return 0;
578942e21c0SMax Gurtovoy 	if (a == &dev_attr_fast_io_fail_tmo.attr && !ctrl->opts)
579942e21c0SMax Gurtovoy 		return 0;
580942e21c0SMax Gurtovoy #ifdef CONFIG_NVME_AUTH
581942e21c0SMax Gurtovoy 	if (a == &dev_attr_dhchap_secret.attr && !ctrl->opts)
582942e21c0SMax Gurtovoy 		return 0;
583942e21c0SMax Gurtovoy 	if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts)
584942e21c0SMax Gurtovoy 		return 0;
585942e21c0SMax Gurtovoy #endif
586942e21c0SMax Gurtovoy 
587942e21c0SMax Gurtovoy 	return a->mode;
588942e21c0SMax Gurtovoy }
589942e21c0SMax Gurtovoy 
590942e21c0SMax Gurtovoy const struct attribute_group nvme_dev_attrs_group = {
591942e21c0SMax Gurtovoy 	.attrs		= nvme_dev_attrs,
592942e21c0SMax Gurtovoy 	.is_visible	= nvme_dev_attrs_are_visible,
593942e21c0SMax Gurtovoy };
594942e21c0SMax Gurtovoy EXPORT_SYMBOL_GPL(nvme_dev_attrs_group);
595942e21c0SMax Gurtovoy 
596942e21c0SMax Gurtovoy const struct attribute_group *nvme_dev_attr_groups[] = {
597942e21c0SMax Gurtovoy 	&nvme_dev_attrs_group,
598942e21c0SMax Gurtovoy 	NULL,
599942e21c0SMax Gurtovoy };
600942e21c0SMax Gurtovoy 
601942e21c0SMax Gurtovoy #define SUBSYS_ATTR_RO(_name, _mode, _show)			\
602942e21c0SMax Gurtovoy 	struct device_attribute subsys_attr_##_name = \
603942e21c0SMax Gurtovoy 		__ATTR(_name, _mode, _show, NULL)
604942e21c0SMax Gurtovoy 
nvme_subsys_show_nqn(struct device * dev,struct device_attribute * attr,char * buf)605942e21c0SMax Gurtovoy static ssize_t nvme_subsys_show_nqn(struct device *dev,
606942e21c0SMax Gurtovoy 				    struct device_attribute *attr,
607942e21c0SMax Gurtovoy 				    char *buf)
608942e21c0SMax Gurtovoy {
609942e21c0SMax Gurtovoy 	struct nvme_subsystem *subsys =
610942e21c0SMax Gurtovoy 		container_of(dev, struct nvme_subsystem, dev);
611942e21c0SMax Gurtovoy 
612942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%s\n", subsys->subnqn);
613942e21c0SMax Gurtovoy }
614942e21c0SMax Gurtovoy static SUBSYS_ATTR_RO(subsysnqn, S_IRUGO, nvme_subsys_show_nqn);
615942e21c0SMax Gurtovoy 
nvme_subsys_show_type(struct device * dev,struct device_attribute * attr,char * buf)616942e21c0SMax Gurtovoy static ssize_t nvme_subsys_show_type(struct device *dev,
617942e21c0SMax Gurtovoy 				    struct device_attribute *attr,
618942e21c0SMax Gurtovoy 				    char *buf)
619942e21c0SMax Gurtovoy {
620942e21c0SMax Gurtovoy 	struct nvme_subsystem *subsys =
621942e21c0SMax Gurtovoy 		container_of(dev, struct nvme_subsystem, dev);
622942e21c0SMax Gurtovoy 
623942e21c0SMax Gurtovoy 	switch (subsys->subtype) {
624942e21c0SMax Gurtovoy 	case NVME_NQN_DISC:
625942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "discovery\n");
626942e21c0SMax Gurtovoy 	case NVME_NQN_NVME:
627942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "nvm\n");
628942e21c0SMax Gurtovoy 	default:
629942e21c0SMax Gurtovoy 		return sysfs_emit(buf, "reserved\n");
630942e21c0SMax Gurtovoy 	}
631942e21c0SMax Gurtovoy }
632942e21c0SMax Gurtovoy static SUBSYS_ATTR_RO(subsystype, S_IRUGO, nvme_subsys_show_type);
633942e21c0SMax Gurtovoy 
634942e21c0SMax Gurtovoy #define nvme_subsys_show_str_function(field)				\
635942e21c0SMax Gurtovoy static ssize_t subsys_##field##_show(struct device *dev,		\
636942e21c0SMax Gurtovoy 			    struct device_attribute *attr, char *buf)	\
637942e21c0SMax Gurtovoy {									\
638942e21c0SMax Gurtovoy 	struct nvme_subsystem *subsys =					\
639942e21c0SMax Gurtovoy 		container_of(dev, struct nvme_subsystem, dev);		\
640942e21c0SMax Gurtovoy 	return sysfs_emit(buf, "%.*s\n",				\
641942e21c0SMax Gurtovoy 			   (int)sizeof(subsys->field), subsys->field);	\
642942e21c0SMax Gurtovoy }									\
643942e21c0SMax Gurtovoy static SUBSYS_ATTR_RO(field, S_IRUGO, subsys_##field##_show);
644942e21c0SMax Gurtovoy 
645942e21c0SMax Gurtovoy nvme_subsys_show_str_function(model);
646942e21c0SMax Gurtovoy nvme_subsys_show_str_function(serial);
647942e21c0SMax Gurtovoy nvme_subsys_show_str_function(firmware_rev);
648942e21c0SMax Gurtovoy 
649942e21c0SMax Gurtovoy static struct attribute *nvme_subsys_attrs[] = {
650942e21c0SMax Gurtovoy 	&subsys_attr_model.attr,
651942e21c0SMax Gurtovoy 	&subsys_attr_serial.attr,
652942e21c0SMax Gurtovoy 	&subsys_attr_firmware_rev.attr,
653942e21c0SMax Gurtovoy 	&subsys_attr_subsysnqn.attr,
654942e21c0SMax Gurtovoy 	&subsys_attr_subsystype.attr,
655942e21c0SMax Gurtovoy #ifdef CONFIG_NVME_MULTIPATH
656942e21c0SMax Gurtovoy 	&subsys_attr_iopolicy.attr,
657942e21c0SMax Gurtovoy #endif
658942e21c0SMax Gurtovoy 	NULL,
659942e21c0SMax Gurtovoy };
660942e21c0SMax Gurtovoy 
661942e21c0SMax Gurtovoy static const struct attribute_group nvme_subsys_attrs_group = {
662942e21c0SMax Gurtovoy 	.attrs = nvme_subsys_attrs,
663942e21c0SMax Gurtovoy };
664942e21c0SMax Gurtovoy 
665942e21c0SMax Gurtovoy const struct attribute_group *nvme_subsys_attrs_groups[] = {
666942e21c0SMax Gurtovoy 	&nvme_subsys_attrs_group,
667942e21c0SMax Gurtovoy 	NULL,
668942e21c0SMax Gurtovoy };
669