mcb-pci: Reallocate memory region to avoid memory overlapping
[linux-2.6-microblaze.git] / drivers / mcb / mcb-pci.c
index dc88232..53d9202 100644 (file)
@@ -31,7 +31,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct resource *res;
        struct priv *priv;
-       int ret;
+       int ret, table_size;
        unsigned long flags;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
@@ -90,7 +90,30 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (ret < 0)
                goto out_mcb_bus;
 
-       dev_dbg(&pdev->dev, "Found %d cells\n", ret);
+       table_size = ret;
+
+       if (table_size < CHAM_HEADER_SIZE) {
+               /* Release the previous resources */
+               devm_iounmap(&pdev->dev, priv->base);
+               devm_release_mem_region(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE);
+
+               /* Then, allocate it again with the actual chameleon table size */
+               res = devm_request_mem_region(&pdev->dev, priv->mapbase,
+                                               table_size,
+                                               KBUILD_MODNAME);
+               if (!res) {
+                       dev_err(&pdev->dev, "Failed to request PCI memory\n");
+                       ret = -EBUSY;
+                       goto out_mcb_bus;
+               }
+
+               priv->base = devm_ioremap(&pdev->dev, priv->mapbase, table_size);
+               if (!priv->base) {
+                       dev_err(&pdev->dev, "Cannot ioremap\n");
+                       ret = -ENOMEM;
+                       goto out_mcb_bus;
+               }
+       }
 
        mcb_bus_add_devices(priv->bus);