diff options
author | Johannes Thumshirn <johannes.thumshirn@men.de> | 2014-12-16 04:09:20 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-01-09 18:46:37 -0500 |
commit | 7b7c54914f73966976893747ee8e2ca58166a627 (patch) | |
tree | 867344f8e283b38127c957f0ee4b3247f7e54687 | |
parent | 7e4a90cb2efecb3799bde9280efbf7f4af8f891b (diff) |
mcb: mcb-pci: Only remap the 1st 0x200 bytes of BAR 0
Currently it is not possible to have a kernel with built-in MCB attached
devices. This results out of the fact that mcb-pci requests PCI BAR 0, then
parses the chameleon table and calls the driver's probe function before
releasing BAR 0 again. When building the kernel with modules this is not a
problem (and therefore it wasn't detected by my tests yet).
A solution is to only remap the 1st 0x200 bytes of a Chameleon PCI device.
0x200 bytes is the maximum size of a Chameleon v2 Table.
Also this patch stops disabling the PCI device on successful registration of MCB
devices.
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@men.de>
Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/mcb/mcb-internal.h | 1 | ||||
-rw-r--r-- | drivers/mcb/mcb-pci.c | 27 |
2 files changed, 19 insertions, 9 deletions
diff --git a/drivers/mcb/mcb-internal.h b/drivers/mcb/mcb-internal.h index f956ef26c0ce..fb7493dcfb79 100644 --- a/drivers/mcb/mcb-internal.h +++ b/drivers/mcb/mcb-internal.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45 | 7 | #define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45 |
8 | #define CHAMELEON_FILENAME_LEN 12 | 8 | #define CHAMELEON_FILENAME_LEN 12 |
9 | #define CHAMELEONV2_MAGIC 0xabce | 9 | #define CHAMELEONV2_MAGIC 0xabce |
10 | #define CHAM_HEADER_SIZE 0x200 | ||
10 | 11 | ||
11 | enum chameleon_descriptor_type { | 12 | enum chameleon_descriptor_type { |
12 | CHAMELEON_DTYPE_GENERAL = 0x0, | 13 | CHAMELEON_DTYPE_GENERAL = 0x0, |
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c index b59181965643..5e1bd5db02c8 100644 --- a/drivers/mcb/mcb-pci.c +++ b/drivers/mcb/mcb-pci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | struct priv { | 18 | struct priv { |
19 | struct mcb_bus *bus; | 19 | struct mcb_bus *bus; |
20 | phys_addr_t mapbase; | ||
20 | void __iomem *base; | 21 | void __iomem *base; |
21 | }; | 22 | }; |
22 | 23 | ||
@@ -31,8 +32,8 @@ static int mcb_pci_get_irq(struct mcb_device *mdev) | |||
31 | 32 | ||
32 | static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 33 | static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
33 | { | 34 | { |
35 | struct resource *res; | ||
34 | struct priv *priv; | 36 | struct priv *priv; |
35 | phys_addr_t mapbase; | ||
36 | int ret; | 37 | int ret; |
37 | int num_cells; | 38 | int num_cells; |
38 | unsigned long flags; | 39 | unsigned long flags; |
@@ -47,19 +48,21 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
47 | return -ENODEV; | 48 | return -ENODEV; |
48 | } | 49 | } |
49 | 50 | ||
50 | mapbase = pci_resource_start(pdev, 0); | 51 | priv->mapbase = pci_resource_start(pdev, 0); |
51 | if (!mapbase) { | 52 | if (!priv->mapbase) { |
52 | dev_err(&pdev->dev, "No PCI resource\n"); | 53 | dev_err(&pdev->dev, "No PCI resource\n"); |
53 | goto err_start; | 54 | goto err_start; |
54 | } | 55 | } |
55 | 56 | ||
56 | ret = pci_request_region(pdev, 0, KBUILD_MODNAME); | 57 | res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE, |
57 | if (ret) { | 58 | KBUILD_MODNAME); |
58 | dev_err(&pdev->dev, "Failed to request PCI BARs\n"); | 59 | if (IS_ERR(res)) { |
60 | dev_err(&pdev->dev, "Failed to request PCI memory\n"); | ||
61 | ret = PTR_ERR(res); | ||
59 | goto err_start; | 62 | goto err_start; |
60 | } | 63 | } |
61 | 64 | ||
62 | priv->base = pci_iomap(pdev, 0, 0); | 65 | priv->base = ioremap(priv->mapbase, CHAM_HEADER_SIZE); |
63 | if (!priv->base) { | 66 | if (!priv->base) { |
64 | dev_err(&pdev->dev, "Cannot ioremap\n"); | 67 | dev_err(&pdev->dev, "Cannot ioremap\n"); |
65 | ret = -ENOMEM; | 68 | ret = -ENOMEM; |
@@ -84,7 +87,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
84 | 87 | ||
85 | priv->bus->get_irq = mcb_pci_get_irq; | 88 | priv->bus->get_irq = mcb_pci_get_irq; |
86 | 89 | ||
87 | ret = chameleon_parse_cells(priv->bus, mapbase, priv->base); | 90 | ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base); |
88 | if (ret < 0) | 91 | if (ret < 0) |
89 | goto err_drvdata; | 92 | goto err_drvdata; |
90 | num_cells = ret; | 93 | num_cells = ret; |
@@ -93,8 +96,10 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
93 | 96 | ||
94 | mcb_bus_add_devices(priv->bus); | 97 | mcb_bus_add_devices(priv->bus); |
95 | 98 | ||
99 | return 0; | ||
100 | |||
96 | err_drvdata: | 101 | err_drvdata: |
97 | pci_iounmap(pdev, priv->base); | 102 | iounmap(priv->base); |
98 | err_ioremap: | 103 | err_ioremap: |
99 | pci_release_region(pdev, 0); | 104 | pci_release_region(pdev, 0); |
100 | err_start: | 105 | err_start: |
@@ -107,6 +112,10 @@ static void mcb_pci_remove(struct pci_dev *pdev) | |||
107 | struct priv *priv = pci_get_drvdata(pdev); | 112 | struct priv *priv = pci_get_drvdata(pdev); |
108 | 113 | ||
109 | mcb_release_bus(priv->bus); | 114 | mcb_release_bus(priv->bus); |
115 | |||
116 | iounmap(priv->base); | ||
117 | release_region(priv->mapbase, CHAM_HEADER_SIZE); | ||
118 | pci_disable_device(pdev); | ||
110 | } | 119 | } |
111 | 120 | ||
112 | static const struct pci_device_id mcb_pci_tbl[] = { | 121 | static const struct pci_device_id mcb_pci_tbl[] = { |