|
@@ -1362,7 +1362,7 @@ static struct attribute *nvme_ns_attrs[] = {
|
|
|
NULL,
|
|
|
};
|
|
|
|
|
|
-static umode_t nvme_attrs_are_visible(struct kobject *kobj,
|
|
|
+static umode_t nvme_ns_attrs_are_visible(struct kobject *kobj,
|
|
|
struct attribute *a, int n)
|
|
|
{
|
|
|
struct device *dev = container_of(kobj, struct device, kobj);
|
|
@@ -1381,7 +1381,7 @@ static umode_t nvme_attrs_are_visible(struct kobject *kobj,
|
|
|
|
|
|
static const struct attribute_group nvme_ns_attr_group = {
|
|
|
.attrs = nvme_ns_attrs,
|
|
|
- .is_visible = nvme_attrs_are_visible,
|
|
|
+ .is_visible = nvme_ns_attrs_are_visible,
|
|
|
};
|
|
|
|
|
|
#define nvme_show_str_function(field) \
|
|
@@ -1407,6 +1407,49 @@ nvme_show_str_function(serial);
|
|
|
nvme_show_str_function(firmware_rev);
|
|
|
nvme_show_int_function(cntlid);
|
|
|
|
|
|
+static ssize_t nvme_sysfs_delete(struct device *dev,
|
|
|
+ struct device_attribute *attr, const char *buf,
|
|
|
+ size_t count)
|
|
|
+{
|
|
|
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (device_remove_file_self(dev, attr))
|
|
|
+ ctrl->ops->delete_ctrl(ctrl);
|
|
|
+ return count;
|
|
|
+}
|
|
|
+static DEVICE_ATTR(delete_controller, S_IWUSR, NULL, nvme_sysfs_delete);
|
|
|
+
|
|
|
+static ssize_t nvme_sysfs_show_transport(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ return snprintf(buf, PAGE_SIZE, "%s\n", ctrl->ops->name);
|
|
|
+}
|
|
|
+static DEVICE_ATTR(transport, S_IRUGO, nvme_sysfs_show_transport, NULL);
|
|
|
+
|
|
|
+static ssize_t nvme_sysfs_show_subsysnqn(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ return snprintf(buf, PAGE_SIZE, "%s\n",
|
|
|
+ ctrl->ops->get_subsysnqn(ctrl));
|
|
|
+}
|
|
|
+static DEVICE_ATTR(subsysnqn, S_IRUGO, nvme_sysfs_show_subsysnqn, NULL);
|
|
|
+
|
|
|
+static ssize_t nvme_sysfs_show_address(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ return ctrl->ops->get_address(ctrl, buf, PAGE_SIZE);
|
|
|
+}
|
|
|
+static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL);
|
|
|
+
|
|
|
static struct attribute *nvme_dev_attrs[] = {
|
|
|
&dev_attr_reset_controller.attr,
|
|
|
&dev_attr_rescan_controller.attr,
|
|
@@ -1414,11 +1457,38 @@ static struct attribute *nvme_dev_attrs[] = {
|
|
|
&dev_attr_serial.attr,
|
|
|
&dev_attr_firmware_rev.attr,
|
|
|
&dev_attr_cntlid.attr,
|
|
|
+ &dev_attr_delete_controller.attr,
|
|
|
+ &dev_attr_transport.attr,
|
|
|
+ &dev_attr_subsysnqn.attr,
|
|
|
+ &dev_attr_address.attr,
|
|
|
NULL
|
|
|
};
|
|
|
|
|
|
+#define CHECK_ATTR(ctrl, a, name) \
|
|
|
+ if ((a) == &dev_attr_##name.attr && \
|
|
|
+ !(ctrl)->ops->get_##name) \
|
|
|
+ return 0
|
|
|
+
|
|
|
+static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
|
|
|
+ struct attribute *a, int n)
|
|
|
+{
|
|
|
+ struct device *dev = container_of(kobj, struct device, kobj);
|
|
|
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (a == &dev_attr_delete_controller.attr) {
|
|
|
+ if (!ctrl->ops->delete_ctrl)
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ CHECK_ATTR(ctrl, a, subsysnqn);
|
|
|
+ CHECK_ATTR(ctrl, a, address);
|
|
|
+
|
|
|
+ return a->mode;
|
|
|
+}
|
|
|
+
|
|
|
static struct attribute_group nvme_dev_attrs_group = {
|
|
|
- .attrs = nvme_dev_attrs,
|
|
|
+ .attrs = nvme_dev_attrs,
|
|
|
+ .is_visible = nvme_dev_attrs_are_visible,
|
|
|
};
|
|
|
|
|
|
static const struct attribute_group *nvme_dev_attr_groups[] = {
|