typhoon: Need non-vmalloc memory to DMA firmware to the card.
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>
This commit is contained in:
@@ -1347,6 +1347,7 @@ typhoon_init_rings(struct typhoon *tp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct firmware *typhoon_fw;
|
static const struct firmware *typhoon_fw;
|
||||||
|
static u8 *typhoon_fw_image;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
typhoon_request_firmware(struct typhoon *tp)
|
typhoon_request_firmware(struct typhoon *tp)
|
||||||
@@ -1367,12 +1368,22 @@ typhoon_request_firmware(struct typhoon *tp)
|
|||||||
memcmp(typhoon_fw->data, "TYPHOON", 8)) {
|
memcmp(typhoon_fw->data, "TYPHOON", 8)) {
|
||||||
printk(KERN_ERR "%s: Invalid firmware image\n",
|
printk(KERN_ERR "%s: Invalid firmware image\n",
|
||||||
tp->name);
|
tp->name);
|
||||||
release_firmware(typhoon_fw);
|
err = -EINVAL;
|
||||||
typhoon_fw = NULL;
|
goto out_err;
|
||||||
return -EINVAL;
|
}
|
||||||
|
|
||||||
|
typhoon_fw_image = kmalloc(typhoon_fw->size, GFP_KERNEL);
|
||||||
|
if (!typhoon_fw_image) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
release_firmware(typhoon_fw);
|
||||||
|
typhoon_fw = NULL;
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1394,11 +1405,11 @@ typhoon_download_firmware(struct typhoon *tp)
|
|||||||
int i;
|
int i;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
image_data = typhoon_fw->data;
|
image_data = typhoon_fw_image;
|
||||||
fHdr = (struct typhoon_file_header *) image_data;
|
fHdr = (struct typhoon_file_header *) image_data;
|
||||||
|
|
||||||
err = -ENOMEM;
|
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);
|
typhoon_fw->size, PCI_DMA_TODEVICE);
|
||||||
if (pci_dma_mapping_error(pdev, image_dma)) {
|
if (pci_dma_mapping_error(pdev, image_dma)) {
|
||||||
printk(KERN_ERR "%s: no DMA mem for firmware\n", tp->name);
|
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,
|
iowrite32(load_addr,
|
||||||
ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
|
ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
|
||||||
iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
|
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);
|
ioaddr + TYPHOON_REG_BOOT_DATA_LO);
|
||||||
typhoon_post_pci_writes(ioaddr);
|
typhoon_post_pci_writes(ioaddr);
|
||||||
iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
|
iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
|
||||||
@@ -2639,8 +2650,10 @@ typhoon_init(void)
|
|||||||
static void __exit
|
static void __exit
|
||||||
typhoon_cleanup(void)
|
typhoon_cleanup(void)
|
||||||
{
|
{
|
||||||
if (typhoon_fw)
|
if (typhoon_fw) {
|
||||||
|
kfree(typhoon_fw_image);
|
||||||
release_firmware(typhoon_fw);
|
release_firmware(typhoon_fw);
|
||||||
|
}
|
||||||
pci_unregister_driver(&typhoon_driver);
|
pci_unregister_driver(&typhoon_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user