diff options
author | Johannes Thumshirn <johannes.thumshirn@men.de> | 2014-04-24 08:35:25 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-27 20:38:11 -0400 |
commit | 4ec65b77c64504e178d75aaba6ac96f68837416c (patch) | |
tree | 573c968f454b51209892fd0ede0c1d56d63f5649 | |
parent | 2e1c951f5da23faaa60224628f44b100ab212d46 (diff) |
mcb: Add support for shared PCI IRQs
Add support for shared PCI IRQs to mcb and mcb-pci.
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@men.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/mcb/mcb-core.c | 20 | ||||
-rw-r--r-- | drivers/mcb/mcb-pci.c | 17 | ||||
-rw-r--r-- | include/linux/mcb.h | 6 |
3 files changed, 36 insertions, 7 deletions
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c index bbe12932d404..9018ab83517a 100644 --- a/drivers/mcb/mcb-core.c +++ b/drivers/mcb/mcb-core.c | |||
@@ -183,14 +183,14 @@ EXPORT_SYMBOL_GPL(mcb_device_register); | |||
183 | * | 183 | * |
184 | * Allocate a new @mcb_bus. | 184 | * Allocate a new @mcb_bus. |
185 | */ | 185 | */ |
186 | struct mcb_bus *mcb_alloc_bus(void) | 186 | struct mcb_bus *mcb_alloc_bus(struct device *carrier) |
187 | { | 187 | { |
188 | struct mcb_bus *bus; | 188 | struct mcb_bus *bus; |
189 | int bus_nr; | 189 | int bus_nr; |
190 | 190 | ||
191 | bus = kzalloc(sizeof(struct mcb_bus), GFP_KERNEL); | 191 | bus = kzalloc(sizeof(struct mcb_bus), GFP_KERNEL); |
192 | if (!bus) | 192 | if (!bus) |
193 | return NULL; | 193 | return ERR_PTR(-ENOMEM); |
194 | 194 | ||
195 | bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL); | 195 | bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL); |
196 | if (bus_nr < 0) { | 196 | if (bus_nr < 0) { |
@@ -200,7 +200,7 @@ struct mcb_bus *mcb_alloc_bus(void) | |||
200 | 200 | ||
201 | INIT_LIST_HEAD(&bus->children); | 201 | INIT_LIST_HEAD(&bus->children); |
202 | bus->bus_nr = bus_nr; | 202 | bus->bus_nr = bus_nr; |
203 | 203 | bus->carrier = carrier; | |
204 | return bus; | 204 | return bus; |
205 | } | 205 | } |
206 | EXPORT_SYMBOL_GPL(mcb_alloc_bus); | 206 | EXPORT_SYMBOL_GPL(mcb_alloc_bus); |
@@ -378,6 +378,13 @@ void mcb_release_mem(struct resource *mem) | |||
378 | } | 378 | } |
379 | EXPORT_SYMBOL_GPL(mcb_release_mem); | 379 | EXPORT_SYMBOL_GPL(mcb_release_mem); |
380 | 380 | ||
381 | static int __mcb_get_irq(struct mcb_device *dev) | ||
382 | { | ||
383 | struct resource *irq = &dev->irq; | ||
384 | |||
385 | return irq->start; | ||
386 | } | ||
387 | |||
381 | /** | 388 | /** |
382 | * mcb_get_irq() - Get device's IRQ number | 389 | * mcb_get_irq() - Get device's IRQ number |
383 | * @dev: The @mcb_device the IRQ is for | 390 | * @dev: The @mcb_device the IRQ is for |
@@ -386,9 +393,12 @@ EXPORT_SYMBOL_GPL(mcb_release_mem); | |||
386 | */ | 393 | */ |
387 | int mcb_get_irq(struct mcb_device *dev) | 394 | int mcb_get_irq(struct mcb_device *dev) |
388 | { | 395 | { |
389 | struct resource *irq = &dev->irq; | 396 | struct mcb_bus *bus = dev->bus; |
390 | 397 | ||
391 | return irq->start; | 398 | if (bus->get_irq) |
399 | return bus->get_irq(dev); | ||
400 | |||
401 | return __mcb_get_irq(dev); | ||
392 | } | 402 | } |
393 | EXPORT_SYMBOL_GPL(mcb_get_irq); | 403 | EXPORT_SYMBOL_GPL(mcb_get_irq); |
394 | 404 | ||
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c index 99c742cbfb5b..b59181965643 100644 --- a/drivers/mcb/mcb-pci.c +++ b/drivers/mcb/mcb-pci.c | |||
@@ -20,6 +20,15 @@ struct priv { | |||
20 | void __iomem *base; | 20 | void __iomem *base; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | static int mcb_pci_get_irq(struct mcb_device *mdev) | ||
24 | { | ||
25 | struct mcb_bus *mbus = mdev->bus; | ||
26 | struct device *dev = mbus->carrier; | ||
27 | struct pci_dev *pdev = to_pci_dev(dev); | ||
28 | |||
29 | return pdev->irq; | ||
30 | } | ||
31 | |||
23 | static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 32 | static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
24 | { | 33 | { |
25 | struct priv *priv; | 34 | struct priv *priv; |
@@ -67,7 +76,13 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
67 | 76 | ||
68 | pci_set_drvdata(pdev, priv); | 77 | pci_set_drvdata(pdev, priv); |
69 | 78 | ||
70 | priv->bus = mcb_alloc_bus(); | 79 | priv->bus = mcb_alloc_bus(&pdev->dev); |
80 | if (IS_ERR(priv->bus)) { | ||
81 | ret = PTR_ERR(priv->bus); | ||
82 | goto err_drvdata; | ||
83 | } | ||
84 | |||
85 | priv->bus->get_irq = mcb_pci_get_irq; | ||
71 | 86 | ||
72 | ret = chameleon_parse_cells(priv->bus, mapbase, priv->base); | 87 | ret = chameleon_parse_cells(priv->bus, mapbase, priv->base); |
73 | if (ret < 0) | 88 | if (ret < 0) |
diff --git a/include/linux/mcb.h b/include/linux/mcb.h index 2db284d14064..ed06e15a36aa 100644 --- a/include/linux/mcb.h +++ b/include/linux/mcb.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/irqreturn.h> | 16 | #include <linux/irqreturn.h> |
17 | 17 | ||
18 | struct mcb_driver; | 18 | struct mcb_driver; |
19 | struct mcb_device; | ||
19 | 20 | ||
20 | /** | 21 | /** |
21 | * struct mcb_bus - MEN Chameleon Bus | 22 | * struct mcb_bus - MEN Chameleon Bus |
@@ -23,11 +24,14 @@ struct mcb_driver; | |||
23 | * @dev: pointer to carrier device | 24 | * @dev: pointer to carrier device |
24 | * @children: the child busses | 25 | * @children: the child busses |
25 | * @bus_nr: mcb bus number | 26 | * @bus_nr: mcb bus number |
27 | * @get_irq: callback to get IRQ number | ||
26 | */ | 28 | */ |
27 | struct mcb_bus { | 29 | struct mcb_bus { |
28 | struct list_head children; | 30 | struct list_head children; |
29 | struct device dev; | 31 | struct device dev; |
32 | struct device *carrier; | ||
30 | int bus_nr; | 33 | int bus_nr; |
34 | int (*get_irq)(struct mcb_device *dev); | ||
31 | }; | 35 | }; |
32 | #define to_mcb_bus(b) container_of((b), struct mcb_bus, dev) | 36 | #define to_mcb_bus(b) container_of((b), struct mcb_bus, dev) |
33 | 37 | ||
@@ -105,7 +109,7 @@ extern void mcb_unregister_driver(struct mcb_driver *driver); | |||
105 | module_driver(__mcb_driver, mcb_register_driver, mcb_unregister_driver); | 109 | module_driver(__mcb_driver, mcb_register_driver, mcb_unregister_driver); |
106 | extern void mcb_bus_add_devices(const struct mcb_bus *bus); | 110 | extern void mcb_bus_add_devices(const struct mcb_bus *bus); |
107 | extern int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev); | 111 | extern int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev); |
108 | extern struct mcb_bus *mcb_alloc_bus(void); | 112 | extern struct mcb_bus *mcb_alloc_bus(struct device *carrier); |
109 | extern struct mcb_bus *mcb_bus_get(struct mcb_bus *bus); | 113 | extern struct mcb_bus *mcb_bus_get(struct mcb_bus *bus); |
110 | extern void mcb_bus_put(struct mcb_bus *bus); | 114 | extern void mcb_bus_put(struct mcb_bus *bus); |
111 | extern struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus); | 115 | extern struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus); |