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); |
