dmaengine: idxd: add event log size sysfs attribute
[linux-2.6-block.git] / drivers / dma / idxd / sysfs.c
index 18cd8151dee02ca32ec07bed109f24b193b2bfdf..85644e5bde8398b1eb2cc2e6a23565b86cdc3f6f 100644 (file)
@@ -1452,15 +1452,13 @@ static ssize_t errors_show(struct device *dev,
                           struct device_attribute *attr, char *buf)
 {
        struct idxd_device *idxd = confdev_to_idxd(dev);
-       int i, out = 0;
+       DECLARE_BITMAP(swerr_bmap, 256);
 
+       bitmap_zero(swerr_bmap, 256);
        spin_lock(&idxd->dev_lock);
-       for (i = 0; i < 4; i++)
-               out += sysfs_emit_at(buf, out, "%#018llx ", idxd->sw_err.bits[i]);
+       multi_u64_to_bmap(swerr_bmap, &idxd->sw_err.bits[0], 4);
        spin_unlock(&idxd->dev_lock);
-       out--;
-       out += sysfs_emit_at(buf, out, "\n");
-       return out;
+       return sysfs_emit(buf, "%*pb\n", 256, swerr_bmap);
 }
 static DEVICE_ATTR_RO(errors);
 
@@ -1563,6 +1561,58 @@ static ssize_t cmd_status_store(struct device *dev, struct device_attribute *att
 }
 static DEVICE_ATTR_RW(cmd_status);
 
+static ssize_t iaa_cap_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct idxd_device *idxd = confdev_to_idxd(dev);
+
+       if (idxd->hw.version < DEVICE_VERSION_2)
+               return -EOPNOTSUPP;
+
+       return sysfs_emit(buf, "%#llx\n", idxd->hw.iaa_cap.bits);
+}
+static DEVICE_ATTR_RO(iaa_cap);
+
+static ssize_t event_log_size_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct idxd_device *idxd = confdev_to_idxd(dev);
+
+       if (!idxd->evl)
+               return -EOPNOTSUPP;
+
+       return sysfs_emit(buf, "%u\n", idxd->evl->size);
+}
+
+static ssize_t event_log_size_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       struct idxd_device *idxd = confdev_to_idxd(dev);
+       unsigned long val;
+       int rc;
+
+       if (!idxd->evl)
+               return -EOPNOTSUPP;
+
+       rc = kstrtoul(buf, 10, &val);
+       if (rc < 0)
+               return -EINVAL;
+
+       if (idxd->state == IDXD_DEV_ENABLED)
+               return -EPERM;
+
+       if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
+               return -EPERM;
+
+       if (val < IDXD_EVL_SIZE_MIN || val > IDXD_EVL_SIZE_MAX)
+               return -EINVAL;
+
+       idxd->evl->size = val;
+       return count;
+}
+static DEVICE_ATTR_RW(event_log_size);
+
 static bool idxd_device_attr_max_batch_size_invisible(struct attribute *attr,
                                                      struct idxd_device *idxd)
 {
@@ -1585,6 +1635,21 @@ static bool idxd_device_attr_read_buffers_invisible(struct attribute *attr,
                idxd->data->type == IDXD_TYPE_IAX;
 }
 
+static bool idxd_device_attr_iaa_cap_invisible(struct attribute *attr,
+                                              struct idxd_device *idxd)
+{
+       return attr == &dev_attr_iaa_cap.attr &&
+              (idxd->data->type != IDXD_TYPE_IAX ||
+              idxd->hw.version < DEVICE_VERSION_2);
+}
+
+static bool idxd_device_attr_event_log_size_invisible(struct attribute *attr,
+                                                     struct idxd_device *idxd)
+{
+       return (attr == &dev_attr_event_log_size.attr &&
+               !idxd->hw.gen_cap.evl_support);
+}
+
 static umode_t idxd_device_attr_visible(struct kobject *kobj,
                                        struct attribute *attr, int n)
 {
@@ -1597,6 +1662,12 @@ static umode_t idxd_device_attr_visible(struct kobject *kobj,
        if (idxd_device_attr_read_buffers_invisible(attr, idxd))
                return 0;
 
+       if (idxd_device_attr_iaa_cap_invisible(attr, idxd))
+               return 0;
+
+       if (idxd_device_attr_event_log_size_invisible(attr, idxd))
+               return 0;
+
        return attr->mode;
 }
 
@@ -1622,6 +1693,8 @@ static struct attribute *idxd_device_attributes[] = {
        &dev_attr_read_buffer_limit.attr,
        &dev_attr_cdev_major.attr,
        &dev_attr_cmd_status.attr,
+       &dev_attr_iaa_cap.attr,
+       &dev_attr_event_log_size.attr,
        NULL,
 };
 
@@ -1643,6 +1716,7 @@ static void idxd_conf_device_release(struct device *dev)
        bitmap_free(idxd->wq_enable_map);
        kfree(idxd->wqs);
        kfree(idxd->engines);
+       kfree(idxd->evl);
        ida_free(&idxd_ida, idxd->id);
        bitmap_free(idxd->opcap_bmap);
        kfree(idxd);