@@ -255,6 +255,23 @@ extern struct bus_type dsa_bus_type;
extern struct bus_type iax_bus_type;
extern bool support_enqcmd;
+extern struct device_type dsa_device_type;
+extern struct device_type iax_device_type;
+
+static inline bool is_dsa_dev(struct device *dev)
+{
+ return dev->type == &dsa_device_type;
+}
+
+static inline bool is_iax_dev(struct device *dev)
+{
+ return dev->type == &iax_device_type;
+}
+
+static inline bool is_idxd_dev(struct device *dev)
+{
+ return is_dsa_dev(dev) || is_iax_dev(dev);
+}
static inline bool wq_dedicated(struct idxd_wq *wq)
{
@@ -322,8 +339,8 @@ static inline int idxd_wq_refcount(struct idxd_wq *wq)
const char *idxd_get_dev_name(struct idxd_device *idxd);
int idxd_register_bus_type(void);
void idxd_unregister_bus_type(void);
-int idxd_setup_sysfs(struct idxd_device *idxd);
-void idxd_cleanup_sysfs(struct idxd_device *idxd);
+int idxd_register_devices(struct idxd_device *idxd);
+void idxd_unregister_devices(struct idxd_device *idxd);
int idxd_register_driver(void);
void idxd_unregister_driver(void);
struct bus_type *idxd_get_bus_type(struct idxd_device *idxd);
@@ -83,9 +83,8 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
* We implement 1 completion list per MSI-X entry except for
* entry 0, which is for errors and others.
*/
- idxd->irq_entries = devm_kcalloc(dev, msixcnt,
- sizeof(struct idxd_irq_entry),
- GFP_KERNEL);
+ idxd->irq_entries = kcalloc_node(msixcnt, sizeof(struct idxd_irq_entry),
+ GFP_KERNEL, dev_to_node(dev));
if (!idxd->irq_entries) {
rc = -ENOMEM;
goto err_irq_entries;
@@ -144,6 +143,7 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
err_misc_irq:
/* Disable error interrupt generation */
idxd_mask_error_interrupts(idxd);
+ kfree(idxd->irq_entries);
err_irq_entries:
pci_free_irq_vectors(pdev);
dev_err(dev, "No usable interrupts\n");
@@ -276,7 +276,7 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev)
struct device *dev = &pdev->dev;
struct idxd_device *idxd;
- idxd = devm_kzalloc(dev, sizeof(struct idxd_device), GFP_KERNEL);
+ idxd = kzalloc_node(sizeof(*idxd), GFP_KERNEL, dev_to_node(dev));
if (!idxd)
return NULL;
@@ -320,6 +320,11 @@ static void idxd_disable_system_pasid(struct idxd_device *idxd)
idxd->sva = NULL;
}
+static void idxd_free(struct idxd_device *idxd)
+{
+ kfree(idxd);
+}
+
static int idxd_probe(struct idxd_device *idxd)
{
struct pci_dev *pdev = idxd->pdev;
@@ -438,7 +443,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err;
}
- rc = idxd_setup_sysfs(idxd);
+ rc = idxd_register_devices(idxd);
if (rc) {
dev_err(dev, "IDXD sysfs setup failed\n");
goto err;
@@ -454,6 +459,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err:
pci_iounmap(pdev, idxd->reg_base);
err_iomap:
+ idxd_free(idxd);
err_idxd_alloc:
pci_disable_device(pdev);
return rc;
@@ -519,15 +525,17 @@ static void idxd_shutdown(struct pci_dev *pdev)
static void idxd_remove(struct pci_dev *pdev)
{
struct idxd_device *idxd = pci_get_drvdata(pdev);
+ int id = idxd->id;
+ enum idxd_type type = idxd->type;
dev_dbg(&pdev->dev, "%s called\n", __func__);
- idxd_cleanup_sysfs(idxd);
idxd_shutdown(pdev);
if (device_pasid_enabled(idxd))
idxd_disable_system_pasid(idxd);
mutex_lock(&idxd_idr_lock);
- idr_remove(&idxd_idrs[idxd->type], idxd->id);
+ idr_remove(&idxd_idrs[type], id);
mutex_unlock(&idxd_idr_lock);
+ idxd_unregister_devices(idxd);
}
static struct pci_driver idxd_pci_driver = {
@@ -16,51 +16,26 @@ static char *idxd_wq_type_names[] = {
[IDXD_WQT_USER] = "user",
};
-static void idxd_conf_device_release(struct device *dev)
+static void idxd_conf_sub_device_release(struct device *dev)
{
dev_dbg(dev, "%s for %s\n", __func__, dev_name(dev));
}
static struct device_type idxd_group_device_type = {
.name = "group",
- .release = idxd_conf_device_release,
+ .release = idxd_conf_sub_device_release,
};
static struct device_type idxd_wq_device_type = {
.name = "wq",
- .release = idxd_conf_device_release,
+ .release = idxd_conf_sub_device_release,
};
static struct device_type idxd_engine_device_type = {
.name = "engine",
- .release = idxd_conf_device_release,
-};
-
-static struct device_type dsa_device_type = {
- .name = "dsa",
- .release = idxd_conf_device_release,
-};
-
-static struct device_type iax_device_type = {
- .name = "iax",
- .release = idxd_conf_device_release,
+ .release = idxd_conf_sub_device_release,
};
-static inline bool is_dsa_dev(struct device *dev)
-{
- return dev ? dev->type == &dsa_device_type : false;
-}
-
-static inline bool is_iax_dev(struct device *dev)
-{
- return dev ? dev->type == &iax_device_type : false;
-}
-
-static inline bool is_idxd_dev(struct device *dev)
-{
- return is_dsa_dev(dev) || is_iax_dev(dev);
-}
-
static inline bool is_idxd_wq_dev(struct device *dev)
{
return dev ? dev->type == &idxd_wq_device_type : false;
@@ -1643,6 +1618,29 @@ static const struct attribute_group *idxd_attribute_groups[] = {
NULL,
};
+static void idxd_conf_device_release(struct device *dev)
+{
+ struct idxd_device *idxd = container_of(dev, struct idxd_device, conf_dev);
+
+ kfree(idxd->groups);
+ kfree(idxd->wqs);
+ kfree(idxd->engines);
+ kfree(idxd->irq_entries);
+ kfree(idxd);
+}
+
+struct device_type dsa_device_type = {
+ .name = "dsa",
+ .release = idxd_conf_device_release,
+ .groups = idxd_attribute_groups,
+};
+
+struct device_type iax_device_type = {
+ .name = "iax",
+ .release = idxd_conf_device_release,
+ .groups = idxd_attribute_groups,
+};
+
static int idxd_setup_engine_sysfs(struct idxd_device *idxd)
{
struct device *dev = &idxd->pdev->dev;
@@ -1748,17 +1746,19 @@ static int idxd_setup_device_sysfs(struct idxd_device *idxd)
{
struct device *dev = &idxd->pdev->dev;
int rc;
- char devname[IDXD_NAME_SIZE];
- sprintf(devname, "%s%d", idxd_get_dev_name(idxd), idxd->id);
+ device_initialize(&idxd->conf_dev);
idxd->conf_dev.parent = dev;
- dev_set_name(&idxd->conf_dev, "%s", devname);
idxd->conf_dev.bus = idxd_get_bus_type(idxd);
- idxd->conf_dev.groups = idxd_attribute_groups;
idxd->conf_dev.type = idxd_get_device_type(idxd);
+ rc = dev_set_name(&idxd->conf_dev, "%s%d", idxd_get_dev_name(idxd), idxd->id);
+ if (rc < 0) {
+ put_device(&idxd->conf_dev);
+ return rc;
+ }
dev_dbg(dev, "IDXD device register: %s\n", dev_name(&idxd->conf_dev));
- rc = device_register(&idxd->conf_dev);
+ rc = device_add(&idxd->conf_dev);
if (rc < 0) {
put_device(&idxd->conf_dev);
return rc;
@@ -1767,7 +1767,7 @@ static int idxd_setup_device_sysfs(struct idxd_device *idxd)
return 0;
}
-int idxd_setup_sysfs(struct idxd_device *idxd)
+int idxd_register_devices(struct idxd_device *idxd)
{
struct device *dev = &idxd->pdev->dev;
int rc;
@@ -1802,7 +1802,7 @@ int idxd_setup_sysfs(struct idxd_device *idxd)
return 0;
}
-void idxd_cleanup_sysfs(struct idxd_device *idxd)
+void idxd_unregister_devices(struct idxd_device *idxd)
{
int i;