@@ -744,7 +744,7 @@ static int idxd_engines_setup(struct idxd_device *idxd)
}
for (i = 0; i < idxd->max_engines; i++) {
- eng = &idxd->engines[i];
+ eng = idxd->engines[i];
group = eng->group;
if (!group)
@@ -194,7 +194,7 @@ struct idxd_device {
struct completion *cmd_done;
struct idxd_group *groups;
struct idxd_wq **wqs;
- struct idxd_engine *engines;
+ struct idxd_engine **engines;
struct iommu_sva *sva;
unsigned int pasid;
@@ -181,6 +181,37 @@ static int idxd_allocate_wqs(struct idxd_device *idxd)
return rc;
}
+static int idxd_allocate_engines(struct idxd_device *idxd)
+{
+ struct idxd_engine *engine;
+ struct device *dev = &idxd->pdev->dev;
+ int i, rc;
+
+ idxd->engines = kcalloc_node(idxd->max_engines, sizeof(struct idxd_engine *),
+ GFP_KERNEL, dev_to_node(dev));
+ if (!idxd->engines)
+ return -ENOMEM;
+
+ for (i = 0; i < idxd->max_engines; i++) {
+ engine = kzalloc_node(sizeof(*engine), GFP_KERNEL, dev_to_node(dev));
+ if (!engine) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ idxd->engines[i] = engine;
+ }
+
+ return 0;
+
+ err:
+ while (--i >= 0)
+ kfree(idxd->engines[i]);
+ kfree(idxd->engines);
+ idxd->engines = NULL;
+ return rc;
+}
+
static int idxd_setup_internals(struct idxd_device *idxd)
{
struct device *dev = &idxd->pdev->dev;
@@ -217,15 +248,15 @@ static int idxd_setup_internals(struct idxd_device *idxd)
return -ENOMEM;
}
- idxd->engines = devm_kcalloc(dev, idxd->max_engines,
- sizeof(struct idxd_engine), GFP_KERNEL);
- if (!idxd->engines)
- return -ENOMEM;
-
+ rc = idxd_allocate_engines(idxd);
+ if (rc < 0)
+ return rc;
for (i = 0; i < idxd->max_engines; i++) {
- idxd->engines[i].idxd = idxd;
- idxd->engines[i].id = i;
+ struct idxd_engine *engine = idxd->engines[i];
+
+ engine->idxd = idxd;
+ engine->id = i;
}
idxd->wq = create_workqueue(dev_name(dev));
@@ -363,6 +394,12 @@ static void idxd_free(struct idxd_device *idxd)
kfree(idxd->wqs);
}
+ if (idxd->engines) {
+ for (i = 0; i < idxd->max_engines; i++)
+ kfree(idxd->engines[i]);
+ kfree(idxd->engines);
+ }
+
kfree(idxd);
}
@@ -26,11 +26,6 @@ static struct device_type idxd_group_device_type = {
.release = idxd_conf_sub_device_release,
};
-static struct device_type idxd_engine_device_type = {
- .name = "engine",
- .release = idxd_conf_sub_device_release,
-};
-
static int idxd_config_bus_match(struct device *dev,
struct device_driver *drv)
{
@@ -469,6 +464,19 @@ static const struct attribute_group *idxd_engine_attribute_groups[] = {
NULL,
};
+static void idxd_conf_engine_release(struct device *dev)
+{
+ struct idxd_engine *engine = container_of(dev, struct idxd_engine, conf_dev);
+
+ kfree(engine);
+}
+
+static struct device_type idxd_engine_device_type = {
+ .name = "engine",
+ .release = idxd_conf_engine_release,
+ .groups = idxd_engine_attribute_groups,
+};
+
/* Group attributes */
static void idxd_set_free_tokens(struct idxd_device *idxd)
@@ -631,7 +639,7 @@ static ssize_t group_engines_show(struct device *dev,
struct idxd_device *idxd = group->idxd;
for (i = 0; i < idxd->max_engines; i++) {
- struct idxd_engine *engine = &idxd->engines[i];
+ struct idxd_engine *engine = idxd->engines[i];
if (!engine->group)
continue;
@@ -1638,30 +1646,28 @@ static int idxd_setup_engine_sysfs(struct idxd_device *idxd)
int i, rc;
for (i = 0; i < idxd->max_engines; i++) {
- struct idxd_engine *engine = &idxd->engines[i];
+ struct idxd_engine *engine = idxd->engines[i];
+ device_initialize(&engine->conf_dev);
engine->conf_dev.parent = &idxd->conf_dev;
- dev_set_name(&engine->conf_dev, "engine%d.%d",
- idxd->id, engine->id);
engine->conf_dev.bus = idxd_get_bus_type(idxd);
- engine->conf_dev.groups = idxd_engine_attribute_groups;
engine->conf_dev.type = &idxd_engine_device_type;
- dev_dbg(dev, "Engine device register: %s\n",
- dev_name(&engine->conf_dev));
- rc = device_register(&engine->conf_dev);
- if (rc < 0) {
- put_device(&engine->conf_dev);
+ rc = dev_set_name(&engine->conf_dev, "engine%d.%d", idxd->id, engine->id);
+ if (rc < 0)
+ goto cleanup;
+ dev_dbg(dev, "Engine device register: %s\n", dev_name(&engine->conf_dev));
+ rc = device_add(&engine->conf_dev);
+ if (rc < 0)
goto cleanup;
- }
}
return 0;
cleanup:
while (i--) {
- struct idxd_engine *engine = &idxd->engines[i];
+ struct idxd_engine *engine = idxd->engines[i];
- device_unregister(&engine->conf_dev);
+ put_device(&engine->conf_dev);
}
return rc;
}
@@ -1803,7 +1809,7 @@ void idxd_unregister_devices(struct idxd_device *idxd)
}
for (i = 0; i < idxd->max_engines; i++) {
- struct idxd_engine *engine = &idxd->engines[i];
+ struct idxd_engine *engine = idxd->engines[i];
device_unregister(&engine->conf_dev);
}