Here's a patch against
<svn://svn.debian.org/svn/kernel/dists/trunk/linux-2.6>.
Still largely untested, I'm afraid.

Ben.

Index: debian/patches/debian/dfsg/files-1
===================================================================
--- debian/patches/debian/dfsg/files-1  (revision 12898)
+++ debian/patches/debian/dfsg/files-1  (working copy)
@@ -23,6 +23,12 @@
 rm firmware/vicam
 rm firmware/yamaha
 
+rm drivers/gpu/drm/mga/mga_ucode.h
+
+unifdef drivers/gpu/drm/r128/r128_cce.c -UREMOVE_DFSG
+
+rm drivers/gpu/drm/radeon/radeon_microcode.h
+
 rm drivers/net/appletalk/cops.c
 rm drivers/net/appletalk/cops.h
 rm drivers/net/appletalk/cops_ffdrv.h
@@ -38,10 +44,18 @@
 
 rm drivers/net/myri_code.h
 
+rm drivers/net/tehuti_fw.h
+
 rm drivers/net/tokenring/3c359.c
 rm drivers/net/tokenring/3c359.h
 rm drivers/net/tokenring/3c359_microcode.h
 
+rm drivers/net/typhoon-firmware.h
+
+rm drivers/scsi/ql1040_fw.h
+rm drivers/scsi/ql12160_fw.h
+rm drivers/scsi/ql1280_fw.h
+
 rm drivers/scsi/qlogicpti_asm.c
 
 rm sound/pci/cs46xx/cs46xx_image.h
Index: debian/patches/series/1~experimental.1
===================================================================
--- debian/patches/series/1~experimental.1      (revision 12898)
+++ debian/patches/series/1~experimental.1      (working copy)
@@ -8,6 +8,12 @@
 
 #+ debian/dfsg/drivers-net-bnx2-request_firmware-1.patch
 #+ features/all/drivers-net-acenic-firmwar_request.patch
++ features/all/drivers-gpu-drm-mga-request_firmware.patch
++ features/all/drivers-gpu-drm-r128-request_firmware.patch
++ features/all/drivers-gpu-drm-radeon-request_firmware.patch
++ features/all/drivers-net-tehuti-request_firmware.patch
++ features/all/drivers-net-typhoon-request_firmware.patch
++ features/all/drivers-scsi-qla1280-request_firmware.patch
 + features/all/export-gfs2-locking-symbols.patch
 + features/all/export-unionfs-symbols.patch
 
Index: debian/patches/series/orig-0
===================================================================
--- debian/patches/series/orig-0        (revision 12898)
+++ debian/patches/series/orig-0        (working copy)
@@ -1,10 +1,16 @@
-X debian/dfsg/files-1
++ debian/dfsg/drivers-gpu-drm-mga-disable.patch
++ debian/dfsg/drivers-gpu-drm-r128-disable.patch
++ debian/dfsg/drivers-gpu-drm-radeon-disable.patch
 + debian/dfsg/drivers-net-bnx2-disable.patch
 + debian/dfsg/drivers-net-bnx2x-disable.patch
 + debian/dfsg/drivers-net-appletalk-cops.patch
 + debian/dfsg/drivers-net-hamradio-yam.patch
 + debian/dfsg/drivers-net-myri.patch
++ debian/dfsg/drivers-net-tehuti-disable.patch
 + debian/dfsg/drivers-net-tokenring-3c359-smctr.patch
++ debian/dfsg/drivers-net-typhoon-disable.patch
++ debian/dfsg/drivers-scsi-qla1280-disable.patch
 + debian/dfsg/drivers-scsi-qlogicpti.patch
 + debian/dfsg/firmware-cleanup.patch
 + debian/dfsg/sound-pci.patch
+X debian/dfsg/files-1
Index: debian/patches/features/all/drivers-net-typhoon-request_firmware.patch
===================================================================
--- debian/patches/features/all/drivers-net-typhoon-request_firmware.patch      
(revision 0)
+++ debian/patches/features/all/drivers-net-typhoon-request_firmware.patch      
(revision 0)
@@ -0,0 +1,167 @@
+From 06fdc64b4d38bde05d41dfa9dfef78473ffae8cd Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <[email protected]>
+Date: Sat, 18 Oct 2008 16:04:33 +0100
+Subject: [PATCH 21/24] typhoon: use request_firmware
+
+Based on patch by Jaswinder Singh <[email protected]>,
+with additional validation of the firmware size.
+
+made following const as we treat firmware data as const:
+        struct typhoon_file_header *fHdr
+        struct typhoon_section_header *sHdr
+        u8 *image_data
+---
+ drivers/net/Kconfig   |    2 +-
+ drivers/net/typhoon.c |   74 +++++++++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 63 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 4bddcbd..29dfc1d 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -732,7 +732,7 @@ config VORTEX
+ config TYPHOON
+       tristate "3cr990 series \"Typhoon\" support"
+       depends on NET_VENDOR_3COM && PCI
+-      depends on BROKEN
++      select FW_LOADER
+       select CRC32
+       ---help---
+         This option enables driver support for the 3cr990 series of cards:
+diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
+index 734ce09..4cacb62 100644
+--- a/drivers/net/typhoon.c
++++ b/drivers/net/typhoon.c
+@@ -129,16 +129,18 @@ static const int multicast_filter_limit = 32;
+ #include <asm/uaccess.h>
+ #include <linux/in6.h>
+ #include <linux/dma-mapping.h>
++#include <linux/firmware.h>
+ 
+ #include "typhoon.h"
+-#include "typhoon-firmware.h"
+ 
+ static char version[] __devinitdata =
+     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
++#define FIRMWARE_NAME         "3com/typhoon.bin"
+ MODULE_AUTHOR("David Dillow <[email protected]>");
+ MODULE_VERSION(DRV_MODULE_VERSION);
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FIRMWARE_NAME);
+ MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
+ MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
+                              "the buffer given back to the NIC. Default "
+@@ -1344,14 +1346,60 @@ typhoon_init_rings(struct typhoon *tp)
+       tp->txHiRing.lastRead = 0;
+ }
+ 
++static const struct firmware *typhoon_fw;
++
++static int typhoon_init_firmware(struct typhoon *tp)
++{
++      const struct typhoon_file_header *fHdr;
++      const struct typhoon_section_header *sHdr;
++      u32 numSections;
++      u32 len;
++      int i;
++      int err;
++
++      err = request_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev);
++      if (err) {
++              printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
++                     tp->name, FIRMWARE_NAME);
++              return err;
++      }
++
++      fHdr = (const struct typhoon_file_header *) typhoon_fw->data;
++      if (typhoon_fw->size < sizeof(*fHdr) || memcmp(fHdr->tag, "TYPHOON", 
8)) {
++              err = -EINVAL;
++              goto out;
++      }
++      numSections = le32_to_cpup(&fHdr->numSections);
++      len = sizeof(*fHdr);
++      for (i = 0; i < numSections; i++) {
++              if (typhoon_fw->size < len + sizeof(*sHdr)) {
++                      err = -EINVAL;
++                      break;
++              }
++              sHdr = (const struct typhoon_section_header *)
++                      (typhoon_fw->data + len);
++              len += sizeof(*sHdr) + le32_to_cpup(&sHdr->len);
++      }
++      if (typhoon_fw->size != len)
++              err = -EINVAL;
++
++out:
++      if (err) {
++              printk(KERN_ERR "%s: Invalid firmware image \"%s\"\n",
++                     tp->name, FIRMWARE_NAME);
++              release_firmware(typhoon_fw);
++      }
++      return err;
++}
++
+ static int
+ typhoon_download_firmware(struct typhoon *tp)
+ {
+       void __iomem *ioaddr = tp->ioaddr;
+       struct pci_dev *pdev = tp->pdev;
+-      struct typhoon_file_header *fHdr;
+-      struct typhoon_section_header *sHdr;
+-      u8 *image_data;
++      const struct typhoon_file_header *fHdr;
++      const struct typhoon_section_header *sHdr;
++      const u8 *image_data;
+       void *dpage;
+       dma_addr_t dpage_dma;
+       __sum16 csum;
+@@ -1366,13 +1414,8 @@ typhoon_download_firmware(struct typhoon *tp)
+       int err;
+ 
+       err = -EINVAL;
+-      fHdr = (struct typhoon_file_header *) typhoon_firmware_image;
+-      image_data = (u8 *) fHdr;
+-
+-      if(memcmp(fHdr->tag, "TYPHOON", 8)) {
+-              printk(KERN_ERR "%s: Invalid firmware image!\n", tp->name);
+-              goto err_out;
+-      }
++      fHdr = (const struct typhoon_file_header *) typhoon_fw->data;
++      image_data = typhoon_fw->data;
+ 
+       /* Cannot just map the firmware image using pci_map_single() as
+        * the firmware is part of the kernel/module image, so we allocate
+@@ -1425,7 +1468,7 @@ typhoon_download_firmware(struct typhoon *tp)
+        * we don't need a typhoon_post_pci_writes() after it.
+        */
+       for(i = 0; i < numSections; i++) {
+-              sHdr = (struct typhoon_section_header *) image_data;
++              sHdr = (const struct typhoon_section_header *) image_data;
+               image_data += sizeof(struct typhoon_section_header);
+               load_addr = le32_to_cpu(sHdr->startAddr);
+               section_len = le32_to_cpu(sHdr->len);
+@@ -2441,6 +2484,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct 
pci_device_id *ent)
+        */
+       tp->name = pci_name(pdev);
+ 
++      err = typhoon_init_firmware(tp);
++      if (err)
++              goto error_out_reset;
++
+       typhoon_init_interface(tp);
+       typhoon_init_rings(tp);
+ 
+@@ -2591,6 +2638,9 @@ typhoon_remove_one(struct pci_dev *pdev)
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       typhoon_reset(tp->ioaddr, NoWait);
++
++      release_firmware(typhoon_fw);
++
+       pci_iounmap(pdev, tp->ioaddr);
+       pci_free_consistent(pdev, sizeof(struct typhoon_shared),
+                           tp->shared, tp->shared_dma);
+-- 
+1.6.1.3
+
Index: debian/patches/features/all/drivers-gpu-drm-r128-request_firmware.patch
===================================================================
--- debian/patches/features/all/drivers-gpu-drm-r128-request_firmware.patch     
(revision 0)
+++ debian/patches/features/all/drivers-gpu-drm-r128-request_firmware.patch     
(revision 0)
@@ -0,0 +1,139 @@
+From 870bed4eea53fbaeb8f585fb9b89d23d9d8c2436 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <[email protected]>
+Date: Sat, 18 Oct 2008 02:27:57 +0100
+Subject: [PATCH 03/24] r128: Use request_firmware() to load CCE microcode
+
+Firmware blob looks like this:
+    __be32 datah
+    __be32 datal
+
+Compile-tested only.
+---
+ drivers/gpu/drm/Kconfig         |    2 +-
+ drivers/gpu/drm/r128/r128_cce.c |   54 ++++++++++++++++++++++++++++++++++----
+ 2 files changed, 49 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index 725f244..e6f4401 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -26,7 +26,7 @@ config DRM_TDFX
+ config DRM_R128
+       tristate "ATI Rage 128"
+       depends on DRM && PCI
+-      depends on BROKEN
++      select FW_LOADER
+       help
+         Choose this option if you have an ATI Rage 128 graphics card.  If M
+         is selected, the module will be called r128.  AGP support for
+diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
+index a9ee89a..63bed21 100644
+--- a/drivers/gpu/drm/r128/r128_cce.c
++++ b/drivers/gpu/drm/r128/r128_cce.c
+@@ -29,6 +29,9 @@
+  *    Gareth Hughes <[email protected]>
+  */
+ 
++#include <linux/firmware.h>
++#include <linux/platform_device.h>
++
+ #include "drmP.h"
+ #include "drm.h"
+ #include "r128_drm.h"
+@@ -36,6 +39,9 @@
+ 
+ #define R128_FIFO_DEBUG               0
+ 
++#define FIRMWARE_NAME         "r128/r128_cce.bin"
++
++MODULE_FIRMWARE(FIRMWARE_NAME);
+ 
+ static int R128_READ_PLL(struct drm_device * dev, int addr)
+ {
+@@ -132,20 +138,50 @@ static int r128_do_wait_for_idle(drm_r128_private_t * 
dev_priv)
+  */
+ 
+ /* Load the microcode for the CCE */
+-static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
++static int r128_cce_load_microcode(drm_r128_private_t *dev_priv)
+ {
+-      int i;
++      struct platform_device *pdev;
++      const struct firmware *fw;
++      const __be32 *fw_data;
++      int rc, i;
+ 
+       DRM_DEBUG("\n");
+ 
++      pdev = platform_device_register_simple("r128_cce", 0, NULL, 0);
++      if (IS_ERR(pdev)) {
++              printk(KERN_ERR "r128_cce: Failed to register firmware\n");
++              return PTR_ERR(pdev);
++      }
++      rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
++      platform_device_unregister(pdev);
++      if (rc) {
++              printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n",
++                     FIRMWARE_NAME);
++              return rc;
++      }
++
++      if (fw->size != 256 * 8) {
++              printk(KERN_ERR
++                     "r128_cce: Bogus length %zu in firmware \"%s\"\n",
++                     fw->size, FIRMWARE_NAME);
++              rc = -EINVAL;
++              goto out_release;
++      }
++
+       r128_do_wait_for_idle(dev_priv);
+ 
++      fw_data = (const __be32 *)fw->data;
+       R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
+       for (i = 0; i < 256; i++) {
+-              R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
++              R128_WRITE(R128_PM4_MICROCODE_DATAH,
++                         be32_to_cpup(&fw_data[i * 2]));
+               R128_WRITE(R128_PM4_MICROCODE_DATAL,
+-                         r128_cce_microcode[i * 2 + 1]);
++                         be32_to_cpup(&fw_data[i * 2 + 1]));
+       }
++
++out_release:
++      release_firmware(fw);
++      return rc;
+ }
+ 
+ /* Flush any pending commands to the CCE.  This should only be used just
+@@ -306,6 +342,7 @@ static void r128_cce_init_ring_buffer(struct drm_device * 
dev,
+ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
+ {
+       drm_r128_private_t *dev_priv;
++      int rc;
+ 
+       DRM_DEBUG("\n");
+ 
+@@ -532,13 +569,18 @@ static int r128_do_init_cce(struct drm_device * dev, 
drm_r128_init_t * init)
+ #endif
+ 
+       r128_cce_init_ring_buffer(dev, dev_priv);
+-      r128_cce_load_microcode(dev_priv);
++      rc = r128_cce_load_microcode(dev_priv);
+ 
+       dev->dev_private = (void *)dev_priv;
+ 
+       r128_do_engine_reset(dev);
+ 
+-      return 0;
++      if (rc) {
++              DRM_ERROR("Failed to load firmware!\n");
++              r128_do_cleanup_cce(dev);
++      }
++
++      return rc;
+ }
+ 
+ int r128_do_cleanup_cce(struct drm_device * dev)
+-- 
+1.6.1.3
+
Index: debian/patches/features/all/drivers-net-tehuti-request_firmware.patch
===================================================================
--- debian/patches/features/all/drivers-net-tehuti-request_firmware.patch       
(revision 0)
+++ debian/patches/features/all/drivers-net-tehuti-request_firmware.patch       
(revision 0)
@@ -0,0 +1,167 @@
+From dfa8d7b01bfc5707c706ca1479c9c426c8454b06 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <[email protected]>
+Date: Wed, 15 Oct 2008 02:47:03 +0100
+Subject: [PATCH 15/24] tehuti: use request_firmware
+
+Based on patch by Jaswinder Singh <[email protected]>
+
+Firmware blob is little endian.
+
+Removed bdx_firmware_endianess() as firmware blob is already little endian
+---
+ drivers/net/Kconfig  |    2 +-
+ drivers/net/tehuti.c |   43 ++++++++++++++++++++++++++++++-------------
+ drivers/net/tehuti.h |    1 +
+ 3 files changed, 32 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 7fdc18f..ded4b06 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -2557,7 +2557,7 @@ config MLX4_DEBUG
+ config TEHUTI
+       tristate "Tehuti Networks 10G Ethernet"
+       depends on PCI
+-      depends on BROKEN
++      select FW_LOADER
+       help
+         Tehuti Networks 10G Ethernet NIC
+ 
+diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
+index 91f9054..69fc129 100644
+--- a/drivers/net/tehuti.c
++++ b/drivers/net/tehuti.c
+@@ -63,7 +63,10 @@
+  */
+ 
+ #include "tehuti.h"
+-#include "tehuti_fw.h"
++
++/* Firmware section */
++#define FIRMWARE_BDX  "tehuti/bdx.bin"
++static const struct firmware *bdx_fw;
+ 
+ static struct pci_device_id __devinitdata bdx_pci_tbl[] = {
+       {0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -80,7 +83,8 @@ static void bdx_tx_cleanup(struct bdx_priv *priv);
+ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int 
budget);
+ 
+ /* Definitions needed by FW loading */
+-static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int 
size);
++static void bdx_tx_push_desc_safe(struct bdx_priv *priv,
++                                const void *data, int size);
+ 
+ /* Definitions needed by hw_start */
+ static int bdx_tx_init(struct bdx_priv *priv);
+@@ -309,6 +313,19 @@ static int bdx_poll(struct napi_struct *napi, int budget)
+       return work_done;
+ }
+ 
++/* bdx_fw_init - intialize firmware  */
++static int bdx_fw_init(struct pci_dev *pdev)
++{
++      int err;
++
++      err = request_firmware(&bdx_fw, FIRMWARE_BDX, &pdev->dev);
++      if (err)
++              printk(KERN_ERR "tehuti: Failed to load firmware \"%s\"\n",
++                     FIRMWARE_BDX);
++
++      return err;
++}
++
+ /* bdx_fw_load - loads firmware to NIC
+  * @priv - NIC private structure
+  * Firmware is loaded via TXD fifo, so it must be initialized first.
+@@ -324,7 +341,7 @@ static int bdx_fw_load(struct bdx_priv *priv)
+       ENTER;
+       master = READ_REG(priv, regINIT_SEMAPHORE);
+       if (!READ_REG(priv, regINIT_STATUS) && master) {
+-              bdx_tx_push_desc_safe(priv, s_firmLoad, sizeof(s_firmLoad));
++              bdx_tx_push_desc_safe(priv, bdx_fw->data, bdx_fw->size);
+               mdelay(100);
+       }
+       for (i = 0; i < 200; i++) {
+@@ -618,13 +635,6 @@ err:
+       RET(rc);
+ }
+ 
+-static void __init bdx_firmware_endianess(void)
+-{
+-      int i;
+-      for (i = 0; i < ARRAY_SIZE(s_firmLoad); i++)
+-              s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);
+-}
+-
+ static int bdx_range_check(struct bdx_priv *priv, u32 offset)
+ {
+       return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
+@@ -1831,7 +1841,7 @@ static void bdx_tx_free(struct bdx_priv *priv)
+  *    of the caller. Neither does it check that data size is smaller then
+  *    fifo size.
+  */
+-static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size)
++static void bdx_tx_push_desc(struct bdx_priv *priv, const void *data, int 
size)
+ {
+       struct txd_fifo *f = &priv->txd_fifo0;
+       int i = f->m.memsz - f->m.wptr;
+@@ -1858,7 +1868,8 @@ static void bdx_tx_push_desc(struct bdx_priv *priv, void 
*data, int size)
+  * NOTE: this func does check for available space and, if neccessary, waits 
for
+  *   NIC to read existing data before writing new one.
+  */
+-static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
++static void bdx_tx_push_desc_safe(struct bdx_priv *priv,
++                                const void *data, int size)
+ {
+       int timer = 0;
+       ENTER;
+@@ -1987,6 +1998,10 @@ bdx_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
+               DBG("HW does not support MSI\n");
+ #endif
+ 
++      /* Initialize firmware */
++      if (bdx_fw_init(pdev))
++              goto err_out_iomap;
++
+     /************** netdev **************/
+       for (port = 0; port < nic->port_num; port++) {
+               if (!(ndev = alloc_etherdev(sizeof(struct bdx_priv)))) {
+@@ -2468,6 +2483,8 @@ static void __devexit bdx_remove(struct pci_dev *pdev)
+               pci_disable_msi(pdev);
+ #endif
+ 
++      release_firmware(bdx_fw);
++
+       iounmap(nic->regs);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+@@ -2498,7 +2515,6 @@ static void __init print_driver_id(void)
+ static int __init bdx_module_init(void)
+ {
+       ENTER;
+-      bdx_firmware_endianess();
+       init_txd_sizes();
+       print_driver_id();
+       RET(pci_register_driver(&bdx_pci_driver));
+@@ -2516,5 +2532,6 @@ static void __exit bdx_module_exit(void)
+ module_exit(bdx_module_exit);
+ 
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FIRMWARE_BDX);
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(BDX_DRV_DESC);
+diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
+index efaf84d..dec67e0 100644
+--- a/drivers/net/tehuti.h
++++ b/drivers/net/tehuti.h
+@@ -29,6 +29,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/interrupt.h>
+ #include <linux/vmalloc.h>
++#include <linux/firmware.h>
+ #include <asm/byteorder.h>
+ 
+ /* Compile Time Switches */
+-- 
+1.6.1.3
+
Index: debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch
===================================================================
--- debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch     
(revision 0)
+++ debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch     
(revision 0)
@@ -0,0 +1,296 @@
+From 8217f31fa9232dad67b0d596e9f7e6678ad44616 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <[email protected]>
+Date: Sat, 18 Oct 2008 16:43:31 +0100
+Subject: [PATCH 24/24] qla1280: use request_firmware
+
+Based on patch by Jaswinder Singh <[email protected]>
+and David Woodhouse <[email protected]>
+
+Firmware blob is little endian looks like this...
+       unsigned char  Version1
+       unsigned char  Version2
+       unsigned char  Version3
+       unsigned char  Padding
+       unsigned short start_address
+       unsigned short data
+---
+ drivers/scsi/Kconfig   |    2 +-
+ drivers/scsi/qla1280.c |  116 +++++++++++++++++++++++++++++++-----------------
+ drivers/scsi/qla1280.h |    6 +++
+ 3 files changed, 82 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 3d97641..0fca0d2 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -1328,7 +1328,7 @@ config SCSI_QLOGIC_FAS
+ config SCSI_QLOGIC_1280
+       tristate "Qlogic QLA 1240/1x80/1x160 SCSI support"
+       depends on PCI && SCSI
+-      depends on BROKEN
++      select FW_LOADER
+       help
+         Say Y if you have a QLogic ISP1240/1x80/1x160 SCSI host adapter.
+ 
+diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
+index b6cd12b..5536676 100644
+--- a/drivers/scsi/qla1280.c
++++ b/drivers/scsi/qla1280.c
+@@ -348,6 +348,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/dma-mapping.h>
++#include <linux/firmware.h>
+ 
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -384,11 +385,7 @@
+ #define       MEMORY_MAPPED_IO        1
+ #endif
+ 
+-#define UNIQUE_FW_NAME
+ #include "qla1280.h"
+-#include "ql12160_fw.h"               /* ISP RISC codes */
+-#include "ql1280_fw.h"
+-#include "ql1040_fw.h"
+ 
+ #ifndef BITS_PER_LONG
+ #error "BITS_PER_LONG not defined!"
+@@ -541,10 +538,7 @@ __setup("qla1280=", qla1280_setup);
+ struct qla_boards {
+       unsigned char name[9];  /* Board ID String */
+       int numPorts;           /* Number of SCSI ports */
+-      unsigned short *fwcode; /* pointer to FW array         */
+-      unsigned short *fwlen;  /* number of words in array    */
+-      unsigned short *fwstart;        /* start address for F/W       */
+-      unsigned char *fwver;   /* Ptr to F/W version array    */
++      char *fwname;           /* firmware name        */
+ };
+ 
+ /* NOTE: the last argument in each entry is used to index ql1280_board_tbl */
+@@ -567,19 +561,13 @@ MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
+ 
+ static struct qla_boards ql1280_board_tbl[] = {
+       /* Name ,  Number of ports, FW details */
+-      {"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01,
+-       &fw12160i_addr01, &fw12160i_version_str[0]},
+-      {"QLA1040", 1, &risc_code01[0], &risc_code_length01,
+-       &risc_code_addr01, &firmware_version[0]},
+-      {"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01,
+-       &fw1280ei_addr01, &fw1280ei_version_str[0]},
+-      {"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01,
+-       &fw1280ei_addr01, &fw1280ei_version_str[0]},
+-      {"QLA1280", 2, &fw1280ei_code01[0], &fw1280ei_length01,
+-       &fw1280ei_addr01, &fw1280ei_version_str[0]},
+-      {"QLA10160", 1, &fw12160i_code01[0], &fw12160i_length01,
+-       &fw12160i_addr01, &fw12160i_version_str[0]},
+-      {"        ", 0}
++      {"QLA12160",    2, "qlogic/12160.bin"},
++      {"QLA1040",     1, "qlogic/1040.bin"},
++      {"QLA1080",     1, "qlogic/1280.bin"},
++      {"QLA1240",     2, "qlogic/1280.bin"},
++      {"QLA1280",     2, "qlogic/1280.bin"},
++      {"QLA10160",    1, "qlogic/12160.bin"},
++      {"        ",    0, "   "},
+ };
+ 
+ static int qla1280_verbose = 1;
+@@ -704,7 +692,7 @@ qla1280_info(struct Scsi_Host *host)
+       sprintf (bp,
+                "QLogic %s PCI to SCSI Host Adapter\n"
+                "       Firmware version: %2d.%02d.%02d, Driver version %s",
+-               &bdp->name[0], bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
++               &bdp->name[0], ha->fwver1, ha->fwver2, ha->fwver3,
+                QLA1280_VERSION);
+       return bp;
+ }
+@@ -1648,36 +1636,60 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
+ static int
+ qla1280_load_firmware_pio(struct scsi_qla_host *ha)
+ {
+-      uint16_t risc_address, *risc_code_address, risc_code_size;
++      const struct firmware *fw;
++      const __le16 *fw_data;
++      uint16_t risc_address, risc_code_size;
+       uint16_t mb[MAILBOX_REGISTER_COUNT], i;
+       int err;
+ 
++      err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
++                             &ha->pdev->dev);
++      if (err) {
++              printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
++                     ql1280_board_tbl[ha->devnum].fwname, err);
++              return err;
++      }
++      if ((fw->size % 2) || (fw->size < 6)) {
++              printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
++                     fw->size, ql1280_board_tbl[ha->devnum].fwname);
++              err = -EINVAL;
++              goto out;
++      }
++      ha->fwver1 = fw->data[0];
++      ha->fwver2 = fw->data[1];
++      ha->fwver3 = fw->data[2];
++      fw_data = (const __le16 *)&fw->data[0];
++      ha->fwstart = __le16_to_cpu(fw_data[2]);
++
+       /* Load RISC code. */
+-      risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+-      risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+-      risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
++      risc_address = ha->fwstart;
++      fw_data = (const __le16 *)&fw->data[4];
++      risc_code_size = (fw->size - 6) / 2;
+ 
+       for (i = 0; i < risc_code_size; i++) {
+               mb[0] = MBC_WRITE_RAM_WORD;
+               mb[1] = risc_address + i;
+-              mb[2] = risc_code_address[i];
++              mb[2] = __le16_to_cpu(fw_data[i]);
+ 
+               err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
+               if (err) {
+                       printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
+                                       ha->host_no);
+-                      return err;
++                      goto out;
+               }
+       }
+-
+-      return 0;
++out:
++      release_firmware(fw);
++      return err;
+ }
+ 
+ #define DUMP_IT_BACK 0                /* for debug of RISC loading */
+ static int
+ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ {
+-      uint16_t risc_address, *risc_code_address, risc_code_size;
++      const struct firmware *fw;
++      const __le16 *fw_data;
++      uint16_t risc_address, risc_code_size;
+       uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
+       int err = 0, num, i;
+ #if DUMP_IT_BACK
+@@ -1689,10 +1701,29 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+               return -ENOMEM;
+ #endif
+ 
++      err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
++                             &ha->pdev->dev);
++      if (err) {
++              printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
++                     ql1280_board_tbl[ha->devnum].fwname, err);
++              return err;
++      }
++      if ((fw->size % 2) || (fw->size < 6)) {
++              printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
++                     fw->size, ql1280_board_tbl[ha->devnum].fwname);
++              err = -EINVAL;
++              goto out;
++      }
++      ha->fwver1 = fw->data[0];
++      ha->fwver2 = fw->data[1];
++      ha->fwver3 = fw->data[2];
++      fw_data = (const __le16 *)&fw->data[0];
++      ha->fwstart = __le16_to_cpu(fw_data[2]);
++
+       /* Load RISC code. */
+-      risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+-      risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+-      risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
++      risc_address = ha->fwstart;
++      fw_data = (const __le16 *)&fw->data[4];
++      risc_code_size = (fw->size - 6) / 2;
+ 
+       dprintk(1, "%s: DMA RISC code (%i) words\n",
+                       __func__, risc_code_size);
+@@ -1708,10 +1739,9 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ 
+               dprintk(2, "qla1280_setup_chip:  loading risc @ =(0x%p),"
+                       "%d,%d(0x%x)\n",
+-                      risc_code_address, cnt, num, risc_address);
++                      fw_data, cnt, num, risc_address);
+               for(i = 0; i < cnt; i++)
+-                      ((__le16 *)ha->request_ring)[i] =
+-                              cpu_to_le16(risc_code_address[i]);
++                      ((__le16 *)ha->request_ring)[i] = fw_data[i];
+ 
+               mb[0] = MBC_LOAD_RAM;
+               mb[1] = risc_address;
+@@ -1763,7 +1793,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ #endif
+               risc_address += cnt;
+               risc_code_size = risc_code_size - cnt;
+-              risc_code_address = risc_code_address + cnt;
++              fw_data = fw_data + cnt;
+               num++;
+       }
+ 
+@@ -1771,6 +1801,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ #if DUMP_IT_BACK
+       pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
+ #endif
++      release_firmware(fw);
+       return err;
+ }
+ 
+@@ -1786,7 +1817,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
+       /* Verify checksum of loaded RISC code. */
+       mb[0] = MBC_VERIFY_CHECKSUM;
+       /* mb[1] = ql12_risc_code_addr01; */
+-      mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
++      mb[1] = ha->fwstart;
+       err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+       if (err) {
+               printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", 
ha->host_no);
+@@ -1796,7 +1827,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
+       /* Start firmware execution. */
+       dprintk(1, "%s: start firmware running.\n", __func__);
+       mb[0] = MBC_EXECUTE_FIRMWARE;
+-      mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
++      mb[1] = ha->fwstart;
+       err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+       if (err) {
+               printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
+@@ -1821,7 +1852,7 @@ qla1280_load_firmware(struct scsi_qla_host *ha)
+       if (err)
+               goto out;
+       err = qla1280_start_firmware(ha);
+- out:
++out:
+       return err;
+ }
+ 
+@@ -4451,6 +4482,9 @@ module_exit(qla1280_exit);
+ MODULE_AUTHOR("Qlogic & Jes Sorensen");
+ MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE("qlogic/1040.bin");
++MODULE_FIRMWARE("qlogic/1280.bin");
++MODULE_FIRMWARE("qlogic/12160.bin");
+ MODULE_VERSION(QLA1280_VERSION);
+ 
+ /*
+diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
+index ff2c363..d7c44b8 100644
+--- a/drivers/scsi/qla1280.h
++++ b/drivers/scsi/qla1280.h
+@@ -1069,6 +1069,12 @@ struct scsi_qla_host {
+ 
+       struct nvram nvram;
+       int nvram_valid;
++
++      /* Firmware Info */
++      unsigned short fwstart; /* start address for F/W   */
++      unsigned char fwver1;   /* F/W version first char  */
++      unsigned char fwver2;   /* F/W version second char */
++      unsigned char fwver3;   /* F/W version third char  */
+ };
+ 
+ #endif /* _QLA1280_H */
+-- 
+1.6.1.3
+
Index: debian/patches/features/all/drivers-gpu-drm-mga-request_firmware.patch
===================================================================
--- debian/patches/features/all/drivers-gpu-drm-mga-request_firmware.patch      
(revision 0)
+++ debian/patches/features/all/drivers-gpu-drm-mga-request_firmware.patch      
(revision 0)
@@ -0,0 +1,295 @@
+From 0175b4bdefff22f837203fd47f568c4647f24a4f Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <[email protected]>
+Date: Sat, 18 Oct 2008 04:28:10 +0100
+Subject: [PATCH 18/24] mga: Use request_firmware() to load microcode
+
+Image format is IHEX, one record for each pipe in order (record
+addresses are ignored).
+
+Compile-tested only.
+---
+ drivers/gpu/drm/Kconfig        |    2 +-
+ drivers/gpu/drm/mga/mga_dma.c  |    4 +-
+ drivers/gpu/drm/mga/mga_drv.h  |    1 -
+ drivers/gpu/drm/mga/mga_warp.c |  180 +++++++++++++++++-----------------------
+ include/drm/mga_drm.h          |    2 +-
+ 5 files changed, 82 insertions(+), 107 deletions(-)
+
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index 853814c..a61d10a 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -81,7 +81,7 @@ endchoice
+ config DRM_MGA
+       tristate "Matrox g200/g400"
+       depends on DRM
+-      depends on BROKEN
++      select FW_LOADER
+       help
+         Choose this option if you have a Matrox G200, G400 or G450 graphics
+         card.  If M is selected, the module will be called mga.  AGP
+diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
+index b49c5ff..7e0b106 100644
+--- a/drivers/gpu/drm/mga/mga_dma.c
++++ b/drivers/gpu/drm/mga/mga_dma.c
+@@ -447,7 +447,7 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * 
dev,
+ {
+       drm_mga_private_t *const dev_priv =
+           (drm_mga_private_t *) dev->dev_private;
+-      unsigned int warp_size = mga_warp_microcode_size(dev_priv);
++      unsigned int warp_size = MGA_WARP_UCODE_SIZE;
+       int err;
+       unsigned offset;
+       const unsigned secondary_size = dma_bs->secondary_bin_count
+@@ -622,7 +622,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * 
dev,
+ {
+       drm_mga_private_t *const dev_priv =
+           (drm_mga_private_t *) dev->dev_private;
+-      unsigned int warp_size = mga_warp_microcode_size(dev_priv);
++      unsigned int warp_size = MGA_WARP_UCODE_SIZE;
+       unsigned int primary_size;
+       unsigned int bin_count;
+       int err;
+diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
+index 88257c2..9e40226 100644
+--- a/drivers/gpu/drm/mga/mga_drv.h
++++ b/drivers/gpu/drm/mga/mga_drv.h
+@@ -177,7 +177,6 @@ extern void mga_do_dma_wrap_end(drm_mga_private_t * 
dev_priv);
+ extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
+ 
+                               /* mga_warp.c */
+-extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * 
dev_priv);
+ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+ extern int mga_warp_init(drm_mga_private_t * dev_priv);
+ 
+diff --git a/drivers/gpu/drm/mga/mga_warp.c b/drivers/gpu/drm/mga/mga_warp.c
+index 651b93c..9aad484 100644
+--- a/drivers/gpu/drm/mga/mga_warp.c
++++ b/drivers/gpu/drm/mga/mga_warp.c
+@@ -27,132 +27,108 @@
+  *    Gareth Hughes <[email protected]>
+  */
+ 
++#include <linux/firmware.h>
++#include <linux/ihex.h>
++#include <linux/platform_device.h>
++
+ #include "drmP.h"
+ #include "drm.h"
+ #include "mga_drm.h"
+ #include "mga_drv.h"
+-#include "mga_ucode.h"
++
++#define FIRMWARE_G200 "matrox/g200_warp.fw"
++#define FIRMWARE_G400 "matrox/g400_warp.fw"
++
++MODULE_FIRMWARE(FIRMWARE_G200);
++MODULE_FIRMWARE(FIRMWARE_G400);
+ 
+ #define MGA_WARP_CODE_ALIGN           256     /* in bytes */
+ 
+-#define WARP_UCODE_SIZE( which )                                      \
+-      ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
+-
+-#define WARP_UCODE_INSTALL( which, where )                            \
+-do {                                                                  \
+-      DRM_DEBUG( " pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase );\
+-      dev_priv->warp_pipe_phys[where] = pcbase;                       \
+-      memcpy( vcbase, which, sizeof(which) );                         \
+-      pcbase += WARP_UCODE_SIZE( which );                             \
+-      vcbase += WARP_UCODE_SIZE( which );                             \
+-} while (0)
+-
+-static const unsigned int mga_warp_g400_microcode_size =
+-    (WARP_UCODE_SIZE(warp_g400_tgz) +
+-     WARP_UCODE_SIZE(warp_g400_tgza) +
+-     WARP_UCODE_SIZE(warp_g400_tgzaf) +
+-     WARP_UCODE_SIZE(warp_g400_tgzf) +
+-     WARP_UCODE_SIZE(warp_g400_tgzs) +
+-     WARP_UCODE_SIZE(warp_g400_tgzsa) +
+-     WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+-     WARP_UCODE_SIZE(warp_g400_tgzsf) +
+-     WARP_UCODE_SIZE(warp_g400_t2gz) +
+-     WARP_UCODE_SIZE(warp_g400_t2gza) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzf) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzs) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
+-
+-static const unsigned int mga_warp_g200_microcode_size =
+-    (WARP_UCODE_SIZE(warp_g200_tgz) +
+-     WARP_UCODE_SIZE(warp_g200_tgza) +
+-     WARP_UCODE_SIZE(warp_g200_tgzaf) +
+-     WARP_UCODE_SIZE(warp_g200_tgzf) +
+-     WARP_UCODE_SIZE(warp_g200_tgzs) +
+-     WARP_UCODE_SIZE(warp_g200_tgzsa) +
+-     WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
+-
+-unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
++#define WARP_UCODE_SIZE(size)         ALIGN(size, MGA_WARP_CODE_ALIGN)
++
++int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+ {
++      unsigned char *vcbase = dev_priv->warp->handle;
++      unsigned long pcbase = dev_priv->warp->offset;
++      const char *firmware_name;
++      struct platform_device *pdev;
++      const struct firmware *fw = NULL;
++      const struct ihex_binrec *rec;
++      unsigned int size;
++      int n_pipes, where;
++      int rc = 0;
++
+       switch (dev_priv->chipset) {
+       case MGA_CARD_TYPE_G400:
+       case MGA_CARD_TYPE_G550:
+-              return PAGE_ALIGN(mga_warp_g400_microcode_size);
++              firmware_name = FIRMWARE_G400;
++              n_pipes = MGA_MAX_G400_PIPES;
++              break;
+       case MGA_CARD_TYPE_G200:
+-              return PAGE_ALIGN(mga_warp_g200_microcode_size);
++              firmware_name = FIRMWARE_G200;
++              n_pipes = MGA_MAX_G200_PIPES;
++              break;
+       default:
+-              return 0;
++              return -EINVAL;
+       }
+-}
+-
+-static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
+-{
+-      unsigned char *vcbase = dev_priv->warp->handle;
+-      unsigned long pcbase = dev_priv->warp->offset;
+-
+-      memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+-
+-      WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
+-      WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
+-      WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
+-      WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
+-      WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
+-      WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
+-      WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
+-      WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
+-
+-      WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
+-      WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
+-      WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
+-      WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
+-      WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
+-      WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
+-      WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
+-      WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
+-
+-      return 0;
+-}
+-
+-static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
+-{
+-      unsigned char *vcbase = dev_priv->warp->handle;
+-      unsigned long pcbase = dev_priv->warp->offset;
+-
+-      memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+-
+-      WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
+-      WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
+-      WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
+-      WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
+-      WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
+-      WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
+-      WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
+-      WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
+ 
+-      return 0;
+-}
++      pdev = platform_device_register_simple("mga_warp", 0, NULL, 0);
++      if (IS_ERR(pdev)) {
++              DRM_ERROR("mga: Failed to register microcode\n");
++              return PTR_ERR(pdev);
++      }
++      rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev);
++      platform_device_unregister(pdev);
++      if (rc) {
++              DRM_ERROR("mga: Failed to load microcode \"%s\"\n",
++                        firmware_name);
++              return rc;
++      }
+ 
+-int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+-{
+-      const unsigned int size = mga_warp_microcode_size(dev_priv);
++      size = 0;
++      where = 0;
++      for (rec = (const struct ihex_binrec *)fw->data;
++           rec;
++           rec = ihex_next_binrec(rec)) {
++              size += WARP_UCODE_SIZE(be16_to_cpu(rec->len));
++              where++;
++      }
+ 
++      if (where != n_pipes) {
++              DRM_ERROR("mga: Invalid microcode \"%s\"\n", firmware_name);
++              rc = -EINVAL;
++              goto out;
++      }
++      size = PAGE_ALIGN(size);
+       DRM_DEBUG("MGA ucode size = %d bytes\n", size);
+       if (size > dev_priv->warp->size) {
+               DRM_ERROR("microcode too large! (%u > %lu)\n",
+                         size, dev_priv->warp->size);
+-              return -ENOMEM;
++              rc = -ENOMEM;
++              goto out;
+       }
+ 
+-      switch (dev_priv->chipset) {
+-      case MGA_CARD_TYPE_G400:
+-      case MGA_CARD_TYPE_G550:
+-              return mga_warp_install_g400_microcode(dev_priv);
+-      case MGA_CARD_TYPE_G200:
+-              return mga_warp_install_g200_microcode(dev_priv);
+-      default:
+-              return -EINVAL;
++      memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
++
++      where = 0;
++      for (rec = (const struct ihex_binrec *)fw->data;
++           rec;
++           rec = ihex_next_binrec(rec)) {
++              unsigned int src_size, dst_size;
++
++              DRM_DEBUG(" pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase);
++              dev_priv->warp_pipe_phys[where] = pcbase;
++              src_size = be16_to_cpu(rec->len);
++              dst_size = WARP_UCODE_SIZE(src_size);
++              memcpy(vcbase, rec->data, src_size);
++              pcbase += dst_size;
++              vcbase += dst_size;
++              where++;
+       }
++
++out:
++      release_firmware(fw);
++      return rc;
+ }
+ 
+ #define WMISC_EXPECTED                (MGA_WUCODECACHE_ENABLE | 
MGA_WMASTER_ENABLE)
+diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h
+index 944b50a..0b8fc27 100644
+--- a/include/drm/mga_drm.h
++++ b/include/drm/mga_drm.h
+@@ -69,7 +69,7 @@
+ #define MGA_MAX_G200_PIPES    8       /* no multitex */
+ #define MGA_MAX_G400_PIPES    16
+ #define MGA_MAX_WARP_PIPES    MGA_MAX_G400_PIPES
+-#define MGA_WARP_UCODE_SIZE   32768   /* in bytes */
++#define MGA_WARP_UCODE_SIZE   40960   /* in bytes */
+ 
+ #define MGA_CARD_TYPE_G200    1
+ #define MGA_CARD_TYPE_G400    2
+-- 
+1.6.1.3
+
Index: debian/patches/features/all/drivers-gpu-drm-radeon-request_firmware.patch
===================================================================
--- debian/patches/features/all/drivers-gpu-drm-radeon-request_firmware.patch   
(revision 0)
+++ debian/patches/features/all/drivers-gpu-drm-radeon-request_firmware.patch   
(revision 0)
@@ -0,0 +1,239 @@
+From 3e3f2f1f9514969b9df1b64a9a12a7a5a1aa7550 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <[email protected]>
+Date: Wed, 15 Oct 2008 01:29:35 +0100
+Subject: [PATCH 06/24] radeon: Use request_firmware() to load CP microcode
+
+Tested on Radeon 7500 (RV200) with and without firmware installed.
+---
+ drivers/gpu/drm/Kconfig             |    2 +-
+ drivers/gpu/drm/radeon/radeon_cp.c  |  115 +++++++++++++++++++++++------------
+ drivers/gpu/drm/radeon/radeon_drv.h |    6 ++
+ 3 files changed, 83 insertions(+), 40 deletions(-)
+
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index a93d249..09ed655 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -35,7 +35,7 @@ config DRM_R128
+ config DRM_RADEON
+       tristate "ATI Radeon"
+       depends on DRM && PCI
+-      depends on BROKEN
++      select FW_LOADER
+       help
+         Choose this option if you have an ATI Radeon graphics card.  There
+         are both PCI and AGP versions.  You don't need to choose this to
+diff --git a/drivers/gpu/drm/radeon/radeon_cp.c 
b/drivers/gpu/drm/radeon/radeon_cp.c
+index dcebb4b..a460149 100644
+--- a/drivers/gpu/drm/radeon/radeon_cp.c
++++ b/drivers/gpu/drm/radeon/radeon_cp.c
+@@ -35,10 +35,23 @@
+ #include "radeon_drv.h"
+ #include "r300_reg.h"
+ 
+-#include "radeon_microcode.h"
+-
+ #define RADEON_FIFO_DEBUG     0
+ 
++/* Firmware Names */
++#define FIRMWARE_R100         "radeon/R100_cp.bin"
++#define FIRMWARE_R200         "radeon/R200_cp.bin"
++#define FIRMWARE_R300         "radeon/R300_cp.bin"
++#define FIRMWARE_R420         "radeon/R420_cp.bin"
++#define FIRMWARE_RS690                "radeon/RS690_cp.bin"
++#define FIRMWARE_R520         "radeon/R520_cp.bin"
++
++MODULE_FIRMWARE(FIRMWARE_R100);
++MODULE_FIRMWARE(FIRMWARE_R200);
++MODULE_FIRMWARE(FIRMWARE_R300);
++MODULE_FIRMWARE(FIRMWARE_R420);
++MODULE_FIRMWARE(FIRMWARE_RS690);
++MODULE_FIRMWARE(FIRMWARE_R520);
++
+ static int radeon_do_cleanup_cp(struct drm_device * dev);
+ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
+ 
+@@ -318,37 +331,34 @@ static void radeon_init_pipes(drm_radeon_private_t 
*dev_priv)
+  */
+ 
+ /* Load the microcode for the CP */
+-static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
++static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
+ {
+-      int i;
++      struct platform_device *pdev;
++      const char *fw_name = NULL;
++      int err;
++
+       DRM_DEBUG("\n");
+ 
+-      radeon_do_wait_for_idle(dev_priv);
++      pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
++      err = IS_ERR(pdev);
++      if (err) {
++              printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
++              return -EINVAL;
++      }
+ 
+-      RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
+               DRM_INFO("Loading R100 Microcode\n");
+-              for (i = 0; i < 256; i++) {
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-                                   R100_cp_microcode[i][1]);
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-                                   R100_cp_microcode[i][0]);
+-              }
++              fw_name = FIRMWARE_R100;
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
+               DRM_INFO("Loading R200 Microcode\n");
+-              for (i = 0; i < 256; i++) {
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-                                   R200_cp_microcode[i][1]);
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-                                   R200_cp_microcode[i][0]);
+-              }
++              fw_name = FIRMWARE_R200;
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
+@@ -356,31 +366,16 @@ static void 
radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+               DRM_INFO("Loading R300 Microcode\n");
+-              for (i = 0; i < 256; i++) {
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-                                   R300_cp_microcode[i][1]);
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-                                   R300_cp_microcode[i][0]);
+-              }
++              fw_name = FIRMWARE_R300;
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
+               DRM_INFO("Loading R400 Microcode\n");
+-              for (i = 0; i < 256; i++) {
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-                                   R420_cp_microcode[i][1]);
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-                                   R420_cp_microcode[i][0]);
+-              }
++              fw_name = FIRMWARE_R420;
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+               DRM_INFO("Loading RS690/RS740 Microcode\n");
+-              for (i = 0; i < 256; i++) {
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-                                   RS690_cp_microcode[i][1]);
+-                      RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-                                   RS690_cp_microcode[i][0]);
+-              }
++              fw_name = FIRMWARE_RS690;
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
+@@ -388,11 +383,41 @@ static void 
radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
+               DRM_INFO("Loading R500 Microcode\n");
+-              for (i = 0; i < 256; i++) {
++              fw_name = FIRMWARE_R520;
++      }
++
++      err = request_firmware(&dev_priv->fw, fw_name, &pdev->dev);
++      platform_device_unregister(pdev);
++      if (err) {
++              printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n",
++                     fw_name);
++      } else if (dev_priv->fw->size % 8) {
++              printk(KERN_ERR
++                     "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
++                     dev_priv->fw->size, fw_name);
++              err = -EINVAL;
++              release_firmware(dev_priv->fw);
++              dev_priv->fw = NULL;
++      }
++      return err;
++}
++
++static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
++{
++      const __be32 *fw_data;
++      int i, size;
++
++      radeon_do_wait_for_idle(dev_priv);
++
++      if (dev_priv->fw) {
++              size = dev_priv->fw->size / 4;
++              fw_data = (const __be32 *)&dev_priv->fw->data[0];
++              RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
++              for (i = 0; i < size; i += 2) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-                                   R520_cp_microcode[i][1]);
++                                   be32_to_cpup(&fw_data[i]));
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-                                   R520_cp_microcode[i][0]);
++                                   be32_to_cpup(&fw_data[i + 1]));
+               }
+       }
+ }
+@@ -1216,6 +1241,14 @@ static int radeon_do_init_cp(struct drm_device * dev, 
drm_radeon_init_t * init)
+               radeon_set_pcigart(dev_priv, 1);
+       }
+ 
++      if (!dev_priv->fw) {
++              int err = radeon_cp_init_microcode(dev_priv);
++              if (err) {
++                      DRM_ERROR("Failed to load firmware!\n");
++                      radeon_do_cleanup_cp(dev);
++                      return err;
++              }
++      }
+       radeon_cp_load_microcode(dev_priv);
+       radeon_cp_init_ring_buffer(dev, dev_priv);
+ 
+@@ -1442,6 +1475,10 @@ void radeon_do_release(struct drm_device * dev)
+ 
+               /* deallocate kernel resources */
+               radeon_do_cleanup_cp(dev);
++              if (dev_priv->fw) {
++                      release_firmware(dev_priv->fw);
++                      dev_priv->fw = NULL;
++              }
+       }
+ }
+ 
+diff --git a/drivers/gpu/drm/radeon/radeon_drv.h 
b/drivers/gpu/drm/radeon/radeon_drv.h
+index 3bbb871..51984d7 100644
+--- a/drivers/gpu/drm/radeon/radeon_drv.h
++++ b/drivers/gpu/drm/radeon/radeon_drv.h
+@@ -31,6 +31,9 @@
+ #ifndef __RADEON_DRV_H__
+ #define __RADEON_DRV_H__
+ 
++#include <linux/firmware.h>
++#include <linux/platform_device.h>
++
+ /* General customization:
+  */
+ 
+@@ -317,6 +320,9 @@ typedef struct drm_radeon_private {
+       int num_gb_pipes;
+       int track_flush;
+       drm_local_map_t *mmio;
++
++      /* firmware */
++      const struct firmware *fw;
+ } drm_radeon_private_t;
+ 
+ typedef struct drm_radeon_buf_priv {
+-- 
+1.6.1.3
+
Index: debian/changelog
===================================================================
--- debian/changelog    (revision 12898)
+++ debian/changelog    (working copy)
@@ -17,7 +17,16 @@
     RADIO_TEA5764, SND_HDA_CODEC_INTELHDMI, RT2860, RT2870, RTL8187SE.
   * topconfig enable SND_HDA_HWDEP for sound debugging purpose.
 
- -- maximilian attems <[email protected]>  Thu, 19 Feb 2009 13:25:20 +0100
+  [ Ben Hutchings ]
+  * Remove firmware from drivers and make them use request_firmware():
+    - mga (closes: #502666)
+    - qla1280 (closes: #502667)
+    - r128 (closes: #494007)
+    - radeon (closes: #494009)
+    - tehuti (closes: #501153)
+    - typhoon (closes: #502669)
+  
+ -- Ben Hutchings <[email protected]>  Sun, 22 Feb 2009 03:14:38 +0000
 
 linux-2.6 (2.6.28-2) UNRELEASED; urgency=low
 
--- END ---

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to