typhoon: Need non-vmalloc memory to DMA firmware to the card.
authorDavid S. Miller <davem@davemloft.net>
Mon, 2 Mar 2009 04:24:32 +0000 (20:24 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 2 Mar 2009 04:24:32 +0000 (20:24 -0800)
request_firmware() gives vmalloc'd memory, which is not suitable
for pci_map_single() and friends.

Use a kmalloc()'d copy of the firmware for this DMA operation.

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/typhoon.c

index cd3283f766d984afb273c7e5f709e97867cbee46..ec2541c8c22935dbf874f1bf9d054dca7a26a447 100644 (file)
@@ -1347,6 +1347,7 @@ typhoon_init_rings(struct typhoon *tp)
 }
 
 static const struct firmware *typhoon_fw;
+static u8 *typhoon_fw_image;
 
 static int
 typhoon_request_firmware(struct typhoon *tp)
@@ -1367,12 +1368,22 @@ typhoon_request_firmware(struct typhoon *tp)
            memcmp(typhoon_fw->data, "TYPHOON", 8)) {
                printk(KERN_ERR "%s: Invalid firmware image\n",
                       tp->name);
-               release_firmware(typhoon_fw);
-               typhoon_fw = NULL;
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_err;
+       }
+
+       typhoon_fw_image = kmalloc(typhoon_fw->size, GFP_KERNEL);
+       if (!typhoon_fw_image) {
+               err = -ENOMEM;
+               goto out_err;
        }
 
        return 0;
+
+out_err:
+       release_firmware(typhoon_fw);
+       typhoon_fw = NULL;
+       return err;
 }
 
 static int
@@ -1394,11 +1405,11 @@ typhoon_download_firmware(struct typhoon *tp)
        int i;
        int err;
 
-       image_data = typhoon_fw->data;
+       image_data = typhoon_fw_image;
        fHdr = (struct typhoon_file_header *) image_data;
 
        err = -ENOMEM;
-       image_dma = pci_map_single(pdev, (u8 *) typhoon_fw->data,
+       image_dma = pci_map_single(pdev, (u8 *) image_data,
                                   typhoon_fw->size, PCI_DMA_TODEVICE);
        if (pci_dma_mapping_error(pdev, image_dma)) {
                printk(KERN_ERR "%s: no DMA mem for firmware\n", tp->name);
@@ -1469,7 +1480,7 @@ typhoon_download_firmware(struct typhoon *tp)
                iowrite32(load_addr,
                          ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
                iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
-               iowrite32(image_dma + (image_data - typhoon_fw->data),
+               iowrite32(image_dma + (image_data - typhoon_fw_image),
                          ioaddr + TYPHOON_REG_BOOT_DATA_LO);
                typhoon_post_pci_writes(ioaddr);
                iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
@@ -2639,8 +2650,10 @@ typhoon_init(void)
 static void __exit
 typhoon_cleanup(void)
 {
-       if (typhoon_fw)
+       if (typhoon_fw) {
+               kfree(typhoon_fw_image);
                release_firmware(typhoon_fw);
+       }
        pci_unregister_driver(&typhoon_driver);
 }