This patch adds the concept of "descendant" device to the pnp layer, one which can claim memory mapped I/O space from the same regions of address space that its "aunts" and "uncles" are claiming from. This is more or less analogous to a device on an ISA bus that needs address space, but needs to avoid claiming any regions that are in use by PCI devices which are peers of the PCI to ISA bridge. This is done in support of changes in the Hyper-V-related drivers, but nothing in this patch is specific to Hyper-V, except in that it doesn't seem to be needed for anything else. Signed-off-by: Jake Oshins <jakeo@xxxxxxxxxxxxx> --- drivers/pnp/Makefile | 2 +- drivers/pnp/base.h | 2 + drivers/pnp/core.c | 1 + drivers/pnp/descendant.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pnp.h | 23 ++++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 drivers/pnp/descendant.c diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile index bfba893..de315f9 100644 --- a/drivers/pnp/Makefile +++ b/drivers/pnp/Makefile @@ -4,7 +4,7 @@ obj-y := pnp.o -pnp-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o +pnp-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o descendant.o obj-$(CONFIG_PNPACPI) += pnpacpi/ obj-$(CONFIG_PNPBIOS) += pnpbios/ diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index c8873b0..0b86437 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -175,6 +175,8 @@ struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev, resource_size_t start, resource_size_t end); +int __init pnpdescendant_init(void); + extern int pnp_debug; #if defined(CONFIG_PNP_DEBUG_MESSAGES) diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index cb6ce42..fc32912 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -212,6 +212,7 @@ void __pnp_remove_device(struct pnp_dev *dev) static int __init pnp_init(void) { + pnpdescendant_init(); return bus_register(&pnp_bus_type); } diff --git a/drivers/pnp/descendant.c b/drivers/pnp/descendant.c new file mode 100644 index 0000000..c25e40b --- /dev/null +++ b/drivers/pnp/descendant.c @@ -0,0 +1,117 @@ +/* + * descendant.c - Resource management for devices which are descendants + * (children or grandchildren of) devices which directly allocate resources, + * i.e. devices enumerated by ACPI, PCI, PCMCIA, ISAPNP or PNPBIOS + * + * Copyright (C) 2015 Microsoft + * Jake Oshins <jakeo@xxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/pnp.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include "base.h" + +int descendant_get_resources(struct pnp_dev *dev) +{ + return 0; +} + +int descendant_set_resources(struct pnp_dev *dev) +{ + return 0; +} + +int descendant_disable_resources(struct pnp_dev *dev) +{ + return 0; +} + +struct pnp_protocol descendant_protocol = { + .name = "Plug and Play descendants", + .get = descendant_get_resources, + .set = descendant_set_resources, + .disable = descendant_disable_resources, +}; + +/* + * This adds an option to the descendant device for memory address space. +*/ +int pnp_descendant_memory_option(struct pnp_dev *dev, resource_size_t min, + resource_size_t max, resource_size_t alignment, + resource_size_t size, unsigned char flags) +{ + return pnp_register_mem_resource(dev, 0, min, max, alignment, size, + flags); +} +EXPORT_SYMBOL(pnp_descendant_memory_option); + +/* + * This creates an entry in the plug-and-play layer for this device, which + * is a descendant of a device already in the plug-and-play layer. +*/ +int pnp_add_descendant(struct pnp_dev *dev) +{ + int error; + + error = pnp_add_device(dev); + if (error) { + put_device(&dev->dev); + return error; + } + + return 0; +} +EXPORT_SYMBOL(pnp_add_descendant); + +void pnp_remove_descendant(struct pnp_dev *dev) +{ + __pnp_remove_device(dev); +} +EXPORT_SYMBOL(pnp_remove_descendant); + +int __init pnpdescendant_init(void) +{ + return pnp_register_protocol(&descendant_protocol); +} + +struct pnp_dev *alloc_pnp_descendant(const char *pnpid) +{ + struct pnp_dev *dev; + + dev = pnp_alloc_dev(&descendant_protocol, 0, pnpid); + + if (!dev) + return NULL; + + pnp_init_resources(dev); + dev->capabilities |= PNP_CONFIGURABLE; + dev->capabilities |= PNP_READ; + dev->capabilities |= PNP_WRITE; + dev->capabilities |= PNP_DISABLE; + dev->capabilities |= PNP_REMOVABLE; + + return dev; +} +EXPORT_SYMBOL(alloc_pnp_descendant); + +void free_pnp_descendant(struct pnp_dev *dev) +{ + kfree(dev); +} +EXPORT_SYMBOL(free_pnp_descendant); + diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 6512e9c..269a7af 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -477,6 +477,15 @@ int compare_pnp_id(struct pnp_id *pos, const char *id); int pnp_register_driver(struct pnp_driver *drv); void pnp_unregister_driver(struct pnp_driver *drv); +/* descendant support */ +struct pnp_dev *alloc_pnp_descendant(const char *pnpid); +void free_pnp_descendant(struct pnp_dev *dev); +int pnp_add_descendant(struct pnp_dev *dev); +void pnp_remove_descendant(struct pnp_dev *dev); +int pnp_descendant_memory_option(struct pnp_dev *dev, resource_size_t min, + resource_size_t max, resource_size_t alignment, + resource_size_t size, unsigned char flags); + #else /* device management */ @@ -508,6 +517,20 @@ static inline int compare_pnp_id(struct pnp_id *pos, const char *id) { return -E static inline int pnp_register_driver(struct pnp_driver *drv) { return -ENODEV; } static inline void pnp_unregister_driver(struct pnp_driver *drv) { } +/* descendant support */ +static inline struct pnp_dev *alloc_pnp_descendant(const char *pnpid) +{ return NULL; } +static inline void free_pnp_descendant(struct pnp_dev *dev) { } +static inline int pnp_add_descendant(struct pnp_dev *dev) { return -ENODEV; } +static inline void pnp_remove_descendant(struct pnp_dev *dev) { } +static inline int pnp_descendant_memory_option(struct pnp_dev *dev, + resource_size_t min, + resource_size_t max, + resource_size_t alignment, + resource_size_t size, + unsigned char flags) +{ return -ENODEV; } + #endif /* CONFIG_PNP */ #endif /* _LINUX_PNP_H */ -- 1.9.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel