Skip to content

Commit

Permalink
mcb: mcb-pci: Only remap the 1st 0x200 bytes of BAR 0
Browse files Browse the repository at this point in the history
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 <[email protected]>
Suggested-by: Bjorn Helgaas <[email protected]>
Reviewed-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Johannes Thumshirn authored and gregkh committed Jan 9, 2015
1 parent 7e4a90c commit 7b7c549
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
1 change: 1 addition & 0 deletions drivers/mcb/mcb-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45
#define CHAMELEON_FILENAME_LEN 12
#define CHAMELEONV2_MAGIC 0xabce
#define CHAM_HEADER_SIZE 0x200

enum chameleon_descriptor_type {
CHAMELEON_DTYPE_GENERAL = 0x0,
Expand Down
27 changes: 18 additions & 9 deletions drivers/mcb/mcb-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

struct priv {
struct mcb_bus *bus;
phys_addr_t mapbase;
void __iomem *base;
};

Expand All @@ -31,8 +32,8 @@ static int mcb_pci_get_irq(struct mcb_device *mdev)

static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct resource *res;
struct priv *priv;
phys_addr_t mapbase;
int ret;
int num_cells;
unsigned long flags;
Expand All @@ -47,19 +48,21 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENODEV;
}

mapbase = pci_resource_start(pdev, 0);
if (!mapbase) {
priv->mapbase = pci_resource_start(pdev, 0);
if (!priv->mapbase) {
dev_err(&pdev->dev, "No PCI resource\n");
goto err_start;
}

ret = pci_request_region(pdev, 0, KBUILD_MODNAME);
if (ret) {
dev_err(&pdev->dev, "Failed to request PCI BARs\n");
res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE,
KBUILD_MODNAME);
if (IS_ERR(res)) {
dev_err(&pdev->dev, "Failed to request PCI memory\n");
ret = PTR_ERR(res);
goto err_start;
}

priv->base = pci_iomap(pdev, 0, 0);
priv->base = ioremap(priv->mapbase, CHAM_HEADER_SIZE);
if (!priv->base) {
dev_err(&pdev->dev, "Cannot ioremap\n");
ret = -ENOMEM;
Expand All @@ -84,7 +87,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)

priv->bus->get_irq = mcb_pci_get_irq;

ret = chameleon_parse_cells(priv->bus, mapbase, priv->base);
ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base);
if (ret < 0)
goto err_drvdata;
num_cells = ret;
Expand All @@ -93,8 +96,10 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)

mcb_bus_add_devices(priv->bus);

return 0;

err_drvdata:
pci_iounmap(pdev, priv->base);
iounmap(priv->base);
err_ioremap:
pci_release_region(pdev, 0);
err_start:
Expand All @@ -107,6 +112,10 @@ static void mcb_pci_remove(struct pci_dev *pdev)
struct priv *priv = pci_get_drvdata(pdev);

mcb_release_bus(priv->bus);

iounmap(priv->base);
release_region(priv->mapbase, CHAM_HEADER_SIZE);
pci_disable_device(pdev);
}

static const struct pci_device_id mcb_pci_tbl[] = {
Expand Down

0 comments on commit 7b7c549

Please sign in to comment.