diff --git a/gasket_core.c b/gasket_core.c index 1cbae4d..65b3ab2 100644 --- a/gasket_core.c +++ b/gasket_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -668,6 +669,25 @@ lookup_pci_internal_desc(struct pci_dev *pci_dev) return NULL; } +/* + * Registered driver descriptor lookup for platform devices. + * Caller must hold g_mutex. + */ +static struct gasket_internal_desc * +lookup_platform_internal_desc(struct platform_device *pdev) +{ + int i; + + __must_hold(&g_mutex); + for (i = 0; i < GASKET_FRAMEWORK_DESC_MAX; i++) { + if (g_descs[i].driver_desc && + strcmp(g_descs[i].driver_desc->name, pdev->name) == 0) + return &g_descs[i]; + } + + return NULL; +} + /* * Verifies that the user has permissions to perform the requested mapping and * that the provided descriptor/range is of adequate size to hold the range to @@ -1557,6 +1577,72 @@ void gasket_pci_remove_device(struct pci_dev *pci_dev) } EXPORT_SYMBOL(gasket_pci_remove_device); +/* Add platform gasket device. Called by Gasket device probe function. */ +int gasket_platform_add_device(struct platform_device *pdev, + struct gasket_dev **gasket_devp) +{ + int ret; + struct gasket_internal_desc *internal_desc; + struct gasket_dev *gasket_dev; + struct device *parent; + + dev_dbg(&pdev->dev, "add platform gasket device\n"); + + mutex_lock(&g_mutex); + internal_desc = lookup_platform_internal_desc(pdev); + mutex_unlock(&g_mutex); + if (!internal_desc) { + dev_err(&pdev->dev, + "%s called for unknown driver type\n", __func__); + return -ENODEV; + } + + parent = &pdev->dev; + ret = __gasket_add_device(parent, internal_desc, &gasket_dev); + if (ret) + return ret; + + gasket_dev->platform_dev = pdev; + *gasket_devp = gasket_dev; + return 0; +} +EXPORT_SYMBOL(gasket_platform_add_device); + +/* Remove a platform gasket device. */ +void gasket_platform_remove_device(struct platform_device *pdev) +{ + int i; + struct gasket_internal_desc *internal_desc; + struct gasket_dev *gasket_dev = NULL; + + /* Find the device desc. */ + mutex_lock(&g_mutex); + internal_desc = lookup_platform_internal_desc(pdev); + mutex_unlock(&g_mutex); + if (!internal_desc) + return; + + /* Now find the specific device */ + mutex_lock(&internal_desc->mutex); + for (i = 0; i < GASKET_DEV_MAX; i++) { + if (internal_desc->devs[i] && + internal_desc->devs[i]->platform_dev == pdev) { + gasket_dev = internal_desc->devs[i]; + break; + } + } + mutex_unlock(&internal_desc->mutex); + + if (!gasket_dev) + return; + + dev_dbg(gasket_dev->dev, "remove %s platform gasket device\n", + internal_desc->driver_desc->name); + + __gasket_remove_device(internal_desc, gasket_dev); +} +EXPORT_SYMBOL(gasket_platform_remove_device); + /** * Lookup a name by number in a num_name table. * @num: Number to lookup. diff --git a/gasket_core.h b/gasket_core.h index ef7cf16..75ad11b 100644 --- a/gasket_core.h +++ b/gasket_core.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -265,9 +266,12 @@ struct gasket_dev { /* Device info */ struct device *dev; - /* PCI subsystem metadata. */ + /* PCI device pointer for PCI devices */ struct pci_dev *pci_dev; + /* Platform device pointer for platform devices */ + struct platform_device *platform_dev; + /* This device's index into internal_desc->devs. */ int dev_idx; @@ -539,6 +543,13 @@ int gasket_pci_add_device(struct pci_dev *pci_dev, /* Remove a PCI gasket device. */ void gasket_pci_remove_device(struct pci_dev *pci_dev); +/* Add a platform gasket device. */ +int gasket_platform_add_device(struct platform_device *pdev, + struct gasket_dev **gasket_devp); + +/* Remove a platform gasket device. */ +void gasket_platform_remove_device(struct platform_device *pdev); + /* Enable a Gasket device. */ int gasket_enable_device(struct gasket_dev *gasket_dev);