On Sun, 2008-10-19 at 03:11 +0100, Ben Hutchings wrote: [...] > My modified firmware-nonfree is at <http://womble.decadent.org.uk/tmp/>. > I'll post a new patch for linux-2.6 tomorrow. Sorry for the delay, I was too tired yesterday to get this finished. The patch against SVN follows. The modified linux-2.6 and firmware-nonfree source packages, and the linux-source-2.6.26 and firmware-* binary packages, can be found in: http://people.debian.org/~benh/firmware-removal/ Please test them if you can. I have only been able to test the radeon changes myself. Index: linux-2.6/debian/changelog =================================================================== --- linux-2.6/debian/changelog (revision 12348) +++ linux-2.6/debian/changelog (working copy) @@ -1,3 +1,22 @@ +linux-2.6 (2.6.26.dfsg.1-10) unstable; urgency=low + + * Remove firmware from drivers and make them use request_firmware(): + - cassini (closes: #498631) + - dabusb (closes: #502663) + - e100 (closes: #494308) + - kaweth (closes: #502665) + - mga (closes: #502666) + - qla1280 (closes: #502667) + - r128 (closes: #494007) + - radeon (closes: #494009) + - starfire (closes: #501152) + - tehuti (closes: #501153) + - typhoon (closes: #502669) + - whiteheat (closes: #502668) + * Add source for dsp56k firmware (closes: #494010) + + -- Ben Hutchings <ben@decadent.org.uk> Sun, 19 Oct 2008 19:59:26 +0100 + linux-2.6 (2.6.26-9) unstable; urgency=low [ Bastian Blank ] Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-cassini-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-net-cassini-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-net-cassini-disable.patch (revision 0) @@ -0,0 +1,45 @@ +From 524d72dfc7d9be55e7b41d21213e555c0b9b5a1a Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 02:01:11 +0100 +Subject: [PATCH] cassini: Add #ifdef markers around firmware and mark broken + +--- + drivers/net/Kconfig | 1 + + drivers/net/cassini.h | 2 ++ + 2 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 0836ea8..9426787 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -584,6 +584,7 @@ config SUNGEM + config CASSINI + tristate "Sun Cassini support" + depends on PCI ++ depends on BROKEN + select CRC32 + help + Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also +diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h +index 552af89..6e8650c 100644 +--- a/drivers/net/cassini.h ++++ b/drivers/net/cassini.h +@@ -2514,6 +2514,7 @@ static cas_hp_inst_t cas_prog_null[] = { {NULL} }; + #define CAS_HP_FIRMWARE cas_prog_null + #endif + ++#ifdef REMOVE_DFSG + /* firmware patch for NS_DP83065 */ + typedef struct cas_saturn_patch { + u16 addr; +@@ -4029,6 +4030,7 @@ cas_saturn_patch_t cas_saturn_patch[] = { + {0x8aca, 0x0039}, { 0x0, 0x0 } + }; + #endif ++#endif /* REMOVE_DFSG */ + + + /* phy types */ +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-media-video-dabusb-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-media-video-dabusb-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-media-video-dabusb-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From a2189e45ec8dfa32e028c7b5d6e6632af2543a7e Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 13:33:37 +0100 +Subject: [PATCH] dabusb: Mark as broken + +--- + drivers/media/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig +index 7a7803b..ec7baaa 100644 +--- a/drivers/media/Kconfig ++++ b/drivers/media/Kconfig +@@ -125,6 +125,7 @@ if DAB + config USB_DABUSB + tristate "DABUSB driver" + depends on USB ++ depends on BROKEN + ---help--- + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux + brought to you by the DAB-Team +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/files-1 =================================================================== --- linux-2.6/debian/patches/debian/dfsg/files-1 (revision 12348) +++ linux-2.6/debian/patches/debian/dfsg/files-1 (working copy) @@ -9,10 +9,18 @@ rm drivers/atm/pca200e_ecd.data rm drivers/atm/sba200e_ecd.data +rm drivers/char/drm/mga_ucode.h + +unifdef drivers/char/drm/r128_cce.c -UREMOVE_DFSG + +rm drivers/char/drm/radeon_microcode.h + rm drivers/char/ip2/fip_firm.h rm drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h +rm drivers/media/video/dabfirmware.h + rm drivers/net/acenic_firmware.h unifdef drivers/net/tg3.c -UREMOVE_DFSG @@ -27,11 +35,19 @@ rm drivers/net/bnx2x_init_values.h +unifdef drivers/net/cassini.h -UREMOVE_DFSG + +unifdef drivers/net/e100.c -UREMOVE_DFSG + rm drivers/net/hamradio/yam1200.h rm drivers/net/hamradio/yam9600.h rm drivers/net/myri_code.h +rm drivers/net/starfire_firmware.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 @@ -40,6 +56,14 @@ rm drivers/net/tokenring/smctr.h rm drivers/net/tokenring/smctr_firmware.h +rm drivers/net/typhoon-firmware.h + +rm drivers/net/usb/kawethfw.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 drivers/usb/misc/emi26.c @@ -62,6 +86,8 @@ rm drivers/usb/serial/keyspan_usa49w_fw.h rm drivers/usb/serial/keyspan_usa49wlc_fw.h +rm drivers/usb/serial/whiteheat_fw.h + rm sound/pci/cs46xx/cs46xx_image.h rm sound/pci/cs46xx/imgs unifdef sound/pci/korg1212/korg1212.c -UCONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-r128-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-r128-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-r128-disable.patch (revision 0) @@ -0,0 +1,45 @@ +From 9122274287bc54d52cee7b79f879fd2715333826 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 00:40:17 +0100 +Subject: [PATCH] r128: Add #ifdef markers around firmware and mark broken + +--- + drivers/char/drm/Kconfig | 1 + + drivers/char/drm/r128_cce.c | 2 ++ + 2 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig +index 610d6fd..8f9c893 100644 +--- a/drivers/char/drm/Kconfig ++++ b/drivers/char/drm/Kconfig +@@ -26,6 +26,7 @@ config DRM_TDFX + config DRM_R128 + tristate "ATI Rage 128" + depends on DRM && PCI ++ depends on BROKEN + 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/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c +index c31afbd..04d8358 100644 +--- a/drivers/char/drm/r128_cce.c ++++ b/drivers/char/drm/r128_cce.c +@@ -36,6 +36,7 @@ + + #define R128_FIFO_DEBUG 0 + ++#ifdef REMOVE_DFSG + /* CCE microcode (from ATI) */ + static u32 r128_cce_microcode[] = { + 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, +@@ -80,6 +81,7 @@ static u32 r128_cce_microcode[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; ++#endif /* REMOVE_DFSG */ + + static int R128_READ_PLL(struct drm_device * dev, int addr) + { +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-scsi-qla1280-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-scsi-qla1280-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-scsi-qla1280-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From dbb422c3adf3bb2e9721203e407d4236daf1f4c3 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:14:43 +0100 +Subject: [PATCH] qla1280: Mark as broken + +--- + drivers/scsi/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig +index 81ccbd7..94831ae 100644 +--- a/drivers/scsi/Kconfig ++++ b/drivers/scsi/Kconfig +@@ -1316,6 +1316,7 @@ config SCSI_QLOGIC_FC_FIRMWARE + config SCSI_QLOGIC_1280 + tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" + depends on PCI && SCSI ++ depends on BROKEN + help + Say Y if you have a QLogic ISP1240/1x80/1x160 SCSI host adapter. + +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-dsp56k-fw-source.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-char-dsp56k-fw-source.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-char-dsp56k-fw-source.patch (revision 0) @@ -0,0 +1,104 @@ +diff --git a/firmware/dsp56k/bootstrap.asm b/firmware/dsp56k/bootstrap.asm +new file mode 100644 +index 0000000..10d8919 +--- /dev/null ++++ b/firmware/dsp56k/bootstrap.asm +@@ -0,0 +1,98 @@ ++; Author: Frederik Noring <noring@nocrew.org> ++; ++; This file is subject to the terms and conditions of the GNU General Public ++; License. See the file COPYING in the main directory of this archive ++; for more details. ++ ++; DSP56k loader ++ ++; Host Interface ++M_BCR EQU $FFFE ; Port A Bus Control Register ++M_PBC EQU $FFE0 ; Port B Control Register ++M_PBDDR EQU $FFE2 ; Port B Data Direction Register ++M_PBD EQU $FFE4 ; Port B Data Register ++M_PCC EQU $FFE1 ; Port C Control Register ++M_PCDDR EQU $FFE3 ; Port C Data Direction Register ++M_PCD EQU $FFE5 ; Port C Data Register ++ ++M_HCR EQU $FFE8 ; Host Control Register ++M_HSR EQU $FFE9 ; Host Status Register ++M_HRX EQU $FFEB ; Host Receive Data Register ++M_HTX EQU $FFEB ; Host Transmit Data Register ++ ++; SSI, Synchronous Serial Interface ++M_RX EQU $FFEF ; Serial Receive Data Register ++M_TX EQU $FFEF ; Serial Transmit Data Register ++M_CRA EQU $FFEC ; SSI Control Register A ++M_CRB EQU $FFED ; SSI Control Register B ++M_SR EQU $FFEE ; SSI Status Register ++M_TSR EQU $FFEE ; SSI Time Slot Register ++ ++; Exception Processing ++M_IPR EQU $FFFF ; Interrupt Priority Register ++ ++ org P:$0 ++start jmp <$40 ++ ++ org P:$40 ++; ; Zero 16384 DSP X and Y words ++; clr A #0,r0 ++; clr B #0,r4 ++; do #64,<_block1 ++; rep #256 ++; move A,X:(r0)+ B,Y:(r4)+ ++;_block1 ; Zero (32768-512) Program words ++; clr A #512,r0 ++; do #126,<_block2 ++; rep #256 ++; move A,P:(r0)+ ++;_block2 ++ ++ ; Copy DSP program control ++ move #real,r0 ++ move #upload,r1 ++ do #upload_end-upload,<_copy ++ move P:(r0)+,x0 ++ move x0,P:(r1)+ ++_copy movep #>4,X:<<M_HCR ++ movep #>$c00,X:<<M_IPR ++ and #<$fe,mr ++ jmp upload ++ ++real ++ org P:$7ea9 ++upload ++ movep #>1,X:<<M_PBC ++ movep #>0,X:<<M_BCR ++ ++next jclr #0,X:<<M_HSR,* ++ movep X:<<M_HRX,A ++ move #>3,x0 ++ cmp x0,A #>1,x0 ++ jeq <$0 ++_get_address ++ jclr #0,X:<<M_HSR,_get_address ++ movep X:<<M_HRX,r0 ++_get_length ++ jclr #0,X:<<M_HSR,_get_length ++ movep X:<<M_HRX,y0 ++ cmp x0,A #>2,x0 ++ jeq load_X ++ cmp x0,A ++ jeq load_Y ++ ++load_P do y0,_load ++ jclr #0,X:<<M_HSR,* ++ movep X:<<M_HRX,P:(r0)+ ++_load jmp next ++load_X do y0,_load ++ jclr #0,X:<<M_HSR,* ++ movep X:<<M_HRX,X:(r0)+ ++_load jmp next ++load_Y do y0,_load ++ jclr #0,X:<<M_HSR,* ++ movep X:<<M_HRX,Y:(r0)+ ++_load jmp next ++ ++upload_end ++ end Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-radeon-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-radeon-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-radeon-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From 32e3f3ea4c0aed82f3e79c84060126d8e5a0038e Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 01:21:34 +0100 +Subject: [PATCH] radeon: Mark as broken + +--- + drivers/char/drm/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig +index ea26dfd..3b0dd6a 100644 +--- a/drivers/char/drm/Kconfig ++++ b/drivers/char/drm/Kconfig +@@ -35,6 +35,7 @@ config DRM_R128 + config DRM_RADEON + tristate "ATI Radeon" + depends on DRM && PCI ++ depends on BROKEN + 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 +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-typhoon-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-net-typhoon-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-net-typhoon-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From 74c4e0c5cd3183c6a0535e00517e662822810f8e Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 14:07:10 +0100 +Subject: [PATCH] typhoon: Mark as broken + +--- + drivers/net/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 616db30..25902d7 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -731,6 +731,7 @@ config VORTEX + config TYPHOON + tristate "3cr990 series \"Typhoon\" support" + depends on NET_VENDOR_3COM && PCI ++ depends on BROKEN + select CRC32 + ---help--- + This option enables driver support for the 3cr990 series of cards: +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-tehuti-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-net-tehuti-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-net-tehuti-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From 87460126549f1142c958c1ddda0b52569fc353d2 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 02:43:20 +0100 +Subject: [PATCH] tehuti: Mark as broken + +--- + drivers/net/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index a167a5e..8cec089 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -2570,6 +2570,7 @@ config MLX4_DEBUG + config TEHUTI + tristate "Tehuti Networks 10G Ethernet" + depends on PCI ++ depends on BROKEN + help + Tehuti Networks 10G Ethernet NIC + +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-usb-serial-whiteheat-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-usb-serial-whiteheat-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-usb-serial-whiteheat-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From dab9a198bf25cf06aab4af5cd75bb9b2ac97299d Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:45:07 +0100 +Subject: [PATCH] whiteheat: Mark as broken + +--- + drivers/usb/serial/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig +index 9ba64cc..96f811b 100644 +--- a/drivers/usb/serial/Kconfig ++++ b/drivers/usb/serial/Kconfig +@@ -102,6 +102,7 @@ config USB_SERIAL_CH341 + + config USB_SERIAL_WHITEHEAT + tristate "USB ConnectTech WhiteHEAT Serial Driver" ++ depends on BROKEN + select USB_EZUSB + help + Say Y here if you want to use a ConnectTech WhiteHEAT 4 port +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-e100-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-net-e100-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-net-e100-disable.patch (revision 0) @@ -0,0 +1,45 @@ +From 9b32fded74fd68bf33a0114344715f48905c8a8f Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 01:49:15 +0100 +Subject: [PATCH] e100: Add #ifdef markers around firmware and mark broken + +--- + drivers/net/Kconfig | 1 + + drivers/net/e100.c | 2 ++ + 2 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index f4182cf..ac4ee2d 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -1442,6 +1442,7 @@ config EEPRO100 + config E100 + tristate "Intel(R) PRO/100+ support" + depends on NET_PCI && PCI ++ depends on BROKEN + select MII + ---help--- + This driver supports Intel(R) PRO/100 family of adapters. +diff --git a/drivers/net/e100.c b/drivers/net/e100.c +index 1037b13..e842718 100644 +--- a/drivers/net/e100.c ++++ b/drivers/net/e100.c +@@ -1049,6 +1049,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) + c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); + } + ++#ifdef REMOVE_DFSG + /********************************************************/ + /* Micro code for 8086:1229 Rev 8 */ + /********************************************************/ +@@ -1186,6 +1187,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) + 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + } ++#endif /* REMOVE_DFSG */ + + static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) + { +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-usb-kaweth-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-net-usb-kaweth-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-net-usb-kaweth-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From e31ad6c4e29509bf9c2bfcdbfc29b8534585bb71 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:11:28 +0100 +Subject: [PATCH] kaweth: Mark as broken + +--- + drivers/net/usb/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig +index 0604f3f..2c0b805 100644 +--- a/drivers/net/usb/Kconfig ++++ b/drivers/net/usb/Kconfig +@@ -29,6 +29,7 @@ config USB_CATC + + config USB_KAWETH + tristate "USB KLSI KL5USB101-based ethernet device support" ++ depends on BROKEN + ---help--- + Say Y here if you want to use one of the following 10Mbps only + USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-mga-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-mga-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-mga-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From f94f9c90f7a67262b174efac6783e8ad2a40009e Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 02:46:55 +0100 +Subject: [PATCH] mga: Mark as broken + +--- + drivers/char/drm/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig +index 17edd8a..1a3d250 100644 +--- a/drivers/char/drm/Kconfig ++++ b/drivers/char/drm/Kconfig +@@ -81,6 +81,7 @@ endchoice + config DRM_MGA + tristate "Matrox g200/g400" + depends on DRM ++ depends on BROKEN + 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 +-- +1.5.6.5 + Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-starfire-disable.patch =================================================================== --- linux-2.6/debian/patches/debian/dfsg/drivers-net-starfire-disable.patch (revision 0) +++ linux-2.6/debian/patches/debian/dfsg/drivers-net-starfire-disable.patch (revision 0) @@ -0,0 +1,24 @@ +From de1dfbcd060a33ad0d434a0891c3c6544cf90a83 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 02:09:01 +0100 +Subject: [PATCH] starfire: Mark as broken + +--- + drivers/net/Kconfig | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index eaacc85..ae6d38f 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -1304,6 +1304,7 @@ config AMD8111E_NAPI + config ADAPTEC_STARFIRE + tristate "Adaptec Starfire/DuraLAN support" + depends on NET_PCI && PCI ++ depends on BROKEN + select CRC32 + select MII + help +-- +1.5.6.5 + Index: linux-2.6/debian/patches/series/10 =================================================================== --- linux-2.6/debian/patches/series/10 (revision 0) +++ linux-2.6/debian/patches/series/10 (revision 0) @@ -0,0 +1,14 @@ +- features/all/firmware-ihex-early.patch ++ features/all/firmware-ihex.patch ++ features/all/drivers-char-drm-mga-request_firmware.patch ++ features/all/drivers-char-drm-r128-request_firmware.patch ++ features/all/drivers-char-drm-radeon-request_firmware.patch ++ features/all/drivers-media-video-dabusb-request_firmware.patch ++ features/all/drivers-net-cassini-request_firmware.patch ++ features/all/drivers-net-e100-request_firmware.patch ++ features/all/drivers-net-starfire-request_firmware.patch ++ features/all/drivers-net-tehuti-request_firmware.patch ++ features/all/drivers-net-typhoon-request_firmware.patch ++ features/all/drivers-net-usb-kaweth-request_firmware.patch ++ features/all/drivers-scsi-qla1280-request_firmware.patch ++ features/all/drivers-usb-serial-whiteheat-request_firmware.patch Index: linux-2.6/debian/patches/series/orig-1 =================================================================== --- linux-2.6/debian/patches/series/orig-1 (revision 0) +++ linux-2.6/debian/patches/series/orig-1 (revision 0) @@ -0,0 +1,30 @@ ++ debian/dfsg/drivers-char-drm-r128-disable.patch ++ debian/dfsg/drivers-net-cassini-disable.patch ++ debian/dfsg/drivers-net-e100-disable.patch ++ debian/dfsg/drivers-net-tg3-mark.patch +X debian/dfsg/files-1 ++ debian/dfsg/drivers-atm.patch ++ debian/dfsg/drivers-char-computone.patch ++ debian/dfsg/drivers-char-drm-mga-disable.patch ++ debian/dfsg/drivers-char-drm-radeon-disable.patch ++ debian/dfsg/drivers-char-dsp56k-fw-source.patch ++ debian/dfsg/drivers-media-video-dabusb-disable.patch ++ debian/dfsg/drivers-media-dvb-ttusb-budget.patch ++ debian/dfsg/drivers-net-acenic-remove.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-starfire-disable.patch ++ debian/dfsg/drivers-net-tehuti-disable.patch ++ debian/dfsg/drivers-net-tg3-remove.patch ++ debian/dfsg/drivers-net-tokenring-3c359-smctr.patch ++ debian/dfsg/drivers-net-typhoon-disable.patch ++ debian/dfsg/drivers-net-usb-kaweth-disable.patch ++ debian/dfsg/drivers-scsi-qla1280-disable.patch ++ debian/dfsg/drivers-scsi-qlogicpti.patch ++ debian/dfsg/drivers-usb-misc-emi62-emi26.patch ++ debian/dfsg/drivers-usb-serial-keyspan-remove.patch ++ debian/dfsg/drivers-usb-serial-whiteheat-disable.patch ++ debian/dfsg/sound-pci.patch Index: linux-2.6/debian/patches/features/all/firmware-ihex-early.patch =================================================================== --- linux-2.6/debian/patches/features/all/firmware-ihex-early.patch (revision 0) +++ linux-2.6/debian/patches/features/all/firmware-ihex-early.patch (revision 0) @@ -0,0 +1,35 @@ +diff --git a/include/linux/ihex.h b/include/linux/ihex.h +new file mode 100644 +index 0000000..902222f +--- /dev/null ++++ b/include/linux/ihex.h +@@ -0,0 +1,28 @@ ++/* ++ * Compact binary representation of ihex records. Some devices need their ++ * firmware loaded in strange orders rather than a single big blob, but ++ * actually parsing ihex-as-text within the kernel seems silly. Thus,... ++ */ ++ ++#ifndef __LINUX_IHEX_H__ ++#define __LINUX_IHEX_H__ ++ ++#include <linux/types.h> ++ ++struct ihex_binrec { ++ __be32 addr; ++ uint8_t len; ++ uint8_t data[0]; ++} __attribute__((aligned(4))); ++ ++/* Find the next record, taking into account the 4-byte alignment */ ++static inline const struct ihex_binrec * ++ihex_next_binrec(const struct ihex_binrec *rec) ++{ ++ int next = ((rec->len + 4) & ~3) - 1; ++ rec = (void *)&rec->data[next]; ++ ++ return rec->len ? rec : NULL; ++} ++ ++#endif /* __LINUX_IHEX_H__ */ + Index: linux-2.6/debian/patches/features/all/drivers-net-typhoon-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-net-typhoon-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-net-typhoon-request_firmware.patch (revision 0) @@ -0,0 +1,167 @@ +From c2bd127e355be09451b57eac3e7e0439e4a912e2 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:04:33 +0100 +Subject: [PATCH] typhoon: use request_firmware + +Based on patch by Jaswinder Singh <jaswinder@infradead.org>, +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 25902d7..7a9316b 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -731,7 +731,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 c0dd25b..2134240 100644 +--- a/drivers/net/typhoon.c ++++ b/drivers/net/typhoon.c +@@ -130,16 +130,18 @@ static const int multicast_filter_limit = 32; + #include <linux/in6.h> + #include <linux/version.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 <dave@thedillows.org>"); + 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 " +@@ -1347,14 +1349,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; +@@ -1369,13 +1417,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 +@@ -1428,7 +1471,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); +@@ -2445,6 +2488,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); + +@@ -2595,6 +2642,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.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-net-tehuti-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-net-tehuti-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-net-tehuti-request_firmware.patch (revision 0) @@ -0,0 +1,167 @@ +From 99b544d9483102180e35c3d679385222845a2ae7 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 02:47:03 +0100 +Subject: [PATCH] tehuti: use request_firmware + +Based on patch by Jaswinder Singh <jaswinder@infradead.org> + +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 8cec089..616db30 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -2570,7 +2570,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 432e837..ea9a2ee 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 efd170f..b9acb3f 100644 +--- a/drivers/net/tehuti.h ++++ b/drivers/net/tehuti.h +@@ -30,6 +30,7 @@ + #include <linux/version.h> + #include <linux/interrupt.h> + #include <linux/vmalloc.h> ++#include <linux/firmware.h> + #include <asm/byteorder.h> + + /* Compile Time Switches */ +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-usb-serial-whiteheat-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-usb-serial-whiteheat-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-usb-serial-whiteheat-request_firmware.patch (revision 0) @@ -0,0 +1,158 @@ +From 5084013135f2efabd241f74fdd83520fc54ccaaf Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:58:59 +0100 +Subject: [PATCH] whiteheat: use request_firmware() + +Based on patch by David Woodhouse <dwmw2@infradead.org>. +--- + drivers/usb/serial/Kconfig | 2 +- + drivers/usb/serial/whiteheat.c | 79 ++++++++++++++++++++++++++-------------- + 2 files changed, 53 insertions(+), 28 deletions(-) + +diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig +index 96f811b..4335d44 100644 +--- a/drivers/usb/serial/Kconfig ++++ b/drivers/usb/serial/Kconfig +@@ -102,8 +102,8 @@ config USB_SERIAL_CH341 + + config USB_SERIAL_WHITEHEAT + tristate "USB ConnectTech WhiteHEAT Serial Driver" +- depends on BROKEN + select USB_EZUSB ++ select FW_LOADER + help + Say Y here if you want to use a ConnectTech WhiteHEAT 4 port + USB to serial converter device. +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index f07e8a4..914784f 100644 +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -81,7 +81,8 @@ + #include <linux/serial_reg.h> + #include <linux/serial.h> + #include <linux/usb/serial.h> +-#include "whiteheat_fw.h" /* firmware for the ConnectTech WhiteHEAT device */ ++#include <linux/firmware.h> ++#include <linux/ihex.h> + #include "whiteheat.h" /* WhiteHEAT specific commands */ + + static int debug; +@@ -280,58 +281,79 @@ static int firm_report_tx_done(struct usb_serial_port *port); + static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id) + { + int response; +- const struct whiteheat_hex_record *record; ++ const struct firmware *loader_fw, *firmware_fw; ++ const struct ihex_binrec *record; + + dbg("%s", __func__); + ++ response = request_ihex_firmware(&firmware_fw, "whiteheat.fw", ++ &serial->dev->dev); ++ if (response) { ++ err("%s - request \"whiteheat.fw\" failed", __func__); ++ return response; ++ } ++ response = request_ihex_firmware(&loader_fw, "whiteheat_loader.fw", ++ &serial->dev->dev); ++ if (response) { ++ err("%s - request \"whiteheat_loader.fw\" failed", __func__); ++ goto out_release_1; ++ } + response = ezusb_set_reset (serial, 1); + +- record = &whiteheat_loader[0]; +- while (record->address != 0xffff) { +- response = ezusb_writememory (serial, record->address, +- (unsigned char *)record->data, record->data_size, 0xa0); ++ record = (const struct ihex_binrec *)loader_fw->data; ++ while (record) { ++ response = ezusb_writememory(serial, be32_to_cpu(record->addr), ++ (unsigned char *)record->data, ++ be16_to_cpu(record->len), 0xa0); + if (response < 0) { + err("%s - ezusb_writememory failed for loader (%d %04X %p %d)", +- __func__, response, record->address, record->data, record->data_size); +- break; ++ __func__, response, be32_to_cpu(record->addr), ++ record->data, be16_to_cpu(record->len)); ++ goto out_reset; + } +- ++record; ++ record = ihex_next_binrec(record); + } + + response = ezusb_set_reset (serial, 0); + +- record = &whiteheat_firmware[0]; +- while (record->address < 0x1b40) { +- ++record; +- } +- while (record->address != 0xffff) { +- response = ezusb_writememory (serial, record->address, +- (unsigned char *)record->data, record->data_size, 0xa3); ++ record = (const struct ihex_binrec *)firmware_fw->data; ++ while (record && be32_to_cpu(record->addr) < 0x1b40) ++ record = ihex_next_binrec(record); ++ while (record) { ++ response = ezusb_writememory(serial, be32_to_cpu(record->addr), ++ (unsigned char *)record->data, ++ be16_to_cpu(record->len), 0xa3); + if (response < 0) { + err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)", +- __func__, response, record->address, record->data, record->data_size); +- break; ++ __func__, response, be32_to_cpu(record->addr), ++ record->data, be16_to_cpu(record->len)); ++ goto out_reset; + } + ++record; + } + + response = ezusb_set_reset (serial, 1); + +- record = &whiteheat_firmware[0]; +- while (record->address < 0x1b40) { +- response = ezusb_writememory (serial, record->address, +- (unsigned char *)record->data, record->data_size, 0xa0); ++ record = (const struct ihex_binrec *)firmware_fw->data; ++ while (record && be32_to_cpu(record->addr) < 0x1b40) { ++ response = ezusb_writememory(serial, be32_to_cpu(record->addr), ++ (unsigned char *)record->data, ++ be16_to_cpu(record->len), 0xa0); + if (response < 0) { + err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)", +- __func__, response, record->address, record->data, record->data_size); +- break; ++ __func__, response, be32_to_cpu(record->addr), ++ record->data, be16_to_cpu(record->len)); ++ goto out_reset; + } + ++record; + } + +- response = ezusb_set_reset (serial, 0); +- +- return 0; ++out_reset: ++ ezusb_set_reset(serial, 0); ++ release_firmware(loader_fw); ++out_release_1: ++ release_firmware(firmware_fw); ++ return response; + } + + +@@ -1503,6 +1525,9 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); + MODULE_DESCRIPTION( DRIVER_DESC ); + MODULE_LICENSE("GPL"); + ++MODULE_FIRMWARE("whiteheat.fw"); ++MODULE_FIRMWARE("whiteheat_loader.fw"); ++ + module_param(urb_pool_size, int, 0); + MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering"); + +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch (revision 0) @@ -0,0 +1,309 @@ +From 701b45853d4dbfb93880b9e02da689d2026c52f2 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:43:31 +0100 +Subject: [PATCH] qla1280: use request_firmware + +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 + +Signed-off-by: Jaswinder Singh <jaswinder@infradead.org> +Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> +Acked-by: Jes Sorensen <jes@sgi.com> +--- + drivers/scsi/Kconfig | 2 +- + drivers/scsi/qla1280.c | 121 +++++++++++++++++++++++++++++++---------------- + drivers/scsi/qla1280.h | 6 ++ + 3 files changed, 87 insertions(+), 42 deletions(-) + +diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig +index 94831ae..61a20e1 100644 +--- a/drivers/scsi/Kconfig ++++ b/drivers/scsi/Kconfig +@@ -1316,7 +1316,7 @@ config SCSI_QLOGIC_FC_FIRMWARE + 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 3754ab8..7b033c5 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!" +@@ -418,6 +415,11 @@ + ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160) + + ++/* Firmware Names */ ++#define FW_QLA12160 "qlogic/12160.bin" ++#define FW_QLA1040 "qlogic/1040.bin" ++#define FW_QLA1280 "qlogic/1280.bin" ++ + static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *); + static void qla1280_remove_one(struct pci_dev *); + +@@ -541,10 +543,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 +566,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, FW_QLA12160}, ++ {"QLA1040", 1, FW_QLA1040}, ++ {"QLA1080", 1, FW_QLA1280}, ++ {"QLA1240", 2, FW_QLA1280}, ++ {"QLA1280", 2, FW_QLA1280}, ++ {"QLA10160", 1, FW_QLA12160}, ++ {" ", 0, " "}, + }; + + static int qla1280_verbose = 1; +@@ -704,7 +697,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 +1641,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 +1706,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", + __FUNCTION__, risc_code_size); +@@ -1708,10 +1744,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 +1798,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 +1806,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 +1822,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 +1832,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha) + /* Start firmware execution. */ + dprintk(1, "%s: start firmware running.\n", __FUNCTION__); + 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 +1857,7 @@ qla1280_load_firmware(struct scsi_qla_host *ha) + if (err) + goto out; + err = qla1280_start_firmware(ha); +- out: ++out: + return err; + } + +@@ -4451,6 +4487,9 @@ module_exit(qla1280_exit); + MODULE_AUTHOR("Qlogic & Jes Sorensen"); + MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver"); + MODULE_LICENSE("GPL"); ++MODULE_FIRMWARE(FW_QLA1040); ++MODULE_FIRMWARE(FW_QLA1280); ++MODULE_FIRMWARE(FW_QLA12160); + 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.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-char-drm-r128-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-char-drm-r128-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-char-drm-r128-request_firmware.patch (revision 0) @@ -0,0 +1,139 @@ +From a349c45d1ba3726c61e4b205006b07fd07543221 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 02:27:57 +0100 +Subject: [PATCH] r128: Use request_firmware() to load CCE microcode + +Firmware blob looks like this: + __be32 datah + __be32 datal + +Compile-tested only. +--- + drivers/char/drm/Kconfig | 2 +- + drivers/char/drm/r128_cce.c | 54 ++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 49 insertions(+), 7 deletions(-) + +diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig +index 8f9c893..ea26dfd 100644 +--- a/drivers/char/drm/Kconfig ++++ b/drivers/char/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/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c +index a9ee89a..63bed21 100644 +--- a/drivers/char/drm/r128_cce.c ++++ b/drivers/char/drm/r128_cce.c +@@ -29,6 +29,9 @@ + * Gareth Hughes <gareth@valinux.com> + */ + ++#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.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-net-e100-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-net-e100-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-net-e100-request_firmware.patch (revision 0) @@ -0,0 +1,223 @@ +From b4ae97fb6c6ab3df6abef40cc18df2e6ea68182e Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 01:56:51 +0100 +Subject: [PATCH] e100: Use request_firmware() to load microcode where needed + +Based on patch by Jaswinder Singh <jaswinder@infradead.org> and +David Woodhouse <dwmw2@infradead.org>. +--- + drivers/net/Kconfig | 2 +- + drivers/net/e100.c | 145 ++++++++++++++++++++++++++++++--------------------- + 2 files changed, 87 insertions(+), 60 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index ac4ee2d..0836ea8 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -1442,7 +1442,7 @@ config EEPRO100 + config E100 + tristate "Intel(R) PRO/100+ support" + depends on NET_PCI && PCI +- depends on BROKEN ++ select FW_LOADER + select MII + ---help--- + This driver supports Intel(R) PRO/100 family of adapters. +diff --git a/drivers/net/e100.c b/drivers/net/e100.c +index b255a84..6e7d623 100644 +--- a/drivers/net/e100.c ++++ b/drivers/net/e100.c +@@ -161,6 +161,7 @@ + #include <linux/skbuff.h> + #include <linux/ethtool.h> + #include <linux/string.h> ++#include <linux/firmware.h> + #include <asm/unaligned.h> + + +@@ -178,6 +179,9 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); + MODULE_AUTHOR(DRV_COPYRIGHT); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); ++MODULE_FIRMWARE("e100/d101m_ucode.bin"); ++MODULE_FIRMWARE("e100/d101s_ucode.bin"); ++MODULE_FIRMWARE("e100/d102e_ucode.bin"); + + static int debug = 3; + static int eeprom_bad_csum_allow = 0; +@@ -1050,40 +1054,6 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) + } + + +-static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) +-{ +-/* *INDENT-OFF* */ +- static struct { +- u32 ucode[UCODE_SIZE + 1]; +- u8 mac; +- u8 timer_dword; +- u8 bundle_dword; +- u8 min_size_dword; +- } ucode_opts[] = { +- { D101M_B_RCVBUNDLE_UCODE, +- mac_82559_D101M, +- D101M_CPUSAVER_TIMER_DWORD, +- D101M_CPUSAVER_BUNDLE_DWORD, +- D101M_CPUSAVER_MIN_SIZE_DWORD }, +- { D101S_RCVBUNDLE_UCODE, +- mac_82559_D101S, +- D101S_CPUSAVER_TIMER_DWORD, +- D101S_CPUSAVER_BUNDLE_DWORD, +- D101S_CPUSAVER_MIN_SIZE_DWORD }, +- { D102_E_RCVBUNDLE_UCODE, +- mac_82551_F, +- D102_E_CPUSAVER_TIMER_DWORD, +- D102_E_CPUSAVER_BUNDLE_DWORD, +- D102_E_CPUSAVER_MIN_SIZE_DWORD }, +- { D102_E_RCVBUNDLE_UCODE, +- mac_82551_10, +- D102_E_CPUSAVER_TIMER_DWORD, +- D102_E_CPUSAVER_BUNDLE_DWORD, +- D102_E_CPUSAVER_MIN_SIZE_DWORD }, +- { {0}, 0, 0, 0, 0} +- }, *opts; +-/* *INDENT-ON* */ +- + /************************************************************************* + * CPUSaver parameters + * +@@ -1143,42 +1113,99 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb + #define BUNDLEMAX (u16)6 + #define INTDELAY (u16)1536 /* 0x600 */ + ++static const struct firmware *e100_request_firmware(struct nic *nic) ++{ ++ const char *fw_name; ++ const struct firmware *fw; ++ u8 timer, bundle, min_size; ++ int err; ++ + /* do not load u-code for ICH devices */ + if (nic->flags & ich) +- goto noloaducode; ++ return NULL; + + /* Search for ucode match against h/w revision */ +- for (opts = ucode_opts; opts->mac; opts++) { +- int i; +- u32 *ucode = opts->ucode; +- if (nic->mac != opts->mac) +- continue; +- +- /* Insert user-tunable settings */ +- ucode[opts->timer_dword] &= 0xFFFF0000; +- ucode[opts->timer_dword] |= INTDELAY; +- ucode[opts->bundle_dword] &= 0xFFFF0000; +- ucode[opts->bundle_dword] |= BUNDLEMAX; +- ucode[opts->min_size_dword] &= 0xFFFF0000; +- ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80; ++ if (nic->mac == mac_82559_D101M) ++ fw_name = "e100/d101m_ucode.bin"; ++ else if (nic->mac == mac_82559_D101S) ++ fw_name = "e100/d101s_ucode.bin"; ++ else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10) ++ fw_name = "e100/d102e_ucode.bin"; ++ else /* No ucode on other devices */ ++ return NULL; ++ ++ err = request_firmware(&fw, fw_name, &nic->pdev->dev); ++ if (err) { ++ DPRINTK(PROBE,ERR, "Failed to load firmware \"%s\": %d\n", ++ fw_name, err); ++ return ERR_PTR(err); ++ } ++ /* Firmware should be precisely UCODE_SIZE (words) plus three bytes ++ indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */ ++ if (fw->size != UCODE_SIZE * 4 + 3) { ++ DPRINTK(PROBE,ERR, "Firmware \"%s\" has wrong size %zu\n", ++ fw_name, fw->size); ++ release_firmware(fw); ++ return ERR_PTR(-EINVAL); ++ } + +- for (i = 0; i < UCODE_SIZE; i++) +- cb->u.ucode[i] = cpu_to_le32(ucode[i]); +- cb->command = cpu_to_le16(cb_ucode | cb_el); +- return; ++ /* Read timer, bundle and min_size from end of firmware blob */ ++ timer = fw->data[UCODE_SIZE * 4]; ++ bundle = fw->data[UCODE_SIZE * 4 + 1]; ++ min_size = fw->data[UCODE_SIZE * 4 + 2]; ++ ++ if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE || ++ min_size >= UCODE_SIZE) { ++ DPRINTK(PROBE,ERR, "Firmware \"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n", ++ fw_name, timer, bundle, min_size); ++ release_firmware(fw); ++ return ERR_PTR(-EINVAL); + } ++ /* OK, firmware is validated and ready to use... */ ++ return fw; ++} + +-noloaducode: +- cb->command = cpu_to_le16(cb_nop | cb_el); ++static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) ++{ ++ const struct firmware *fw = (void *)skb; ++ u8 timer, bundle, min_size; ++ ++ /* It's not a real skb; we just abused the fact that e100_exec_cb ++ will pass it through to here... */ ++ cb->skb = NULL; ++ ++ /* firmware is stored as little endian already */ ++ memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4); ++ ++ /* Read timer, bundle and min_size from end of firmware blob */ ++ timer = fw->data[UCODE_SIZE * 4]; ++ bundle = fw->data[UCODE_SIZE * 4 + 1]; ++ min_size = fw->data[UCODE_SIZE * 4 + 2]; ++ ++ /* Insert user-tunable settings in cb->u.ucode */ ++ cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000); ++ cb->u.ucode[timer] |= cpu_to_le32(INTDELAY); ++ cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000); ++ cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX); ++ cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000); ++ cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80); ++ ++ cb->command = cpu_to_le16(cb_ucode | cb_el); + } + +-static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb, +- void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) ++static inline int e100_load_ucode_wait(struct nic *nic) + { ++ const struct firmware *fw; ++ + int err = 0, counter = 50; + struct cb *cb = nic->cb_to_clean; + +- if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode))) ++ fw = e100_request_firmware(nic); ++ /* If it's NULL, then no ucode is required */ ++ if (!fw || IS_ERR(fw)) ++ return PTR_ERR(fw); ++ ++ if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode))) + DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err); + + /* must restart cuc */ +@@ -1298,7 +1325,7 @@ static int e100_hw_init(struct nic *nic) + return err; + if((err = e100_exec_cmd(nic, ruc_load_base, 0))) + return err; +- if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) ++ if ((err = e100_load_ucode_wait(nic))) + return err; + if((err = e100_exec_cb(nic, NULL, e100_configure))) + return err; +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-net-usb-kaweth-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-net-usb-kaweth-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-net-usb-kaweth-request_firmware.patch (revision 0) @@ -0,0 +1,141 @@ +From 501cc6ba7b2b1ad48a231d6b9395c0f5973f58b6 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 16:13:47 +0100 +Subject: [PATCH] kaweth: use request_firmware() + +Based on patch by David Woodhouse <dwmw2@infradead.org>. +--- + drivers/net/usb/Kconfig | 2 +- + drivers/net/usb/kaweth.c | 43 ++++++++++++++++++++++++++----------------- + 2 files changed, 27 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig +index 2c0b805..aec69f5 100644 +--- a/drivers/net/usb/Kconfig ++++ b/drivers/net/usb/Kconfig +@@ -29,7 +29,7 @@ config USB_CATC + + config USB_KAWETH + tristate "USB KLSI KL5USB101-based ethernet device support" +- depends on BROKEN ++ select FW_LOADER + ---help--- + Say Y here if you want to use one of the following 10Mbps only + USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: +diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c +index 7c66b05..d6829db 100644 +--- a/drivers/net/usb/kaweth.c ++++ b/drivers/net/usb/kaweth.c +@@ -57,13 +57,12 @@ + #include <linux/ethtool.h> + #include <linux/dma-mapping.h> + #include <linux/wait.h> ++#include <linux/firmware.h> + #include <asm/uaccess.h> + #include <asm/byteorder.h> + + #undef DEBUG + +-#include "kawethfw.h" +- + #define KAWETH_MTU 1514 + #define KAWETH_BUF_SIZE 1664 + #define KAWETH_TX_TIMEOUT (5 * HZ) +@@ -108,6 +107,10 @@ + MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>"); + MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver"); + MODULE_LICENSE("GPL"); ++MODULE_FIRMWARE("kaweth/new_code.bin"); ++MODULE_FIRMWARE("kaweth/new_code_fix.bin"); ++MODULE_FIRMWARE("kaweth/trigger_code.bin"); ++MODULE_FIRMWARE("kaweth/trigger_code_fix.bin"); + + static const char driver_name[] = "kaweth"; + +@@ -385,17 +388,28 @@ static int kaweth_set_receive_filter(struct kaweth_device *kaweth, + * kaweth_download_firmware + ****************************************************************/ + static int kaweth_download_firmware(struct kaweth_device *kaweth, +- __u8 *data, +- __u16 data_len, ++ const char *fwname, + __u8 interrupt, + __u8 type) + { +- if(data_len > KAWETH_FIRMWARE_BUF_SIZE) { +- err("Firmware too big: %d", data_len); ++ const struct firmware *fw; ++ int data_len; ++ int ret; ++ ++ ret = request_firmware(&fw, fwname, &kaweth->dev->dev); ++ if (ret) { ++ err("Firmware request failed\n"); ++ return ret; ++ } ++ ++ if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) { ++ err("Firmware too big: %zu", fw->size); + return -ENOSPC; + } ++ data_len = fw->size; ++ memcpy(kaweth->firmware_buf, fw->data, fw->size); + +- memcpy(kaweth->firmware_buf, data, data_len); ++ release_firmware(fw); + + kaweth->firmware_buf[2] = (data_len & 0xFF) - 7; + kaweth->firmware_buf[3] = data_len >> 8; +@@ -406,8 +420,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, + kaweth->firmware_buf[2]); + + dbg("Downloading firmware at %p to kaweth device at %p", +- data, +- kaweth); ++ fw->data, kaweth); + dbg("Firmware length: %d", data_len); + + return kaweth_control(kaweth, +@@ -1009,8 +1022,7 @@ static int kaweth_probe( + info("Downloading firmware..."); + kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); + if ((result = kaweth_download_firmware(kaweth, +- kaweth_new_code, +- len_kaweth_new_code, ++ "kaweth/new_code.bin", + 100, + 2)) < 0) { + err("Error downloading firmware (%d)", result); +@@ -1018,8 +1030,7 @@ static int kaweth_probe( + } + + if ((result = kaweth_download_firmware(kaweth, +- kaweth_new_code_fix, +- len_kaweth_new_code_fix, ++ "kaweth/new_code_fix.bin", + 100, + 3)) < 0) { + err("Error downloading firmware fix (%d)", result); +@@ -1027,8 +1038,7 @@ static int kaweth_probe( + } + + if ((result = kaweth_download_firmware(kaweth, +- kaweth_trigger_code, +- len_kaweth_trigger_code, ++ "kaweth/trigger_code.bin", + 126, + 2)) < 0) { + err("Error downloading trigger code (%d)", result); +@@ -1037,8 +1047,7 @@ static int kaweth_probe( + } + + if ((result = kaweth_download_firmware(kaweth, +- kaweth_trigger_code_fix, +- len_kaweth_trigger_code_fix, ++ "kaweth/trigger_code_fix.bin", + 126, + 3)) < 0) { + err("Error downloading trigger code fix (%d)", result); +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-char-drm-mga-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-char-drm-mga-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-char-drm-mga-request_firmware.patch (revision 0) @@ -0,0 +1,295 @@ +From 32f99018901dd149fbd1be7da408f6f6b5246f5b Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 04:28:10 +0100 +Subject: [PATCH] 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/char/drm/Kconfig | 2 +- + drivers/char/drm/mga_dma.c | 4 +- + drivers/char/drm/mga_drm.h | 2 +- + drivers/char/drm/mga_drv.h | 1 - + drivers/char/drm/mga_warp.c | 180 +++++++++++++++++++------------------------ + 5 files changed, 82 insertions(+), 107 deletions(-) + +diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig +index 1a3d250..5268ad4 100644 +--- a/drivers/char/drm/Kconfig ++++ b/drivers/char/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/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c +index c1d12db..bcd3ff1 100644 +--- a/drivers/char/drm/mga_dma.c ++++ b/drivers/char/drm/mga_dma.c +@@ -439,7 +439,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 +@@ -614,7 +614,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/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h +index 944b50a..0b8fc27 100644 +--- a/drivers/char/drm/mga_drm.h ++++ b/drivers/char/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 +diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h +index f6ebd24..e3945c2 100644 +--- a/drivers/char/drm/mga_drv.h ++++ b/drivers/char/drm/mga_drv.h +@@ -176,7 +176,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/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c +index 651b93c..9aad484 100644 +--- a/drivers/char/drm/mga_warp.c ++++ b/drivers/char/drm/mga_warp.c +@@ -27,132 +27,108 @@ + * Gareth Hughes <gareth@valinux.com> + */ + ++#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) +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-net-starfire-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-net-starfire-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-net-starfire-request_firmware.patch (revision 0) @@ -0,0 +1,180 @@ +From 24add72cd3fc11429f3e0db2a50d08a0f272835c Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 02:13:56 +0100 +Subject: [PATCH] starfire: use request_firmware() + +Based on patch by Jaswinder Singh <jaswinder@infradead.org> and +David Woodhouse <David.Woodhouse@intel.com>. + +Firmware blob is big endian +--- + drivers/net/Kconfig | 2 +- + drivers/net/starfire.c | 68 +++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 63 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index ae6d38f..a167a5e 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -1304,9 +1304,9 @@ config AMD8111E_NAPI + config ADAPTEC_STARFIRE + tristate "Adaptec Starfire/DuraLAN support" + depends on NET_PCI && PCI +- depends on BROKEN + select CRC32 + select MII ++ select FW_LOADER + help + Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network + adapter. The DuraLAN chip is used on the 64 bit PCI boards from +diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c +index 7b7b171..63e426b 100644 +--- a/drivers/net/starfire.c ++++ b/drivers/net/starfire.c +@@ -42,11 +42,11 @@ + #include <linux/mii.h> + #include <linux/if_vlan.h> + #include <linux/mm.h> ++#include <linux/firmware.h> + #include <asm/processor.h> /* Processor type for cache alignment. */ + #include <asm/uaccess.h> + #include <asm/io.h> + +-#include "starfire_firmware.h" + /* + * The current frame processor firmware fails to checksum a fragment + * of length 1. If and when this is fixed, the #define below can be removed. +@@ -214,6 +214,9 @@ do { \ + #endif /* not HAVE_NETDEV_POLL */ + /* end of compatibility code */ + ++/* Firmware names */ ++#define FIRMWARE_RX "adaptec/starfire_rx.bin" ++#define FIRMWARE_TX "adaptec/starfire_tx.bin" + + /* These identify the driver base version and may not be removed. */ + static char version[] = +@@ -223,6 +226,8 @@ KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELD + MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); + MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); + MODULE_LICENSE("GPL"); ++MODULE_FIRMWARE(FIRMWARE_RX); ++MODULE_FIRMWARE(FIRMWARE_TX); + MODULE_VERSION(DRV_VERSION); + + module_param(max_interrupt_work, int, 0); +@@ -622,6 +627,9 @@ struct netdev_private { + int phy_cnt; /* MII device addresses. */ + unsigned char phys[PHY_CNT]; /* MII device addresses. */ + void __iomem *base; ++ ++ /* Firmware section */ ++ const struct firmware *fw_rx, *fw_tx; + }; + + +@@ -682,6 +690,42 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) + } + #endif /* VLAN_SUPPORT */ + ++static int starfire_init_firmware(struct netdev_private *np) ++{ ++ int retval; ++ ++ retval = request_firmware(&np->fw_rx, FIRMWARE_RX, &np->pci_dev->dev); ++ if (retval) { ++ printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", ++ FIRMWARE_RX); ++ return retval; ++ } ++ if (np->fw_rx->size % 4) { ++ printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", ++ np->fw_rx->size, FIRMWARE_RX); ++ retval = -EINVAL; ++ goto out_rx; ++ } ++ retval = request_firmware(&np->fw_tx, FIRMWARE_TX, &np->pci_dev->dev); ++ if (retval) { ++ printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", ++ FIRMWARE_TX); ++ goto out_rx; ++ } ++ if (np->fw_tx->size % 4) { ++ printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", ++ np->fw_tx->size, FIRMWARE_TX); ++ retval = -EINVAL; ++ goto out_tx; ++ } ++ return 0; ++ ++out_tx: ++ release_firmware(np->fw_tx); ++out_rx: ++ release_firmware(np->fw_rx); ++ return retval; ++} + + static int __devinit starfire_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +@@ -868,6 +912,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, + dev->name, netdrv_tbl[chip_idx].name, base, + print_mac(mac, dev->dev_addr), irq); + ++ if (starfire_init_firmware(np)) ++ goto err_out_cleardev; ++ + if (drv_flags & CanHaveMII) { + int phy, phy_idx = 0; + int mii_status; +@@ -946,7 +993,9 @@ static int netdev_open(struct net_device *dev) + { + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; ++ const __be32 *fw_rx_data, *fw_tx_data; + int i, retval; ++ size_t tx_size, rx_size; + size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size; + + /* Do we ever need to reset the chip??? */ +@@ -1083,11 +1132,15 @@ static int netdev_open(struct net_device *dev) + writel(ETH_P_8021Q, ioaddr + VlanType); + #endif /* VLAN_SUPPORT */ + ++ fw_rx_data = (const __be32 *)&np->fw_rx->data[0]; ++ fw_tx_data = (const __be32 *)&np->fw_tx->data[0]; ++ rx_size = np->fw_rx->size / 4; ++ tx_size = np->fw_tx->size / 4; + /* Load Rx/Tx firmware into the frame processors */ +- for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++) +- writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4); +- for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++) +- writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4); ++ for (i = 0; i < rx_size; i++) ++ writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4); ++ for (i = 0; i < tx_size; i++) ++ writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4); + if (enable_hw_cksum) + /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */ + writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl); +@@ -1099,7 +1152,7 @@ static int netdev_open(struct net_device *dev) + printk(KERN_DEBUG "%s: Done netdev_open().\n", + dev->name); + +- return 0; ++ return retval; + } + + +@@ -2009,6 +2062,9 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) + + BUG_ON(!dev); + ++ release_firmware(np->fw_tx); ++ release_firmware(np->fw_rx); ++ + unregister_netdev(dev); + + if (np->queue_mem) +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-char-drm-radeon-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-char-drm-radeon-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-char-drm-radeon-request_firmware.patch (revision 0) @@ -0,0 +1,358 @@ +From 6e8e826c3577a4d4d875c754fd207e132c8f3a8a Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 01:29:35 +0100 +Subject: [PATCH] radeon: Use request_firmware() to load CP microcode + +Tested on Radeon 7500 (RV200) with and without firmware installed. +--- + drivers/char/drm/Kconfig | 2 +- + drivers/char/drm/radeon_cp.c | 151 ++++++++++++++++++++++++----------------- + drivers/char/drm/radeon_drv.h | 6 ++ + 3 files changed, 95 insertions(+), 64 deletions(-) + +diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig +index 3b0dd6a..17edd8a 100644 +--- a/drivers/char/drm/Kconfig ++++ b/drivers/char/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/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c +index e53158f..5542b0b 100644 +--- a/drivers/char/drm/radeon_cp.c ++++ b/drivers/char/drm/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 u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +@@ -320,66 +333,48 @@ 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) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || + ((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_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) { + DRM_INFO("Loading RS690 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) || +@@ -387,11 +382,40 @@ 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); ++ } ++ 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])); + } + } + } +@@ -853,14 +877,14 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) + static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + { + drm_radeon_private_t *dev_priv = dev->dev_private; ++ int err = -EINVAL; + + DRM_DEBUG("\n"); + + /* if we require new memory map but we don't have it fail */ + if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { + DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + + if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { +@@ -874,16 +898,14 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + + if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { + DRM_ERROR("PCI GART memory not allocated!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + + dev_priv->usec_timeout = init->usec_timeout; + if (dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { + DRM_DEBUG("TIMEOUT problem!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + + /* Enable vblank on CRTC1 for older X servers +@@ -911,8 +933,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && + (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { + DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + + switch (init->fb_bpp) { +@@ -980,28 +1001,24 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + dev_priv->sarea = drm_getsarea(dev); + if (!dev_priv->sarea) { + DRM_ERROR("could not find sarea!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + + dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); + if (!dev_priv->cp_ring) { + DRM_ERROR("could not find cp ring region!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); + if (!dev_priv->ring_rptr) { + DRM_ERROR("could not find ring read pointer!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + dev->agp_buffer_token = init->buffers_offset; + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if (!dev->agp_buffer_map) { + DRM_ERROR("could not find dma buffer region!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + + if (init->gart_textures_offset) { +@@ -1009,8 +1026,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + drm_core_findmap(dev, init->gart_textures_offset); + if (!dev_priv->gart_textures) { + DRM_ERROR("could not find GART texture region!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + } + +@@ -1027,8 +1043,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + !dev_priv->ring_rptr->handle || + !dev->agp_buffer_map->handle) { + DRM_ERROR("could not find ioremap agp regions!\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + } else + #endif +@@ -1180,21 +1195,25 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + if (dev_priv->flags & RADEON_IS_PCIE) { + DRM_ERROR + ("Cannot use PCI Express without GART in FB memory\n"); +- radeon_do_cleanup_cp(dev); +- return -EINVAL; ++ goto out; + } + } + + if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { + DRM_ERROR("failed to init PCI GART!\n"); +- radeon_do_cleanup_cp(dev); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto out; + } + + /* Turn on PCI GART */ + radeon_set_pcigart(dev_priv, 1); + } + ++ err = radeon_cp_init_microcode(dev_priv); ++ if (err) { ++ DRM_ERROR("Failed to load firmware!\n"); ++ goto out; ++ } + radeon_cp_load_microcode(dev_priv); + radeon_cp_init_ring_buffer(dev, dev_priv); + +@@ -1204,6 +1223,9 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) + radeon_test_writeback(dev_priv); + + return 0; ++out: ++ radeon_do_cleanup_cp(dev); ++ return err; + } + + static int radeon_do_cleanup_cp(struct drm_device * dev) +@@ -1249,6 +1271,9 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) + dev_priv->gart_info.addr = 0; + } + } ++ ++ release_firmware(dev_priv->fw); ++ + /* only clear to the start of flags */ + memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); + +diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h +index 3f0eca9..5cc808e 100644 +--- a/drivers/char/drm/radeon_drv.h ++++ b/drivers/char/drm/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: + */ + +@@ -311,6 +314,9 @@ typedef struct drm_radeon_private { + unsigned long fb_aper_offset; + + int num_gb_pipes; ++ ++ /* firmware */ ++ const struct firmware *fw; + } drm_radeon_private_t; + + typedef struct drm_radeon_buf_priv { +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/firmware-ihex.patch =================================================================== --- linux-2.6/debian/patches/features/all/firmware-ihex.patch (revision 0) +++ linux-2.6/debian/patches/features/all/firmware-ihex.patch (revision 0) @@ -0,0 +1,114 @@ +From cd76b5773b38860d3ffbe6f332d2feddae9191c1 Mon Sep 17 00:00:00 2001 +From: David Woodhouse <dwmw2@infradead.org> +Date: Fri, 30 May 2008 13:57:27 +0300 +Subject: [PATCH] ihex.h: binary representation of ihex records + +Combination of two patches by David Woodhouse: + +Some devices need their firmware as a set of {address, len, data...} +records in some specific order rather than a simple blob. + +The normal way of doing this kind of thing is 'ihex', which is a text +format and not entirely suitable for use in the kernel. + +This provides a binary representation which is very similar, but much +more compact -- and a helper routine to skip to the next record, +because the alignment constraints mean that everybody will screw it up +for themselves otherwise. + +Also a helper function which can verify that a 'struct firmware' +contains a valid set of ihex records, and that following them won't run +off the end of the loaded data. + +Provide a helper to load the file and validate it in one call, to +simplify error handling in the drivers which are going to use it. + +Signed-off-by: David Woodhouse <dwmw2@infradead.org> +--- + include/linux/ihex.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 74 insertions(+), 0 deletions(-) + create mode 100644 include/linux/ihex.h + +diff --git a/include/linux/ihex.h b/include/linux/ihex.h +new file mode 100644 +index 0000000..2baace2 +--- /dev/null ++++ b/include/linux/ihex.h +@@ -0,0 +1,74 @@ ++/* ++ * Compact binary representation of ihex records. Some devices need their ++ * firmware loaded in strange orders rather than a single big blob, but ++ * actually parsing ihex-as-text within the kernel seems silly. Thus,... ++ */ ++ ++#ifndef __LINUX_IHEX_H__ ++#define __LINUX_IHEX_H__ ++ ++#include <linux/types.h> ++#include <linux/firmware.h> ++#include <linux/device.h> ++ ++/* Intel HEX files actually limit the length to 256 bytes, but we have ++ drivers which would benefit from using separate records which are ++ longer than that, so we extend to 16 bits of length */ ++struct ihex_binrec { ++ __be32 addr; ++ __be16 len; ++ uint8_t data[0]; ++} __attribute__((aligned(4))); ++ ++/* Find the next record, taking into account the 4-byte alignment */ ++static inline const struct ihex_binrec * ++ihex_next_binrec(const struct ihex_binrec *rec) ++{ ++ int next = ((be16_to_cpu(rec->len) + 5) & ~3) - 2; ++ rec = (void *)&rec->data[next]; ++ ++ return be16_to_cpu(rec->len) ? rec : NULL; ++} ++ ++/* Check that ihex_next_binrec() won't take us off the end of the image... */ ++static inline int ihex_validate_fw(const struct firmware *fw) ++{ ++ const struct ihex_binrec *rec; ++ size_t ofs = 0; ++ ++ while (ofs <= fw->size - sizeof(*rec)) { ++ rec = (void *)&fw->data[ofs]; ++ ++ /* Zero length marks end of records */ ++ if (!be16_to_cpu(rec->len)) ++ return 0; ++ ++ /* Point to next record... */ ++ ofs += (sizeof(*rec) + be16_to_cpu(rec->len) + 3) & ~3; ++ } ++ return -EINVAL; ++} ++ ++/* Request firmware and validate it so that we can trust we won't ++ * run off the end while reading records... */ ++static inline int request_ihex_firmware(const struct firmware **fw, ++ const char *fw_name, ++ struct device *dev) ++{ ++ const struct firmware *lfw; ++ int ret; ++ ++ ret = request_firmware(&lfw, fw_name, dev); ++ if (ret) ++ return ret; ++ ret = ihex_validate_fw(lfw); ++ if (ret) { ++ dev_err(dev, "Firmware \"%s\" not valid IHEX records\n", ++ fw_name); ++ release_firmware(lfw); ++ return ret; ++ } ++ *fw = lfw; ++ return 0; ++} ++#endif /* __LINUX_IHEX_H__ */ +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-net-cassini-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-net-cassini-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-net-cassini-request_firmware.patch (revision 0) @@ -0,0 +1,148 @@ +From 1fcdebdd05d5f730afc74cc910ab52497656fb93 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 15 Oct 2008 02:06:48 +0100 +Subject: [PATCH] cassini: Use request_firmware() to load Saturn PHY firmware patch + +Based on patch by Jaswinder Singh <jaswinder@infradead.org>. + +Firmware blob looks like this... + __le16 load_address + unsigned char data[] +--- + drivers/net/Kconfig | 2 +- + drivers/net/cassini.c | 44 ++++++++++++++++++++++++++++++++++++++------ + drivers/net/cassini.h | 3 +++ + 3 files changed, 42 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 9426787..eaacc85 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -584,8 +584,8 @@ config SUNGEM + config CASSINI + tristate "Sun Cassini support" + depends on PCI +- depends on BROKEN + select CRC32 ++ select FW_LOADER + help + Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also + <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf> +diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c +index 83768df..71096ea 100644 +--- a/drivers/net/cassini.c ++++ b/drivers/net/cassini.c +@@ -91,6 +91,7 @@ + #include <linux/ip.h> + #include <linux/tcp.h> + #include <linux/mutex.h> ++#include <linux/firmware.h> + + #include <net/checksum.h> + +@@ -188,6 +189,7 @@ + #define CAS_RESET_SPARE 3 + #endif + ++#define FIRMWARE_NAME "sun/cassini.bin" + static char version[] __devinitdata = + DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + +@@ -197,6 +199,7 @@ static int link_mode; + MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)"); + MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver"); + MODULE_LICENSE("GPL"); ++MODULE_FIRMWARE(FIRMWARE_NAME); + module_param(cassini_debug, int, 0); + MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value"); + module_param(link_mode, int, 0); +@@ -800,9 +803,33 @@ static int cas_reset_mii_phy(struct cas *cp) + return (limit <= 0); + } + ++static int cas_saturn_firmware_init(struct cas *cp) ++{ ++ int err; ++ ++ if (PHY_NS_DP83065 != cp->phy_id) { ++ cp->fw = NULL; ++ return 0; ++ } ++ ++ err = request_firmware(&cp->fw, FIRMWARE_NAME, &cp->pdev->dev); ++ if (err) ++ printk(KERN_ERR "cassini: Failed to load firmware \"%s\"\n", ++ FIRMWARE_NAME); ++ else if (cp->fw->size < 2) { ++ printk(KERN_ERR "cassini: bogus length %zu in \"%s\"\n", ++ cp->fw->size, FIRMWARE_NAME); ++ err = -EINVAL; ++ release_firmware(cp->fw); ++ } ++ ++ return err; ++} ++ + static void cas_saturn_firmware_load(struct cas *cp) + { +- cas_saturn_patch_t *patch = cas_saturn_patch; ++ int i; ++ u16 fw_load_addr; + + cas_phy_powerdown(cp); + +@@ -819,13 +846,13 @@ static void cas_saturn_firmware_load(struct cas *cp) + cas_phy_write(cp, DP83065_MII_REGE, 0x8ffc); + cas_phy_write(cp, DP83065_MII_REGD, 0x39); + ++ fw_load_addr = cp->fw->data[1] << 8 | cp->fw->data[0]; ++ + /* download new firmware */ + cas_phy_write(cp, DP83065_MII_MEM, 0x1); +- cas_phy_write(cp, DP83065_MII_REGE, patch->addr); +- while (patch->addr) { +- cas_phy_write(cp, DP83065_MII_REGD, patch->val); +- patch++; +- } ++ cas_phy_write(cp, DP83065_MII_REGE, fw_load_addr); ++ for (i = 2; i < cp->fw->size; i++) ++ cas_phy_write(cp, DP83065_MII_REGD, cp->fw->data[i]); + + /* enable firmware */ + cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8); +@@ -5096,6 +5123,9 @@ static int __devinit cas_init_one(struct pci_dev *pdev, + cas_reset(cp, 0); + if (cas_check_invariants(cp)) + goto err_out_iounmap; ++ if (cp->cas_flags & CAS_FLAG_SATURN) ++ if (cas_saturn_firmware_init(cp)) ++ goto err_out_iounmap; + + cp->init_block = (struct cas_init_block *) + pci_alloc_consistent(pdev, sizeof(struct cas_init_block), +@@ -5205,6 +5235,8 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) + cp = netdev_priv(dev); + unregister_netdev(dev); + ++ release_firmware(cp->fw); ++ + mutex_lock(&cp->pm_mutex); + flush_scheduled_work(); + if (cp->hw_running) +diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h +index 70f8b36..6f0f62f 100644 +--- a/drivers/net/cassini.h ++++ b/drivers/net/cassini.h +@@ -2874,6 +2874,9 @@ struct cas { + dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS]; + struct pci_dev *pdev; + struct net_device *dev; ++ ++ /* Firmware section */ ++ const struct firmware *fw; + }; + + #define TX_DESC_NEXT(r, x) (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1)) +-- +1.5.6.5 + Index: linux-2.6/debian/patches/features/all/drivers-media-video-dabusb-request_firmware.patch =================================================================== --- linux-2.6/debian/patches/features/all/drivers-media-video-dabusb-request_firmware.patch (revision 0) +++ linux-2.6/debian/patches/features/all/drivers-media-video-dabusb-request_firmware.patch (revision 0) @@ -0,0 +1,165 @@ +From 3c26f7c55d6a0bc1769eff3d41db3db46620b37c Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sat, 18 Oct 2008 15:48:14 +0100 +Subject: [PATCH] dabusb: Use request_firmware() to load firmware and FPGA bitfile + +Based on patch by David Woodhouse <David.Woodhouse@intel.com>. +--- + drivers/media/Kconfig | 2 +- + drivers/media/video/dabusb.c | 60 +++++++++++++++++++++++++++++++++-------- + 2 files changed, 49 insertions(+), 13 deletions(-) + +diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig +index ec7baaa..89fadba 100644 +--- a/drivers/media/Kconfig ++++ b/drivers/media/Kconfig +@@ -125,7 +125,7 @@ if DAB + config USB_DABUSB + tristate "DABUSB driver" + depends on USB +- depends on BROKEN ++ select FW_LOADER + ---help--- + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux + brought to you by the DAB-Team +diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c +index 8d1f8ee..3d52e07 100644 +--- a/drivers/media/video/dabusb.c ++++ b/drivers/media/video/dabusb.c +@@ -38,9 +38,10 @@ + #include <linux/delay.h> + #include <linux/usb.h> + #include <linux/mutex.h> ++#include <linux/firmware.h> ++#include <linux/ihex.h> + + #include "dabusb.h" +-#include "dabfirmware.h" + + /* + * Version Information +@@ -49,6 +50,12 @@ + #define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" + #define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" + ++#define FIRMWARE_NAME "dabusb/firmware.fw" ++#define BITSTREAM_NAME "dabusb/bitstream.bin" ++ ++MODULE_FIRMWARE(FIRMWARE_NAME); ++MODULE_FIRMWARE(BITSTREAM_NAME); ++ + /* --------------------------------------------------------------------- */ + + #ifdef CONFIG_USB_DYNAMIC_MINORS +@@ -297,7 +304,8 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) + return ret; + } + /* --------------------------------------------------------------------- */ +-static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len) ++static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data, ++ int len) + { + int ret; + unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); +@@ -324,24 +332,35 @@ static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) + static int dabusb_loadmem (pdabusb_t s, const char *fname) + { + int ret; +- PINTEL_HEX_RECORD ptr = firmware; ++ const struct ihex_binrec *rec; ++ const struct firmware *fw; + + dbg("Enter dabusb_loadmem (internal)"); + ++ ret = request_ihex_firmware(&fw, FIRMWARE_NAME, &s->usbdev->dev); ++ if (ret) { ++ err("Failed to load \"" FIRMWARE_NAME "\": %d\n", ret); ++ goto out; ++ } + ret = dabusb_8051_reset (s, 1); +- while (ptr->Type == 0) { + +- dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length); ++ for (rec = (const struct ihex_binrec *)fw->data; rec; ++ rec = ihex_next_binrec(rec)) { ++ dbg("dabusb_writemem: %04X %p %d)", be32_to_cpu(rec->addr), ++ rec->data, be16_to_cpu(rec->len)); + +- ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length); ++ ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data, ++ be16_to_cpu(rec->len)); + if (ret < 0) { +- err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length); ++ err("dabusb_writemem failed (%d %04X %p %d)", ret, ++ be32_to_cpu(rec->addr), rec->data, ++ be16_to_cpu(rec->len)); + break; + } +- ptr++; + } + ret = dabusb_8051_reset (s, 0); +- ++ release_firmware(fw); ++ out: + dbg("dabusb_loadmem: exit"); + + return ret; +@@ -376,9 +395,9 @@ static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) + static int dabusb_fpga_download (pdabusb_t s, const char *fname) + { + pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); ++ const struct firmware *fw; + unsigned int blen, n; + int ret; +- unsigned char *buf = bitstream; + + dbg("Enter dabusb_fpga_download (internal)"); + +@@ -387,10 +406,24 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname) + return -ENOMEM; + } + ++ ret = request_firmware(&fw, BITSTREAM_NAME, &s->usbdev->dev); ++ if (ret) { ++ err("Failed to load \"" BITSTREAM_NAME "\": %d\n", ret); ++ goto out_free; ++ } ++ if (fw->size < 74) { ++ ret = -EINVAL; ++ goto out_release; ++ } ++ blen = fw->data[73] + (fw->data[72] << 8); ++ if (fw->size != 74 + blen) { ++ ret = -EINVAL; ++ goto out_release; ++ } ++ + b->pipe = 1; + ret = dabusb_fpga_clear (s, b); + mdelay (10); +- blen = buf[73] + (buf[72] << 8); + + dbg("Bitstream len: %i", blen); + +@@ -402,7 +435,7 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname) + for (n = 0; n <= blen + 60; n += 60) { + // some cclks for startup + b->size = 64; +- memcpy (b->data + 4, buf + 74 + n, 60); ++ memcpy (b->data + 4, fw->data + 74 + n, 60); + ret = dabusb_bulk (s, b); + if (ret < 0) { + err("dabusb_bulk failed."); +@@ -412,6 +445,9 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname) + } + + ret = dabusb_fpga_init (s, b); ++out_release: ++ release_firmware(fw); ++out_free: + kfree (b); + + dbg("exit dabusb_fpga_download"); +-- +1.5.6.5 +
Attachment:
signature.asc
Description: This is a digitally signed message part