From 4a7cc831670550e6b48ef5760e7213f89935ff0d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Thu, 9 Jul 2015 16:00:44 +0800 Subject: genirq/MSI: Move msi_list from struct pci_dev to struct device Move msi_list from struct pci_dev into struct device, so we can support non-PCI-device based generic MSI interrupts. msi_list is now conditional under CONFIG_GENERIC_MSI_IRQ, which is selected from CONFIG_PCI_MSI, so no functional change for PCI MSI users. Signed-off-by: Jiang Liu Reviewed-by: Yijing Wang Acked-by: Bjorn Helgaas Cc: Tony Luck Cc: linux-arm-kernel@lists.infradead.org Cc: Grant Likely Cc: Marc Zyngier Cc: Stuart Yoder Cc: Borislav Petkov Cc: Greg Kroah-Hartman Cc: Joe Perches Cc: Dmitry Torokhov Cc: Paul Gortmaker Cc: Luis R. Rodriguez Cc: Rafael J. Wysocki Cc: Joerg Roedel Cc: Alexander Gordeev Link: http://lkml.kernel.org/r/1436428847-8886-10-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- include/linux/device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/device.h') diff --git a/include/linux/device.h b/include/linux/device.h index 5a31bf3a4024..22227e7fe463 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -713,6 +713,7 @@ struct device_dma_parameters { * along with subsystem-level and driver-level callbacks. * @pins: For device pin management. * See Documentation/pinctrl.txt for details. + * @msi_list: Hosts MSI descriptors * @numa_node: NUMA node this device is close to. * @dma_mask: Dma mask (if dma'ble device). * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all @@ -776,6 +777,9 @@ struct device { #ifdef CONFIG_PINCTRL struct dev_pin_info *pins; #endif +#ifdef CONFIG_GENERIC_MSI_IRQ + struct list_head msi_list; +#endif #ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ -- cgit v1.2.3 From 3d060aeb72113cda0acf906bfe26914fc689506a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 27 Jul 2015 18:04:00 +0300 Subject: driver core: implement device_for_each_child_reverse() The new function device_for_each_child_reverse() is helpful to traverse the registered devices in a reversed order, e.g. in the case when an operation on each device should be done first on the last added device, then on one before last and so on. Signed-off-by: Andy Shevchenko Acked-by: Greg Kroah-Hartman Signed-off-by: Lee Jones --- drivers/base/core.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 2 ++ 2 files changed, 45 insertions(+) (limited to 'include/linux/device.h') diff --git a/drivers/base/core.c b/drivers/base/core.c index dafae6d2f7ac..7d6279554afc 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1252,6 +1252,19 @@ void device_unregister(struct device *dev) } EXPORT_SYMBOL_GPL(device_unregister); +static struct device *prev_device(struct klist_iter *i) +{ + struct klist_node *n = klist_prev(i); + struct device *dev = NULL; + struct device_private *p; + + if (n) { + p = to_device_private_parent(n); + dev = p->device; + } + return dev; +} + static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); @@ -1340,6 +1353,36 @@ int device_for_each_child(struct device *parent, void *data, } EXPORT_SYMBOL_GPL(device_for_each_child); +/** + * device_for_each_child_reverse - device child iterator in reversed order. + * @parent: parent struct device. + * @fn: function to be called for each device. + * @data: data for the callback. + * + * Iterate over @parent's child devices, and call @fn for each, + * passing it @data. + * + * We check the return of @fn each time. If it returns anything + * other than 0, we break out and return that value. + */ +int device_for_each_child_reverse(struct device *parent, void *data, + int (*fn)(struct device *dev, void *data)) +{ + struct klist_iter i; + struct device *child; + int error = 0; + + if (!parent->p) + return 0; + + klist_iter_init(&parent->p->klist_children, &i); + while ((child = prev_device(&i)) && !error) + error = fn(child, data); + klist_iter_exit(&i); + return error; +} +EXPORT_SYMBOL_GPL(device_for_each_child_reverse); + /** * device_find_child - device iterator for locating a particular device. * @parent: parent struct device diff --git a/include/linux/device.h b/include/linux/device.h index 5a31bf3a4024..af6fbc35d8a6 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -958,6 +958,8 @@ extern int __must_check device_add(struct device *dev); extern void device_del(struct device *dev); extern int device_for_each_child(struct device *dev, void *data, int (*fn)(struct device *dev, void *data)); +extern int device_for_each_child_reverse(struct device *dev, void *data, + int (*fn)(struct device *dev, void *data)); extern struct device *device_find_child(struct device *dev, void *data, int (*match)(struct device *dev, void *data)); extern int device_rename(struct device *dev, const char *new_name); -- cgit v1.2.3 From f1421db8ca4c110144be97a5997ed83d34685db5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 28 Jul 2015 14:46:10 +0100 Subject: device core: Introduce per-device MSI domain pointer As MSI-type features are creeping into non-PCI devices, it is starting to make sense to give our struct device some form of support for this, by allowing a pointer to an MSI irq domain to be set/retrieved. Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier Cc: Cc: Yijing Wang Cc: Ma Jun Cc: Lorenzo Pieralisi Cc: Duc Dang Cc: Bjorn Helgaas Cc: Jiang Liu Cc: Jason Cooper Link: http://lkml.kernel.org/r/1438091186-10244-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/device.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include/linux/device.h') diff --git a/include/linux/device.h b/include/linux/device.h index 3d3139ad5705..50e000576d3c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -715,6 +715,7 @@ struct device_dma_parameters { * @pins: For device pin management. * See Documentation/pinctrl.txt for details. * @msi_list: Hosts MSI descriptors + * @msi_domain: The generic MSI domain this device is using. * @numa_node: NUMA node this device is close to. * @dma_mask: Dma mask (if dma'ble device). * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all @@ -775,6 +776,9 @@ struct device { struct dev_pm_info power; struct dev_pm_domain *pm_domain; +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN + struct irq_domain *msi_domain; +#endif #ifdef CONFIG_PINCTRL struct dev_pin_info *pins; #endif @@ -865,6 +869,22 @@ static inline void set_dev_node(struct device *dev, int node) } #endif +static inline struct irq_domain *dev_get_msi_domain(const struct device *dev) +{ +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN + return dev->msi_domain; +#else + return NULL; +#endif +} + +static inline void dev_set_msi_domain(struct device *dev, struct irq_domain *d) +{ +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN + dev->msi_domain = d; +#endif +} + static inline void *dev_get_drvdata(const struct device *dev) { return dev->driver_data; -- cgit v1.2.3 From 71db87ba570038497db1227b7dc61113c4156565 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 30 Jul 2015 15:04:01 +0530 Subject: bus: subsys: update return type of ->remove_dev() to void Its return value is not used by the subsys core and nothing meaningful can be done with it, even if we want to use it. The subsys device is anyway getting removed. Update prototype of ->remove_dev() to make its return type as void. Fix all usage sites as well. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- arch/sh/kernel/cpu/sh4/sq.c | 3 +-- arch/tile/kernel/sysfs.c | 11 ++++------- arch/x86/kernel/cpu/microcode/core.c | 5 ++--- drivers/cpufreq/cpufreq.c | 12 +++++------- drivers/net/rionet.c | 4 +--- include/linux/device.h | 2 +- 6 files changed, 14 insertions(+), 23 deletions(-) (limited to 'include/linux/device.h') diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 0a47bd3e7bee..4ca78ed71ad2 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c @@ -355,13 +355,12 @@ static int sq_dev_add(struct device *dev, struct subsys_interface *sif) return error; } -static int sq_dev_remove(struct device *dev, struct subsys_interface *sif) +static void sq_dev_remove(struct device *dev, struct subsys_interface *sif) { unsigned int cpu = dev->id; struct kobject *kobj = sq_kobject[cpu]; kobject_put(kobj); - return 0; } static struct subsys_interface sq_interface = { diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c index a3ed12f8f83b..825867c53853 100644 --- a/arch/tile/kernel/sysfs.c +++ b/arch/tile/kernel/sysfs.c @@ -198,16 +198,13 @@ static int hv_stats_device_add(struct device *dev, struct subsys_interface *sif) return err; } -static int hv_stats_device_remove(struct device *dev, - struct subsys_interface *sif) +static void hv_stats_device_remove(struct device *dev, + struct subsys_interface *sif) { int cpu = dev->id; - if (!cpu_online(cpu)) - return 0; - - sysfs_remove_file(&dev->kobj, &dev_attr_hv_stats.attr); - return 0; + if (cpu_online(cpu)) + sysfs_remove_file(&dev->kobj, &dev_attr_hv_stats.attr); } diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 6236a54a63f4..3c986390058a 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -377,17 +377,16 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) return err; } -static int mc_device_remove(struct device *dev, struct subsys_interface *sif) +static void mc_device_remove(struct device *dev, struct subsys_interface *sif) { int cpu = dev->id; if (!cpu_online(cpu)) - return 0; + return; pr_debug("CPU%d removed\n", cpu); microcode_fini_cpu(cpu); sysfs_remove_group(&dev->kobj, &mc_attr_group); - return 0; } static struct subsys_interface mc_cpu_interface = { diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 26063afb3eba..6da25c10bdfd 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1518,7 +1518,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev, * * Removes the cpufreq interface for a CPU device. */ -static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) +static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) { unsigned int cpu = dev->id; int ret; @@ -1533,7 +1533,7 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) struct cpumask mask; if (!policy) - return 0; + return; cpumask_copy(&mask, policy->related_cpus); cpumask_clear_cpu(cpu, &mask); @@ -1544,19 +1544,17 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) */ if (cpumask_intersects(&mask, cpu_present_mask)) { remove_cpu_dev_symlink(policy, cpu); - return 0; + return; } cpufreq_policy_free(policy, true); - return 0; + return; } ret = __cpufreq_remove_dev_prepare(dev, sif); if (!ret) - ret = __cpufreq_remove_dev_finish(dev, sif); - - return ret; + __cpufreq_remove_dev_finish(dev, sif); } static void handle_update(struct work_struct *work) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index dac7a0d9bb46..01f08a7751f7 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -396,7 +396,7 @@ static int rionet_close(struct net_device *ndev) return 0; } -static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif) +static void rionet_remove_dev(struct device *dev, struct subsys_interface *sif) { struct rio_dev *rdev = to_rio_dev(dev); unsigned char netid = rdev->net->hport->id; @@ -416,8 +416,6 @@ static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif) } } } - - return 0; } static void rionet_get_drvinfo(struct net_device *ndev, diff --git a/include/linux/device.h b/include/linux/device.h index a2b4ea70a946..1225f98e9240 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -341,7 +341,7 @@ struct subsys_interface { struct bus_type *subsys; struct list_head node; int (*add_dev)(struct device *dev, struct subsys_interface *sif); - int (*remove_dev)(struct device *dev, struct subsys_interface *sif); + void (*remove_dev)(struct device *dev, struct subsys_interface *sif); }; int subsys_interface_register(struct subsys_interface *sif); -- cgit v1.2.3