rpms/kernel-xen-2.6/devel git-iwlwifi-fixes.patch, NONE, 1.1.2.1 git-iwlwifi.patch, NONE, 1.1.2.1 git-wireless-dev.patch, NONE, 1.1.2.1 linux-2.6-ata-quirk.patch, NONE, 1.1.2.1 linux-2.6-crap-sysfs-workaround.patch, NONE, 1.1.2.1 linux-2.6-debug-extra-warnings.patch, NONE, 1.1.2.1 linux-2.6-defaults-pci_no_msi_mmconf.patch, NONE, 1.1.2.1 linux-2.6-dvb-spinlock.patch, NONE, 1.1.2.1 linux-2.6-firewire-check-condition.patch, NONE, 1.1.2.1 linux-2.6-firewire-context-run.patch, NONE, 1.1.2.1 linux-2.6-fix-pmops-1.patch, NONE, 1.1.2.1 linux-2.6-fix-pmops-2.patch, NONE, 1.1.2.1 linux-2.6-fix-pmops-3.patch, NONE, 1.1.2.1 linux-2.6-fix-pmops-4.patch, NONE, 1.1.2.1 linux-2.6-i82875-edac-pci-setup.patch, NONE, 1.1.2.1 linux-2.6-mpc52xx-fec.patch, NONE, 1.1.2.1 linux-2.6-mpc52xx-sdma.patch, NONE, 1.1.2.1 linux-2.6-ondemand-timer.patch, NONE, 1.1.2.1 linux-2.6-pmac-zilog.patch, NONE, 1.1.2.1 linux-2.6-powermac-generic-suspend-1.patch, NONE, 1.1.2.1 linux-2.6-powermac-generic-suspend-2.patch, NONE, 1.1.2.1 linux-2.6-powe! rmac-generic-suspend-3.patch, NONE, 1.1.2.1 linux-2.6-powermac-generic-suspend-4.patch, NONE, 1.1.2.1 linux-2.6-ps3-device-init.patch, NONE, 1.1.2.1 linux-2.6-ps3-ethernet-autoload.patch, NONE, 1.1.2.1 linux-2.6-ps3-ethernet-modular.patch, NONE, 1.1.2.1 linux-2.6-ps3-ethernet.patch, NONE, 1.1.2.1 linux-2.6-ps3-exports.patch, NONE, 1.1.2.1 linux-2.6-ps3-fix-slowdown-bug.patch, NONE, 1.1.2.1 linux-2.6-ps3-legacy-ioport.patch, NONE, 1.1.2.1 linux-2.6-ps3-memory-probe.patch, NONE, 1.1.2.1 linux-2.6-ps3-replace-irq-alloc-free.patch, NONE, 1.1.2.1 linux-2.6-ps3-sound.patch, NONE, 1.1.2.1 linux-2.6-ps3-stable-patches.patch, NONE, 1.1.2.1 linux-2.6-ps3-storage.patch, NONE, 1.1.2.1 linux-2.6-ps3av-export-header.patch, NONE, 1.1.2.1 linux-2.6-ps3fb-panic.patch, NONE, 1.1.2.1 linux-2.6-rt2x00-scan-fix.patch, NONE, 1.1.2.1 linux-2.6-uevent-ps3.patch, NONE, 1.1.2.1 linux-2.6-warnings-inline.patch, NONE, 1.1.2.1 linux-2.6-xen-blktap-cleanup.patch, NONE, 1.1.2.1 linux-2.6-xen-blktap-dynamic-major.patch, NONE, 1.1.2.1 linux-2.6-xe! n-blktap-fixes.patch,NONE,1.1.2.1 linux-2.6-xen-blktap-sysfs.p! atch,NON

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Tue Apr 10 12:42:50 UTC 2007


Author: ehabkost

Update of /cvs/dist/rpms/kernel-xen-2.6/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv6120

Modified Files:
      Tag: private-ehabkost-2_6_21-branch
	kernel-xen.spec linux-2.6-compile-fixes.patch 
	linux-2.6-debug-no-quiet.patch 
	linux-2.6-debug-sizeof-structs.patch 
	linux-2.6-debug-sleep-in-irq-warning.patch 
	linux-2.6-debug-sysfs-crash-debugging-xen.patch 
	linux-2.6-debug-sysfs-crash-debugging.patch 
	linux-2.6-debug-taint-vm.patch linux-2.6-devmem.patch 
	linux-2.6-execshield.patch linux-2.6-firewire.patch 
	linux-2.6-modsign-core.patch linux-2.6-modsign-crypto.patch 
	linux-2.6-modsign-include.patch linux-2.6-modsign-ksign.patch 
	linux-2.6-modsign-mpilib.patch linux-2.6-modsign-script.patch 
	linux-2.6-silence-noise.patch linux-2.6-squashfs.patch 
	linux-2.6-utrace.patch linux-2.6-xen-execshield.patch 
	linux-2.6-xen.patch sources 
Added Files:
      Tag: private-ehabkost-2_6_21-branch
	git-iwlwifi-fixes.patch git-iwlwifi.patch 
	git-wireless-dev.patch linux-2.6-ata-quirk.patch 
	linux-2.6-crap-sysfs-workaround.patch 
	linux-2.6-debug-extra-warnings.patch 
	linux-2.6-defaults-pci_no_msi_mmconf.patch 
	linux-2.6-dvb-spinlock.patch 
	linux-2.6-firewire-check-condition.patch 
	linux-2.6-firewire-context-run.patch 
	linux-2.6-fix-pmops-1.patch linux-2.6-fix-pmops-2.patch 
	linux-2.6-fix-pmops-3.patch linux-2.6-fix-pmops-4.patch 
	linux-2.6-i82875-edac-pci-setup.patch 
	linux-2.6-mpc52xx-fec.patch linux-2.6-mpc52xx-sdma.patch 
	linux-2.6-ondemand-timer.patch linux-2.6-pmac-zilog.patch 
	linux-2.6-powermac-generic-suspend-1.patch 
	linux-2.6-powermac-generic-suspend-2.patch 
	linux-2.6-powermac-generic-suspend-3.patch 
	linux-2.6-powermac-generic-suspend-4.patch 
	linux-2.6-ps3-device-init.patch 
	linux-2.6-ps3-ethernet-autoload.patch 
	linux-2.6-ps3-ethernet-modular.patch 
	linux-2.6-ps3-ethernet.patch linux-2.6-ps3-exports.patch 
	linux-2.6-ps3-fix-slowdown-bug.patch 
	linux-2.6-ps3-legacy-ioport.patch 
	linux-2.6-ps3-memory-probe.patch 
	linux-2.6-ps3-replace-irq-alloc-free.patch 
	linux-2.6-ps3-sound.patch linux-2.6-ps3-stable-patches.patch 
	linux-2.6-ps3-storage.patch 
	linux-2.6-ps3av-export-header.patch 
	linux-2.6-ps3fb-panic.patch linux-2.6-rt2x00-scan-fix.patch 
	linux-2.6-uevent-ps3.patch linux-2.6-warnings-inline.patch 
	linux-2.6-xen-blktap-cleanup.patch 
	linux-2.6-xen-blktap-dynamic-major.patch 
	linux-2.6-xen-blktap-fixes.patch 
	linux-2.6-xen-blktap-sysfs.patch 
	linux-2.6-xen-execshield-lazy-exec-limit.patch 
	linux-2.6-xen-pvfb.patch 
	linux-2.6-xen-x86_64-add-ppoll-pselect.patch nouveau-drm.patch 
Log Message:
Importing all patches from rawhide kernel

The patches are not applying cleanly yet. They will be updated on a
further commit, after the 2.6.21 xen patch is integrated.

Patches not related to xen that are not on rawhide were removed.



git-iwlwifi-fixes.patch:
 base.c |    1 +
 1 files changed, 1 insertion(+)

--- NEW FILE git-iwlwifi-fixes.patch ---
--- linux-2.6.20.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c.orig	2007-03-22 14:13:12.000000000 -0400
+++ linux-2.6.20.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c	2007-03-22 14:13:23.000000000 -0400
@@ -12377,6 +12377,7 @@ static int ipw_pci_probe(struct pci_dev 
 	err = ipw_read_ucode(priv);
 	if (err) {
 		IPW_ERROR("Could not read microcode from disk: %d\n", err);
+		mutex_unlock(&priv->mutex);
 		goto out_remove_sysfs;
 	}
 

git-iwlwifi.patch:
 Kconfig              |    1 
 Makefile             |    1 
 iwlwifi/Kconfig      |   52 
 iwlwifi/Makefile     |    2 
 iwlwifi/base.c       |13753 +++++++++++++++++++++++++++++++++++++++++++++++++++
 iwlwifi/iwlwifi.h    | 1297 ++++
 iwlwifi/iwlwifi_hw.h | 1877 ++++++
 7 files changed, 16983 insertions(+)

--- NEW FILE git-iwlwifi.patch ---
--- linux-2.6.20.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c.orig	2007-03-22 15:13:39.000000000 -0400
+++ linux-2.6.20.noarch/drivers/net/wireless/mac80211/iwlwifi/base.c	2007-03-22 15:14:05.000000000 -0400
@@ -0,0 +1,13753 @@
+/******************************************************************************
+
+  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
+
+  Portions of this file are derived from the ipw3945 project, as well
+  as portions of the ieee80211 subsystem header files.
+
+  802.11 status code portion of this file from ethereal-0.10.6:
+    Copyright 2000, Axis Communications AB
+    Ethereal - Network traffic analyzer
+    By Gerald Combs <gerald at ethereal.com>
+    Copyright 1998 Gerald Combs
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin at linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+/*
+ * Theory of operation:
+ *
+ * The primary NIC mode of operation is configured within the RXON command.
+ * As such, there are two instances of RXON data -- staging_rxon and
+ * active_rxon.  The former is used to configure the device, the later to
+ * reflect the actual currently active configuration.
+ *
+ * After configuring staging_rxon, it is activated by calling
+ * ipw_commit_rxon(). The ipw_commit_rxon() will ensure the correct sequence
+ * of commands are invoked on the hardware to result in Tx being possible
+ * (if the channel is appropriate for Tx)
+ *
+ * About the threading and lock model of the driver...
+ *
+ * There are three paths of execution through the driver.
+ *
+ * 1.  ioctl based (wireless extensions, netdev, etc.)
+ * 2.  interrupt based
+ * 3.  scheduled work queue items
+ *
+ * As soon as an interrupt comes in, it schedules a tasklet.  That tasklet,
+ * when run, does any HW checks, pulls any data from the read queue,
+ * and schedules other layers to do the actual work.
+ *
+ * NOTE: This driver is a work in progress.  It is currently structured
+ * in a way that we can add support for the next wireless adapter
+ * available from Intel.
+ *
+ * Our current focus is as follows:
+ * 1.  Get the driver working w/ mac80211 in STA(client) mode.
+ * 2.  Clean up the dual-driver code from function redirection to
+ *     if/else switches where the code detlas are minimal.
+ * 3.  Evaluate the amount of delta between the hardware versions and
+ *     possibly split iwlwifi into multiple drivers for each piece of
+ *     HW, sharing as much base code as possible (would result in
+ *     multiple driver files on disk vs. a single module that works
+ *     with multiple hardware types)
+ * 4.  Document the uCode regulatory enforcement
+ * 5.  Document the rate scaling capabilities of the 3945
+ * 6.  Provide an initial rate scaling algorithm tailored for the
+ *     statistic data exposed by the 3945.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <net/iw_handler.h>
+
+//#define BIT(x) (1 << (x))
+#include <net/mac80211.h>
+#include <net/ieee80211.h>
+
+#include <../net/mac80211/ieee80211_rate.h>
+
+#include <net/ieee80211_radiotap.h>
+	
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+#include <linux/if_arp.h>
+#include <asm/div64.h>
+
+#include "iwlwifi.h"
+
+#define IWLWIFI_VERSION "0.0.11k"
+
+#define DRV_DESCRIPTION	"Intel(R) Wireless Link driver for Linux"
+#define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
+#define DRV_VERSION     IWLWIFI_VERSION
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+/*MAC80211  move this to mac80211 files */
+#define IEEE80211_FC(type, stype) cpu_to_le16((type << 2) | (stype << 4))
+
+#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010
+
+#define IEEE80211_24GHZ_BAND     (1<<0)
+#define IEEE80211_52GHZ_BAND     (1<<1)
+
+#define IEEE80211_CCK_RATE_1MB                  0x02
+#define IEEE80211_CCK_RATE_2MB                  0x04
+#define IEEE80211_CCK_RATE_5MB                  0x0B
+#define IEEE80211_CCK_RATE_11MB                 0x16
+#define IEEE80211_OFDM_RATE_6MB                 0x0C
+#define IEEE80211_OFDM_RATE_9MB                 0x12
+#define IEEE80211_OFDM_RATE_12MB                0x18
+#define IEEE80211_OFDM_RATE_18MB                0x24
+#define IEEE80211_OFDM_RATE_24MB                0x30
+#define IEEE80211_OFDM_RATE_36MB                0x48
+#define IEEE80211_OFDM_RATE_48MB                0x60
+#define IEEE80211_OFDM_RATE_54MB                0x6C
+#define IEEE80211_BASIC_RATE_MASK               0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK             (1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK             (1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK             (1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK            (1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK            (1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK            (1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK           (1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK           (1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK           (1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK           (1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK           (1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK           (1<<11)
+
+#define IEEE80211_CCK_RATES_MASK                0x0000000F
+#define IEEE80211_CCK_BASIC_RATES_MASK  (IEEE80211_CCK_RATE_1MB_MASK | \
+        IEEE80211_CCK_RATE_2MB_MASK)
+#define IEEE80211_CCK_DEFAULT_RATES_MASK        (IEEE80211_CCK_BASIC_RATES_MASK | \
+        IEEE80211_CCK_RATE_5MB_MASK | \
+        IEEE80211_CCK_RATE_11MB_MASK)
+
+#define IEEE80211_OFDM_RATES_MASK               0x00000FF0
+#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
+        IEEE80211_OFDM_RATE_12MB_MASK | \
+        IEEE80211_OFDM_RATE_24MB_MASK)
+#define IEEE80211_OFDM_DEFAULT_RATES_MASK       (IEEE80211_OFDM_BASIC_RATES_MASK | \
+        IEEE80211_OFDM_RATE_9MB_MASK  | \
+        IEEE80211_OFDM_RATE_18MB_MASK | \
+        IEEE80211_OFDM_RATE_36MB_MASK | \
+        IEEE80211_OFDM_RATE_48MB_MASK | \
+        IEEE80211_OFDM_RATE_54MB_MASK)
+#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
+                                IEEE80211_CCK_DEFAULT_RATES_MASK)
+
+#define IEEE80211_NUM_OFDM_RATES            8
+#define IEEE80211_NUM_CCK_RATES             4
+#define IEEE80211_OFDM_SHIFT_MASK_A         4
+
+/*MAC80211 end */
+
+static u32 ipw_debug_level;
+
+static int param_debug = 0;
+static int param_channel = 0;
+static int param_mode = 0;
+static int param_auto_create = 1;	/* def: create new adhoc network if needed */
+static int param_led = 1;	/* def: use LEDs */
+static int param_disable = 0;	/* def: enable radio */
+static int param_antenna = 0;	/* def: 0 = both antennas (use diversity) */
+static int param_hwcrypto = 0;	/* def: using software encryption */
+static int param_qos_enable = 1;
+static int param_rtap_iface = 0;
+
+static const char ipw_modes[] = {
+	'a', 'b', 'g', '?'
+};
[...16611 lines suppressed...]
+	u8 flags;
+	/* We have 15 LSB to use as we please (MSB indicates
+	 * a frame Rx'd from the HW).  We encode the following
+	 * information into the sequence field:
+	 *
+	 *  0:7    index in fifo
+	 *  8:13   fifo selection
+	 * 14:14   bit indicating if this packet references the 'extra'
+	 *         storage at the end of the memory queue
+	 * 15:15   (Rx indication)
+	 *
+	 */
+	u16 sequence;
+
+	/* command data follows immediately */
+	u8 data[0];
+} __attribute__ ((packed));
+
+// Used for passing to driver number of successes and failures per rate
+struct rate_histogram {
+	union {
+		u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} success;
+	union {
+		u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} failed;
+} __attribute__ ((packed));
+
+/* statistics command response */
+
+struct statistics_rx_phy {
+	u32 ina_cnt;
+	u32 fina_cnt;
+	u32 plcp_err;
+	u32 crc32_err;
+	u32 overrun_err;
+	u32 early_overrun_err;
+	u32 crc32_good;
+	u32 false_alarm_cnt;
+	u32 fina_sync_err_cnt;
+	u32 sfd_timeout;
+	u32 fina_timeout;
+	u32 unresponded_rts;
+	u32 rxe_frame_limit_overrun;
+	u32 sent_ack_cnt;
+	u32 sent_cts_cnt;
+} __attribute__ ((packed));
+
+struct statistics_rx {
+	struct statistics_rx_phy ofdm;
+	struct statistics_rx_phy cck;
+	u32 bogus_cts;
+	u32 bogus_ack;
+	u32 non_bssid_frames;
+	u32 filtered_frames;
+	u32 non_channel_beacons;
+} __attribute__ ((packed));
+
+struct statistics_tx {
+	u32 preamble_cnt;
+	u32 rx_detected_cnt;
+	u32 bt_prio_defer_cnt;
+	u32 bt_prio_kill_cnt;
+	u32 few_bytes_cnt;
+	u32 cts_timeout;
+	u32 ack_timeout;
+	u32 expected_ack_cnt;
+	u32 actual_ack_cnt;
+} __attribute__ ((packed));
+
+struct statistics_dbg {
+	u32 burst_check;
+	u32 burst_count;
+	u32 reserved[4];
+} __attribute__ ((packed));
+
+struct statistics_div {
+	u32 tx_on_a;
+	u32 tx_on_b;
+	u32 exec_time;
+	u32 probe_time;
+} __attribute__ ((packed));
+
+struct statistics_general {
+	u32 temperature;
+	struct statistics_dbg dbg;
+	u32 sleep_time;
+	u32 slots_out;
+	u32 slots_idle;
+	u32 ttl_timestamp;
+	struct statistics_div div;
+} __attribute__ ((packed));
+
+struct ipw_notif_statistics {
+	u32 flag;
+	struct statistics_rx rx;
+	struct statistics_tx tx;
+	struct statistics_general general;
+} __attribute__ ((packed));
+
+struct ipw_rx_packet {
+	u32 len;
+	struct ipw_cmd_header hdr;
+	union {
+		struct ipw_alive_resp alive_frame;
+		struct ipw_rx_frame rx_frame;
+		struct ipw_tx_resp tx_resp;
+		struct ipw_spectrum_notification spectrum_notif;
+		struct ipw_csa_notification csa_notif;
+		struct ipw_error_resp err_resp;
+		struct ipw_card_state_notif card_state_notif;
+		struct ipw_notif_statistics stats;
+		struct BeaconNtfSpecifics beacon_status;
+		struct ipw_add_sta_resp add_sta;
+		struct ipw_sleep_notification sleep_notif;
+		u32 status;
+		u8 raw[0];
+	} u;
+} __attribute__ ((packed));
+
+#define IPW_RX_FRAME_SIZE        (4 + sizeof(struct ipw_rx_frame))
+
+struct ipw_multicast_addr {
+	u8 num_of_multicast_addresses;
+	u8 reserved[3];
+	u8 mac1[6];
+	u8 mac2[6];
+	u8 mac3[6];
+	u8 mac4[6];
+} __attribute__ ((packed));
+
+struct ipw_tgi_tx_key {
+	u8 key_id;
+	u8 security_type;
+	u8 station_index;
+	u8 flags;
+	u8 key[16];
+	u32 tx_counter[2];
+} __attribute__ ((packed));
+
+struct ipw_associate {
+	u8 channel;
+	u8 auth_type:4, auth_key:4;
+	u8 assoc_type;
+	u8 reserved;
+	u16 policy_support;
+	u8 preamble_length;
+	u8 ieee_mode;
+	u8 bssid[ETH_ALEN];
+	u32 assoc_tsf_msw;
+	u32 assoc_tsf_lsw;
+	u16 capability;
+	u16 listen_interval;
+	u16 beacon_interval;
+	u8 dest[ETH_ALEN];
+	u16 atim_window;
+	u8 smr;
+	u8 reserved1;
+	u16 reserved2;
+	u16 assoc_id;
+	u8 erp_value;
+} __attribute__ ((packed));
+
+#define IPW_SUPPORTED_RATES_IE_LEN         8
+
+struct ipw_supported_rates {
+	u8 ieee_mode;
+	u8 num_rates;
+	u8 purpose;
+	u8 reserved;
+	u8 supported_rates[IPW_MAX_RATES];
+} __attribute__ ((packed));
+
+struct ipw_channel_tx_power {
+	u8 channel_number;
+	s8 tx_power;
+} __attribute__ ((packed));
+
+
+#define IPW_RX_BUF_SIZE 3000
+
+#endif				/* __iwlwifi_hw_h__ */
--- linux-2.6.20.noarch/drivers/net/wireless/mac80211/Makefile.orig	2007-03-22 15:13:39.000000000 -0400
+++ linux-2.6.20.noarch/drivers/net/wireless/mac80211/Makefile	2007-03-22 15:13:46.000000000 -0400
@@ -4,3 +4,4 @@ obj-$(CONFIG_ADM8211)		+= adm8211/
 obj-$(CONFIG_P54_COMMON)	+= p54/
 obj-$(CONFIG_ZD1211RW_MAC80211)	+= zd1211rw/
 obj-$(CONFIG_RTL818X)		+= rtl818x/
+obj-$(CONFIG_IWLWIFI)		+= iwlwifi/
--- linux-2.6.20.noarch/drivers/net/wireless/mac80211/Kconfig.orig	2007-03-22 15:13:39.000000000 -0400
+++ linux-2.6.20.noarch/drivers/net/wireless/mac80211/Kconfig	2007-03-22 15:13:46.000000000 -0400
@@ -4,3 +4,4 @@ source "drivers/net/wireless/mac80211/ad
 source "drivers/net/wireless/mac80211/p54/Kconfig"
 source "drivers/net/wireless/mac80211/zd1211rw/Kconfig"
 source "drivers/net/wireless/mac80211/rtl818x/Kconfig"
+source "drivers/net/wireless/mac80211/iwlwifi/Kconfig"

git-wireless-dev.patch:
 CREDITS                                                 |   31 
 MAINTAINERS                                             |   54 
 drivers/Kconfig                                         |    2 
 drivers/Makefile                                        |    1 
 drivers/net/Makefile                                    |    2 
 drivers/net/wireless/Kconfig                            |  120 
 drivers/net/wireless/Makefile                           |    3 
 drivers/net/wireless/bcm43xx/Kconfig                    |    3 
 drivers/net/wireless/hostap/Kconfig                     |    3 
 drivers/net/wireless/mac80211/Kconfig                   |    6 
 drivers/net/wireless/mac80211/Makefile                  |    6 
 drivers/net/wireless/mac80211/README                    |    2 
 drivers/net/wireless/mac80211/adm8211/Kconfig           |   25 
 drivers/net/wireless/mac80211/adm8211/Makefile          |    1 
 drivers/net/wireless/mac80211/adm8211/adm8211.c         | 2188 +++++++
 drivers/net/wireless/mac80211/adm8211/adm8211.h         |  622 ++
 drivers/net/wireless/mac80211/bcm43xx/Kconfig           |  100 
 drivers/net/wireless/mac80211/bcm43xx/Makefile          |   16 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx.h         |  870 ++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_debugfs.c |  433 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_debugfs.h |  110 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_dma.c     | 1297 ++++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_dma.h     |  361 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_leds.c    |  300 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_leds.h    |   56 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_lo.c      | 1081 +++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_lo.h      |   92 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.c    | 3988 ++++++++++++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_main.h    |  156 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pcmcia.c  |  163 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pcmcia.h  |   22 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_phy.c     | 4235 +++++++++++++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_phy.h     |  309 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pio.c     |  671 ++
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_pio.h     |  170 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_power.c   |   82 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_power.h   |   41 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_sysfs.c   |  232 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_sysfs.h   |    9 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_tables.c  |  376 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_tables.h  |   28 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_vstack.c  |  202 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_vstack.h  |   83 
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_xmit.c    |  615 +
 drivers/net/wireless/mac80211/bcm43xx/bcm43xx_xmit.h    |  215 
 drivers/net/wireless/mac80211/p54/Kconfig               |   10 
 drivers/net/wireless/mac80211/p54/Makefile              |    4 
 drivers/net/wireless/mac80211/p54/net2280.h             |  452 +
 drivers/net/wireless/mac80211/p54/prism54.h             |   77 
 drivers/net/wireless/mac80211/p54/prism54common.c       |  807 ++
 drivers/net/wireless/mac80211/p54/prism54common.h       |  304 
 drivers/net/wireless/mac80211/p54/prism54magic.h        |   77 
 drivers/net/wireless/mac80211/p54/prism54pci.c          |  698 ++
 drivers/net/wireless/mac80211/p54/prism54pci.h          |  106 
 drivers/net/wireless/mac80211/p54/prism54usb.c          |  946 +++
 drivers/net/wireless/mac80211/p54/prism54usb.h          |  133 
 drivers/net/wireless/mac80211/rt2x00/Kconfig            |   86 
 drivers/net/wireless/mac80211/rt2x00/Makefile           |    9 
 drivers/net/wireless/mac80211/rt2x00/rt2400pci.c        | 2586 ++++++++
 drivers/net/wireless/mac80211/rt2x00/rt2400pci.h        |  931 +++
 drivers/net/wireless/mac80211/rt2x00/rt2500pci.c        | 2883 +++++++++
 drivers/net/wireless/mac80211/rt2x00/rt2500pci.h        | 1198 +++
 drivers/net/wireless/mac80211/rt2x00/rt2500usb.c        | 2718 ++++++++
 drivers/net/wireless/mac80211/rt2x00/rt2500usb.h        |  746 ++
 drivers/net/wireless/mac80211/rt2x00/rt2x00.h           | 1069 +++
 drivers/net/wireless/mac80211/rt2x00/rt2x00debug.c      |  380 +
 drivers/net/wireless/mac80211/rt2x00/rt2x00debug.h      |   70 
 drivers/net/wireless/mac80211/rt2x00/rt2x00dev.c        |  231 
 drivers/net/wireless/mac80211/rt2x00/rt2x00lib.h        |   74 
 drivers/net/wireless/mac80211/rt2x00/rt2x00mac.c        |  540 +
 drivers/net/wireless/mac80211/rt2x00/rt2x00pci.h        |   39 
 drivers/net/wireless/mac80211/rt2x00/rt2x00usb.h        |   82 
 drivers/net/wireless/mac80211/rt2x00/rt61pci.c          | 3364 ++++++++++
 drivers/net/wireless/mac80211/rt2x00/rt61pci.h          | 1361 ++++
 drivers/net/wireless/mac80211/rt2x00/rt73usb.c          | 3024 +++++++++
 drivers/net/wireless/mac80211/rt2x00/rt73usb.h          |  945 +++
 drivers/net/wireless/mac80211/rtl818x/Kconfig           |    9 
 drivers/net/wireless/mac80211/rtl818x/Makefile          |    2 
 drivers/net/wireless/mac80211/rtl818x/rtl8187.h         |  126 
 drivers/net/wireless/mac80211/rtl818x/rtl8187_dev.c     |  720 ++
 drivers/net/wireless/mac80211/rtl818x/rtl8187_rtl8225.c |  747 ++
 drivers/net/wireless/mac80211/rtl818x/rtl8187_rtl8225.h |   30 
 drivers/net/wireless/mac80211/rtl818x/rtl818x.h         |  177 
 drivers/net/wireless/mac80211/zd1211rw/Kconfig          |   19 
 drivers/net/wireless/mac80211/zd1211rw/Makefile         |   11 
 drivers/net/wireless/mac80211/zd1211rw/zd_chip.c        | 1676 +++++
 drivers/net/wireless/mac80211/zd1211rw/zd_chip.h        |  909 ++
 drivers/net/wireless/mac80211/zd1211rw/zd_def.h         |   57 
 drivers/net/wireless/mac80211/zd1211rw/zd_ieee80211.h   |   67 
 drivers/net/wireless/mac80211/zd1211rw/zd_mac.c         |  705 ++
 drivers/net/wireless/mac80211/zd1211rw/zd_mac.h         |  250 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf.c          |  156 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf.h          |   81 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf_al2230.c   |  436 +
 drivers/net/wireless/mac80211/zd1211rw/zd_rf_al7230b.c  |  274 
 drivers/net/wireless/mac80211/zd1211rw/zd_rf_rf2959.c   |  279 
 drivers/net/wireless/mac80211/zd1211rw/zd_usb.c         | 1327 ++++
 drivers/net/wireless/mac80211/zd1211rw/zd_usb.h         |  241 
 drivers/net/wireless/mac80211/zd1211rw/zd_util.c        |   82 
 drivers/net/wireless/mac80211/zd1211rw/zd_util.h        |   29 
 drivers/net/wireless/zd1211rw/Kconfig                   |    3 
 drivers/ssb/Kconfig                                     |   93 
 drivers/ssb/Makefile                                    |   11 
 drivers/ssb/driver_chipcommon.c                         |  402 +
 drivers/ssb/driver_mipscore.c                           |  258 
 drivers/ssb/driver_pcicore.c                            |  556 +
 drivers/ssb/main.c                                      | 1042 +++
 drivers/ssb/pci.c                                       |  667 ++
 drivers/ssb/pcihost_wrapper.c                           |  104 
 drivers/ssb/pcmcia.c                                    |  256 
 drivers/ssb/scan.c                                      |  407 +
 drivers/ssb/ssb_private.h                               |  151 
 drivers/usb/host/Kconfig                                |   13 
 drivers/usb/host/ohci-hcd.c                             |   21 
 drivers/usb/host/ohci-ssb.c                             |  254 
 include/linux/Kbuild                                    |    2 
 include/linux/crc-itu-t.h                               |   27 
 include/linux/eeprom_93cx6.h                            |   77 
 include/linux/ieee80211.h                               |  330 +
 include/linux/netdevice.h                               |    7 
 include/linux/nl80211.h                                 |  275 
 include/linux/ssb/ssb.h                                 |  403 +
 include/linux/ssb/ssb_driver_chipcommon.h               |  387 +
 include/linux/ssb/ssb_driver_extif.h                    |  163 
 include/linux/ssb/ssb_driver_mips.h                     |   47 
 include/linux/ssb/ssb_driver_pci.h                      |  108 
 include/linux/ssb/ssb_regs.h                            |  294 
 include/net/cfg80211.h                                  |  169 
 include/net/iw_handler.h                                |    3 
 include/net/mac80211.h                                  | 1074 +++
 include/net/wireless.h                                  |  160 
 lib/Kconfig                                             |   16 
 lib/Makefile                                            |    3 
 lib/crc-itu-t.c                                         |   64 
 lib/eeprom_93cx6.c                                      |  344 +
 net/Kconfig                                             |   12 
 net/Makefile                                            |    2 
 net/core/Makefile                                       |    1 
 net/core/dev.c                                          |   33 
 net/core/wireless.c                                     | 2371 -------
 net/ieee80211/Kconfig                                   |    3 
 net/mac80211/Kconfig                                    |   71 
 net/mac80211/Makefile                                   |   26 
 net/mac80211/aes_ccm.c                                  |  155 
 net/mac80211/aes_ccm.h                                  |   26 
 net/mac80211/fifo_qdisc.c                               |  102 
 net/mac80211/hostapd_ioctl.h                            |  347 +
 net/mac80211/ieee80211.c                                | 4940 ++++++++++++++++
 net/mac80211/ieee80211_cfg.c                            |   90 
 net/mac80211/ieee80211_cfg.h                            |    9 
 net/mac80211/ieee80211_common.h                         |   98 
 net/mac80211/ieee80211_i.h                              |  720 ++
 net/mac80211/ieee80211_iface.c                          |  372 +
 net/mac80211/ieee80211_ioctl.c                          | 3304 ++++++++++
 net/mac80211/ieee80211_key.h                            |   89 
 net/mac80211/ieee80211_led.c                            |   91 
 net/mac80211/ieee80211_led.h                            |   32 
 net/mac80211/ieee80211_rate.c                           |  140 
 net/mac80211/ieee80211_rate.h                           |  161 
 net/mac80211/ieee80211_scan.c                           |  344 +
 net/mac80211/ieee80211_sta.c                            | 3013 +++++++++
 net/mac80211/ieee80211_sysfs.c                          |  718 ++
 net/mac80211/ieee80211_sysfs.h                          |   12 
 net/mac80211/ieee80211_sysfs_sta.c                      |  438 +
 net/mac80211/michael.c                                  |  104 
 net/mac80211/michael.h                                  |   20 
 net/mac80211/rc80211_simple.c                           |  399 +
 net/mac80211/sta_info.c                                 |  461 +
 net/mac80211/sta_info.h                                 |  150 
 net/mac80211/tkip.c                                     |  341 +
 net/mac80211/tkip.h                                     |   36 
 net/mac80211/wep.c                                      |  328 +
 net/mac80211/wep.h                                      |   40 
 net/mac80211/wme.c                                      |  679 ++
 net/mac80211/wme.h                                      |   38 
 net/mac80211/wpa.c                                      |  846 ++
 net/mac80211/wpa.h                                      |   31 
 net/wireless/Kconfig                                    |   46 
 net/wireless/Makefile                                   |   17 
 net/wireless/core.c                                     |  323 +
 net/wireless/core.h                                     |   77 
 net/wireless/nl80211.c                                  | 1051 +++
 net/wireless/nl80211.h                                  |   17 
 net/wireless/sysfs.c                                    |  125 
 net/wireless/sysfs.h                                    |    9 
 net/wireless/wext-common.c                              |  663 ++
 net/wireless/wext-compat.c                              |  819 ++
 net/wireless/wext-export.c                              |   29 
 net/wireless/wext-mod.c                                 |   20 
 net/wireless/wext-old.c                                 | 1461 ++++
 net/wireless/wext.h                                     |   51 
 191 files changed, 85347 insertions(+), 2487 deletions(-)

--- NEW FILE git-wireless-dev.patch ---
--- /dev/null	2007-03-09 11:47:32.684268720 -0500
+++ linux-2.6.20.noarch/include/net/wireless.h	2007-03-20 11:29:04.000000000 -0400
@@ -0,0 +1,160 @@
+#ifndef __NET_WIRELESS_H
+#define __NET_WIRELESS_H
+
+/*
+ * 802.11 device management
+ *
+ * Copyright 2007	Johannes Berg <johannes at sipsolutions.net>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <net/cfg80211.h>
+
+/**
+ * struct wiphy - wireless hardware description
+ * @idx: the wiphy index assigned to this item
+ * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
+ */
+struct wiphy {
+	/* assign these fields before you register the wiphy */
+
+	/* permanent MAC address */
+	u8 perm_addr[ETH_ALEN];
+
+	/* If multiple wiphys are registered and you're handed e.g.
+	 * a regular netdev with assigned ieee80211_ptr, you won't
+	 * know whether it points to a wiphy your driver has registered
+	 * or not. Assign this to something global to your driver to
+	 * help determine whether you own this wiphy or not. */
+	void *privid;
+
+	/* fields below are read-only, assigned by cfg80211 */
+
+	/* the item in /sys/class/ieee80211/ points to this,
+	 * you need use set_wiphy_dev() (see below) */
+	struct device dev;
+
+	/* dir in debugfs: ieee80211/<wiphyname> */
+	struct dentry *debugfsdir;
+
+	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+/** struct wireless_dev - wireless per-netdev state
+ *
+ * This structure must be allocated by the driver/stack
+ * that uses the ieee80211_ptr field in struct net_device
+ * (this is intentional so it can be allocated along with
+ * the netdev.)
+ *
+ * @wiphy: pointer to hardware description
+ */
+struct wireless_dev {
+	struct wiphy *wiphy;
+
+	/* private to the generic wireless code */
+	struct cfg80211_config pending_config;
+	struct list_head list;
+	struct net_device *netdev;
+};
+
+/**
+ * wiphy_priv - return priv from wiphy
+ */
+static inline void *wiphy_priv(struct wiphy *wiphy)
+{
+	BUG_ON(!wiphy);
+	return &wiphy->priv;
+}
+
+/**
+ * set_wiphy_dev - set device pointer for wiphy
+ */
+static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev)
+{
+	wiphy->dev.parent = dev;
+}
+
+/**
+ * wiphy_dev - get wiphy dev pointer
+ */
+static inline struct device *wiphy_dev(struct wiphy *wiphy)
+{
+	return wiphy->dev.parent;
+}
+
+/**
+ * wiphy_name - get wiphy name
+ */
+static inline char *wiphy_name(struct wiphy *wiphy)
+{
+	return wiphy->dev.bus_id;
+}
+
+/**
+ * wdev_priv - return wiphy priv from wireless_dev
+ */
+static inline void *wdev_priv(struct wireless_dev *wdev)
+{
+	BUG_ON(!wdev);
+	return wiphy_priv(wdev->wiphy);
+}
+
+/**
+ * wiphy_new - create a new wiphy for use with cfg80211
+ *
+ * create a new wiphy and associate the given operations with it.
+ * @sizeof_priv bytes are allocated for private use.
+ *
+ * the returned pointer must be assigned to each netdev's
+ * ieee80211_ptr for proper operation.
+ */
+struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv);
+
+/**
+ * wiphy_register - register a wiphy with cfg80211
+ *
+ * register the given wiphy
+ *
+ * Returns a non-negative wiphy index or a negative error code.
+ */
+extern int wiphy_register(struct wiphy *wiphy);
+
+/**
+ * wiphy_unregister - deregister a wiphy from cfg80211
+ *
+ * unregister a device with the given priv pointer.
+ * After this call, no more requests can be made with this priv
+ * pointer, but the call may sleep to wait for an outstanding
+ * request that is being handled.
+ */
+extern void wiphy_unregister(struct wiphy *wiphy);
+
+/**
+ * wiphy_free - free wiphy
+ */
+extern void wiphy_free(struct wiphy *wiphy);
+
+
+/*
+ * internal definitions for wireless
+ */
+
+#if defined(CONFIG_CFG80211_WEXT_COMPAT) || defined(CONFIG_WIRELESS_EXT)
+int wext_ioctl(unsigned int cmd, struct ifreq *ifreq, void __user *arg);
+int wireless_proc_init(void);
+#else
+static inline
+int wext_ioctl(unsigned int cmd, struct ifreq *ifreq, void __user *arg)
+{
+	return -EINVAL;
+}
+static inline int wireless_proc_init(void)
+{
+	return 0;
+}
+#endif
+
+#endif /* __NET_WIRELESS_H */
--- /dev/null	2007-03-09 11:47:32.684268720 -0500
+++ linux-2.6.20.noarch/include/net/mac80211.h	2007-03-20 11:29:04.000000000 -0400
@@ -0,0 +1,1074 @@
+/*
+ * Low-level hardware driver -- IEEE 802.11 driver (80211.o) interface
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MAC80211_H
+#define MAC80211_H
+
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/wireless.h>
+#include <linux/device.h>
+#include <linux/ieee80211.h>
+#include <net/wireless.h>
+#include <net/cfg80211.h>
+
+/* Note! Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+ * IEEE 802.11 code call after this, e.g., from a scheduled tasklet (in
+ * software interrupt context).
+ */
+
+/*
+ * Frame format used when passing frame between low-level hardware drivers
+ * and IEEE 802.11 driver the same as used in the wireless media, i.e.,
+ * buffers start with IEEE 802.11 header and include the same octets that
[...88476 lines suppressed...]
+			break;
+
+		buf = kmalloc(100, GFP_ATOMIC);
+		if (!buf)
+			break;
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "bcn_int=%d", bss->beacon_int);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "rssi=%d", bss->rssi);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "capab=0x%04x", bss->capability);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  buf);
+
+		/* dispaly all support rates in readable format */
+		p = current_ev + IW_EV_LCP_LEN;
+		iwe.cmd = SIOCGIWRATE;
+		/* Those two flags are ignored... */
+		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+		for (i = 0; i < bss->supp_rates_len; i++) {
+			iwe.u.bitrate.value = ((bss->supp_rates[i] &
+							0x7f) * 500000);
+			p = iwe_stream_add_value(current_ev, p,
+					end_buf, &iwe, IW_EV_PARAM_LEN);
+		}
+		/* Check if we added any rate */
+		if((p - current_ev) > IW_EV_LCP_LEN)
+			current_ev = p;
+
+		kfree(buf);
+		break;
+	} while (0);
+
+	return current_ev;
+}
+
+
+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	char *current_ev = buf;
+	char *end_buf = buf + len;
+	struct ieee80211_sta_bss *bss;
+
+	spin_lock_bh(&local->sta_bss_lock);
+	list_for_each_entry(bss, &local->sta_bss_list, list) {
+		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
+			spin_unlock_bh(&local->sta_bss_lock);
+			return -E2BIG;
+		}
+		current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
+						       end_buf);
+	}
+	spin_unlock_bh(&local->sta_bss_lock);
+	return current_ev - buf;
+}
+
+
+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+	kfree(ifsta->extra_ie);
+	if (len == 0) {
+		ifsta->extra_ie = NULL;
+		ifsta->extra_ie_len = 0;
+		return 0;
+	}
+	ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
+	if (!ifsta->extra_ie) {
+		ifsta->extra_ie_len = 0;
+		return -ENOMEM;
+	}
+	memcpy(ifsta->extra_ie, ie, len);
+	ifsta->extra_ie_len = len;
+	return 0;
+}
+
+
+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+					 struct sk_buff *skb, u8 *bssid,
+					 u8 *addr)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata = NULL;
+	struct net_device *sta_dev = NULL;
+
+	/* TODO: Could consider removing the least recently used entry and
+	 * allow new one to be added. */
+	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
+			       "entry " MAC_FMT "\n", dev->name, MAC_ARG(addr));
+		}
+		return NULL;
+	}
+
+	spin_lock_bh(&local->sub_if_lock);
+	list_for_each_entry(sdata, &local->sub_if_list, list)
+		if (sdata->type == IEEE80211_IF_TYPE_IBSS &&
+		    memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
+			sta_dev = sdata->dev;
+			break;
+		}
+	spin_unlock_bh(&local->sub_if_lock);
+
+	if (!sta_dev)
+		return NULL;
+
+	printk(KERN_DEBUG "%s: Adding new IBSS station " MAC_FMT " (dev=%s)\n",
+	       dev->name, MAC_ARG(addr), sta_dev->name);
+
+	sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+	if (!sta)
+		return NULL;
+
+	sta->dev = sta_dev;
+	sta->supp_rates = sdata->u.sta.supp_rates_bits;
+
+	rate_control_rate_init(sta, local);
+
+	return sta; /* caller will call sta_info_put() */
+}
+
+
+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+	       dev->name, reason);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
+	    sdata->type != IEEE80211_IF_TYPE_IBSS)
+		return -EINVAL;
+
+	ieee80211_send_deauth(dev, ifsta, reason);
+	ieee80211_set_disassoc(dev, ifsta, 1);
+	return 0;
+}
+
+
+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+	printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+	       dev->name, reason);
+
+	if (sdata->type != IEEE80211_IF_TYPE_STA)
+		return -EINVAL;
+
+	if (!ifsta->associated)
+		return -1;
+
+	ieee80211_send_disassoc(dev, ifsta, reason);
+	ieee80211_set_disassoc(dev, ifsta, 0);
+	return 0;
+}
--- /dev/null	2007-03-09 11:47:32.684268720 -0500
+++ linux-2.6.20.noarch/net/mac80211/ieee80211_cfg.h	2007-03-20 11:29:04.000000000 -0400
@@ -0,0 +1,9 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ */
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+extern struct cfg80211_ops mac80211_config_ops;
+
+#endif /* __IEEE80211_CFG_H */
--- linux-2.6.20.noarch/net/ieee80211/Kconfig.orig	2007-03-20 11:27:30.000000000 -0400
+++ linux-2.6.20.noarch/net/ieee80211/Kconfig	2007-03-20 11:29:04.000000000 -0400
@@ -56,7 +56,8 @@ config IEEE80211_CRYPT_CCMP
 
 config IEEE80211_CRYPT_TKIP
 	tristate "IEEE 802.11i TKIP encryption"
-	depends on IEEE80211 && NET_RADIO
+	depends on IEEE80211
+	select WIRELESS_EXT
 	select CRYPTO
 	select CRYPTO_MICHAEL_MIC
 	select CRYPTO_ECB

linux-2.6-ata-quirk.patch:
 Makefile |    1 +
 quirks.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

--- NEW FILE linux-2.6-ata-quirk.patch ---
--- linux-2.6.20/arch/ia64/kernel/quirks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.20_fix/arch/ia64/kernel/quirks.c	2007-02-13 13:56:34.000000000 -0500
@@ -0,0 +1,45 @@
+/*
+ * This file contains work-arounds for ia64 platform bugs.
+ */
+#include <linux/pci.h>
+
+/*
+ * quirk_intel_ide_controller: If an ide/ata controller is
+ * at legacy mode, BIOS might initiates BAR(bar 0~3 and 5)
+ * with incorrect value. This quirk will reset the incorrect
+ * value to 0.
+ */
+static void __devinit quirk_intel_ide_controller(struct pci_dev *dev)
+{
+	unsigned int pos;
+	struct resource *res;
+	int fixed = 0;
+	u8 tmp8;
+
+	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+
+	/* TODO: What if one channel is in native mode ... */
+	pci_read_config_byte(dev, PCI_CLASS_PROG, &tmp8);
+	if ((tmp8 & 5) == 5)
+		return;
+
+	for( pos = 0; pos < 6; pos ++ ) {
+		res = &dev->resource[pos];
+		if (!(res->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
+
+		if (!res->start && res->end) {
+			res->start = res->end = 0;
+			res->flags = 0;
+			fixed = 1;
+		}
+	}
+	if (fixed)
+		printk(KERN_WARNING
+			"PCI device %s: BIOS resource configuration fixed.\n",
+			pci_name(dev));
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11, quirk_intel_ide_controller);
+
--- linux-2.6.20/arch/ia64/kernel/Makefile	2007-02-08 02:13:41.000000000 -0500
+++ linux-2.6.20_fix/arch/ia64/kernel/Makefile	2007-02-12 09:49:39.000000000 -0500
@@ -33,6 +33,7 @@ obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)	+= uncached.o
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj-$(CONFIG_PCI_MSI)		+= msi_ia64.o
+obj-$(CONFIG_PCI)		+= quirks.o
 mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 
 obj-$(CONFIG_IA64_ESI)		+= esi.o

linux-2.6-crap-sysfs-workaround.patch:
 class.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE linux-2.6-crap-sysfs-workaround.patch ---
--- linux-2.6.20.ppc/drivers/base/class.c~	2007-02-04 18:44:54.000000000 +0000
+++ linux-2.6.20.ppc/drivers/base/class.c	2007-03-28 00:23:30.000000000 +0100
@@ -380,7 +380,7 @@ static int deprecated_class_uevent(char 
 	struct device *dev = class_dev->dev;
 	char *path;
 
-	if (!dev)
+	//if (!dev)
 		return 0;
 
 	/* add device, backing this class device (deprecated) */

linux-2.6-debug-extra-warnings.patch:
 Makefile |    4 +++-
 1 files changed, 3 insertions(+), 1 deletion(-)

--- NEW FILE linux-2.6-debug-extra-warnings.patch ---
-Werror-implicit-function-declaration
 This makes builds fail sooner if something is implicitly defined instead
 of having to wait half an hour for it to fail at the linking stage.

-Wextra -Wno-unused-parameter -Wno-missing-field-initializers
 Enable the kitchen-sink of 'mostly harmless' warnings, and exclude
 some of the really noisy ones.

Signed-off-by: Dave Jones <davej at redhat.com>

diff --git a/Makefile b/Makefile
index 6393738..c5d60f2 100644
--- a/Makefile
+++ b/Makefile
@@ -313,7 +313,9 @@ LINUXINCLUDE    := -Iinclude \
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-                   -fno-strict-aliasing -fno-common
+                   -fno-strict-aliasing -fno-common \
+		   -Werror-implicit-function-declaration \
+		   -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-strict-aliasing
 AFLAGS          := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)

linux-2.6-defaults-pci_no_msi_mmconf.patch:
 Documentation/kernel-parameters.txt   |    5 +++++
 arch/i386/pci/common.c                |    6 +++++-
 drivers/pci/msi.c                     |    6 +++++-
 linux-2.6.20.noarch/drivers/pci/pci.c |    2 ++
 linux-2.6.20.noarch/drivers/pci/pci.h |    2 ++
 5 files changed, 19 insertions(+), 2 deletions(-)

--- NEW FILE linux-2.6-defaults-pci_no_msi_mmconf.patch ---
Disable PCI MSI and MMCONFIG by default, add kernel parameters
to enable them.

Original mmconfig patch by Kyle McMartin <kyle at ubuntu.com>

Signed-off-by: Chuck Ebbert <cebbert at redhat.com>

---
 Documentation/kernel-parameters.txt |    5 +++++
 arch/i386/pci/common.c              |    6 +++++-
 drivers/pci/msi.c                   |    6 +++++-
 drivers/pci/pci.c                   |    2 ++
 drivers/pci/pci.h                   |    2 ++
 5 files changed, 19 insertions(+), 2 deletions(-)

--- linux-2.6.20.noarch.orig/drivers/pci/msi.c
+++ linux-2.6.20.noarch/drivers/pci/msi.c
@@ -28,7 +28,7 @@ static DEFINE_SPINLOCK(msi_lock);
 static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
 static struct kmem_cache* msi_cachep;
 
-static int pci_msi_enable = 1;
+static int pci_msi_enable = 0;
 
 static int msi_cache_init(void)
 {
@@ -977,6 +977,10 @@ void pci_no_msi(void)
 {
 	pci_msi_enable = 0;
 }
+void pci_yes_msi(void)
+{
+	pci_msi_enable = 1;
+}
 
 EXPORT_SYMBOL(pci_enable_msi);
 EXPORT_SYMBOL(pci_disable_msi);
--- linux-2.6.20.noarch.orig/Documentation/kernel-parameters.txt
+++ linux-2.6.20.noarch/Documentation/kernel-parameters.txt
@@ -1197,8 +1197,13 @@ and is between 256 and 4096 characters. 
 				Mechanism 1.
 		conf2		[IA-32] Force use of PCI Configuration
 				Mechanism 2.
+		mmconf		[IA-32,X86_64] Enable use of MMCONFIG for PCI
+				Configuration
 		nommconf	[IA-32,X86_64] Disable use of MMCONFIG for PCI
 				Configuration
+		msi		[MSI] If the PCI_MSI kernel config parameter is
+				enabled, this kernel boot option can be used to
+				enable the use of MSI interrupts system-wide.
 		nomsi		[MSI] If the PCI_MSI kernel config parameter is
 				enabled, this kernel boot option can be used to
 				disable the use of MSI interrupts system-wide.
--- linux-2.6.20.noarch.orig/arch/i386/pci/common.c
+++ linux-2.6.20.noarch/arch/i386/pci/common.c
@@ -18,7 +18,7 @@
 #include "pci.h"
 
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
-				PCI_PROBE_MMCONF;
+				0; /* PCI_PROBE_MMCONF */
 
 static int pci_bf_sort;
 int pci_routeirq;
@@ -292,6 +292,10 @@ char * __devinit  pcibios_setup(char *st
 		pci_probe &= ~PCI_PROBE_MMCONF;
 		return NULL;
 	}
+	else if (!strcmp(str, "mmconf")) {
+		pci_probe |= PCI_PROBE_MMCONF;
+		return NULL;
+	}
 #endif
 	else if (!strcmp(str, "noacpi")) {
 		acpi_noirq_set();
--- linux-2.6.20.noarch/drivers/pci/pci.c~	2007-04-04 01:33:08.000000000 -0400
+++ linux-2.6.20.noarch/drivers/pci/pci.c	2007-04-04 01:33:33.000000000 -0400
@@ -1358,6 +1358,8 @@ static int __devinit pci_setup(char *str
 		if (*str && (str = pcibios_setup(str)) && *str) {
 			if (!strcmp(str, "nomsi")) {
 				pci_no_msi();
+			} else if (!strcmp(str, "msi")) {
+				pci_yes_msi();
 			} else if (!strncmp(str, "cbiosize=", 9)) {
 				pci_cardbus_io_size = memparse(str + 9, &str);
 			} else if (!strncmp(str, "cbmemsize=", 10)) {
--- linux-2.6.20.noarch/drivers/pci/pci.h~	2007-04-04 01:34:07.000000000 -0400
+++ linux-2.6.20.noarch/drivers/pci/pci.h	2007-04-04 01:34:31.000000000 -0400
@@ -47,8 +47,10 @@ extern unsigned int pci_pm_d3_delay;
 
 #ifdef CONFIG_PCI_MSI
 void pci_no_msi(void);
+void pci_yes_msi(void);
 #else
 static inline void pci_no_msi(void) { }
+static inline void pci_yes_msi(void) { }
 #endif
 
 #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)

linux-2.6-dvb-spinlock.patch:
 flexcop-pci.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

--- NEW FILE linux-2.6-dvb-spinlock.patch ---

# HG changeset patch
# User Mauro Carvalho Chehab <mchehab at infradead.org>
# Date Thu Apr 05 14:28:11 2007 -0300
# Node ID a80058519added447f1cdd870334282e8ac3226e
# parent: 628ca02d680721a85e9b2fca7cf4b782b31f9443
Fix Kernel Bugzilla #8301: spinlock fix for flexcop-pci

# Now, patch author (just the main one), on a From: field
# Please change below if the committer is not the patch author.
#
>From Hendrik Borghorst <hendrik at borghorst.org>

# Then a detailed description:
If you modprobe the b2c2-flexcop-pci module you got a hardlock of your system.
This is due the usage of spin_lock before spin_lock_init is called.

# At the end Signed-off-by: fields by patch author and committer, at least.
#
Signed-Off-By: Patrick Boettcher <pb at linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab at infradead.org>

--- a/drivers/media/dvb/b2c2/flexcop-pci.c	Wed Apr 04 13:11:06 2007 -0700
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c	Thu Apr 05 14:28:11 2007 -0300
@@ -143,10 +143,11 @@ static irqreturn_t flexcop_pci_isr(int i
 {
 	struct flexcop_pci *fc_pci = dev_id;
 	struct flexcop_device *fc = fc_pci->fc_dev;
+	unsigned long flags;
 	flexcop_ibi_value v;
 	irqreturn_t ret = IRQ_HANDLED;
 
-	spin_lock_irq(&fc_pci->irq_lock);
+	spin_lock_irqsave(&fc_pci->irq_lock,flags);
 
 	v = fc->read_ibi_reg(fc,irq_20c);
 
@@ -210,7 +211,7 @@ static irqreturn_t flexcop_pci_isr(int i
 		ret = IRQ_NONE;
 	}
 
-	spin_unlock_irq(&fc_pci->irq_lock);
+	spin_unlock_irqrestore(&fc_pci->irq_lock,flags);
 
 	return ret;
 }
@@ -309,12 +310,12 @@ static int flexcop_pci_init(struct flexc
 	}
 
 	pci_set_drvdata(fc_pci->pdev, fc_pci);
-
+	spin_lock_init(&fc_pci->irq_lock);
 	if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
 					IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
 		goto err_pci_iounmap;
 
-	spin_lock_init(&fc_pci->irq_lock);
+
 
 	fc_pci->init_state |= FC_PCI_INIT;
 	return ret;


linux-2.6-firewire-check-condition.patch:
 fw-sbp2.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

--- NEW FILE linux-2.6-firewire-check-condition.patch ---
>From ad12bc442b70e3bfd831e197dbaeabcd6086a137 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Kristian_H=C3=B8gsberg?= <krh at redhat.com>
Date: Fri, 6 Apr 2007 10:44:57 -0400
Subject: [PATCH] Report CHECK_CONDITION up to the SCSI stack.

On some devices (e.g. the 3rd generation iPod) the command agent
dies a lot, typically on SCSI level errors.  When it dies it returns
an CHECK_CONDITION status, and we need to propagate this up to the
SCSI stack so it properly recover the device.
---
 drivers/firewire/fw-sbp2.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 2e5479b..28d0884 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -746,7 +746,8 @@ static struct fw_driver sbp2_driver = {
 	.id_table = sbp2_id_table,
 };
 
-static unsigned int sbp2_status_to_sense_data(u8 * sbp2_status, u8 * sense_data)
+static unsigned int
+sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
 {
 	sense_data[0] = 0x70;
 	sense_data[1] = 0x0;
@@ -767,20 +768,19 @@ static unsigned int sbp2_status_to_sense_data(u8 * sbp2_status, u8 * sense_data)
 
 	switch (sbp2_status[0] & 0x3f) {
 	case SAM_STAT_GOOD:
-		return DID_OK;
+		return DID_OK << 16;
 
 	case SAM_STAT_CHECK_CONDITION:
-		/* return CHECK_CONDITION << 1 | DID_OK << 16; */
-		return DID_OK;
+		return DID_OK << 16 | CHECK_CONDITION << 1;
 
 	case SAM_STAT_BUSY:
-		return DID_BUS_BUSY;
+		return DID_BUS_BUSY << 16;
 
 	case SAM_STAT_CONDITION_MET:
 	case SAM_STAT_RESERVATION_CONFLICT:
 	case SAM_STAT_COMMAND_TERMINATED:
 	default:
-		return DID_ERROR;
+		return DID_ERROR << 16;
 	}
 }
 
@@ -801,26 +801,26 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 
 		switch (status_get_response(*status)) {
 		case SBP2_STATUS_REQUEST_COMPLETE:
-			result = DID_OK;
+			result = DID_OK << 16;
 			break;
 		case SBP2_STATUS_TRANSPORT_FAILURE:
-			result = DID_BUS_BUSY;
+			result = DID_BUS_BUSY << 16;
 			break;
 		case SBP2_STATUS_ILLEGAL_REQUEST:
 		case SBP2_STATUS_VENDOR_DEPENDENT:
 		default:
-			result = DID_ERROR;
+			result = DID_ERROR << 16;
 			break;
 		}
 
-		if (result == DID_OK && status_get_len(*status) > 1)
+		if (result == DID_OK << 16 && status_get_len(*status) > 1)
 			result = sbp2_status_to_sense_data(status_get_data(*status),
 							   orb->cmd->sense_buffer);
 	} else {
 		/* If the orb completes with status == NULL, something
 		 * went wrong, typically a bus reset happened mid-orb
 		 * or when sending the write (less likely). */
-		result = DID_BUS_BUSY;
+		result = DID_BUS_BUSY << 16;
 	}
 
 	dma_unmap_single(device->card->device, orb->base.request_bus,
@@ -841,7 +841,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 				 sizeof orb->request_buffer_bus,
 				 DMA_FROM_DEVICE);
 
-	orb->cmd->result = result << 16;
+	orb->cmd->result = result;
 	orb->done(orb->cmd);
 
 	kfree(orb);
-- 
1.4.4.2


linux-2.6-firewire-context-run.patch:
 fw-ohci.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE linux-2.6-firewire-context-run.patch ---
>From 758c2744e2a64aa0c20d229b1f08a6d6b48b8d17 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Kristian_H=C3=B8gsberg?= <krh at redhat.com>
Date: Fri, 6 Apr 2007 10:32:26 -0400
Subject: [PATCH] Check CONTEXT_RUN, not CONTEXT_ACTIVE to se if context is running.

Doh.
---
 drivers/firewire/fw-ohci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 6f9895d..fca7eac 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -661,7 +661,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
 
 	/* If the context isn't already running, start it up. */
 	reg = reg_read(ctx->ohci, control_set(ctx->regs));
-	if ((reg & CONTEXT_ACTIVE) == 0)
+	if ((reg & CONTEXT_RUN) == 0)
 		context_run(ctx, 0);
 
 	return 0;
-- 
1.4.4.2


linux-2.6-fix-pmops-1.patch:
 arch/arm/common/sharpsl_pm.c |    1 
 arch/arm/mach-at91/pm.c      |    1 
 arch/arm/mach-omap1/pm.c     |    1 
 arch/arm/mach-omap2/pm.c     |    1 
 arch/arm/mach-pxa/pm.c       |    4 ---
 arch/arm/mach-sa1100/pm.c    |    7 -----
 arch/arm/plat-s3c24xx/pm.c   |    9 ------
 arch/sh/boards/hp6xx/pm.c    |    7 -----
 include/linux/pm.h           |   23 +++++++++--------
 kernel/power/disk.c          |   56 ++++++++++++++++++++++++++++---------------
 kernel/power/main.c          |    6 +++-
 11 files changed, 54 insertions(+), 62 deletions(-)

--- NEW FILE linux-2.6-fix-pmops-1.patch ---
>From johannes at sipsolutions.net Wed Mar 21 15:56:28 2007
Date: Wed, 21 Mar 2007 15:56:28 +0100
From: Johannes Berg <johannes at sipsolutions.net>
To: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-pm at lists.linux-foundation.org, David Brownell <david-b at pacbell.net>, Pavel Machek <pavel at ucw.cz>
Subject: [PATCH 1/3] rework pm_ops pm_disk_mode, kill misuse

The pm_ops.pm_disk_mode is used in totally bogus ways since
nobody really seems to understand what it actually does.

This patch clarifies the pm_disk_mode description.

It also removes all the arm and sh users that think they can veto
suspend to disk via pm_ops; not so since the user can always
do echo shutdown > /sys/power/disk, they need to find a better
way involving Kconfig or such.

ACPI is the only user left with a non-zero pm_disk_mode.

The patch also sets the default mode to shutdown again, but
when a new pm_ops is registered its pm_disk_mode is selected
as default, that way the default stays for ACPI where it is
apparently required.

Signed-off-by: Johannes Berg <johannes at sipsolutions.net>
Cc: David Brownell <david-b at pacbell.net>
Cc: Pavel Machek <pavel at ucw.cz>
Cc: linux-pm at lists.linux-foundation.org

---
 arch/arm/common/sharpsl_pm.c |    1 
 arch/arm/mach-at91/pm.c      |    1 
 arch/arm/mach-omap1/pm.c     |    1 
 arch/arm/mach-omap2/pm.c     |    1 
 arch/arm/mach-pxa/pm.c       |    4 ---
 arch/arm/mach-sa1100/pm.c    |    7 -----
 arch/arm/plat-s3c24xx/pm.c   |    9 ------
 arch/sh/boards/hp6xx/pm.c    |    7 -----
 include/linux/pm.h           |   23 +++++++++--------
 kernel/power/disk.c          |   56 ++++++++++++++++++++++++++++---------------
 kernel/power/main.c          |    6 +++-
 11 files changed, 54 insertions(+), 62 deletions(-)

--- linux-2.6.orig/include/linux/pm.h	2007-03-20 12:41:38.423214909 +0100
+++ linux-2.6/include/linux/pm.h	2007-03-20 12:42:02.253214909 +0100
@@ -112,6 +112,8 @@ typedef int __bitwise suspend_state_t;
 
 typedef int __bitwise suspend_disk_method_t;
 
+/* invalid must be 0 so struct pm_ops initialisers can leave it out */
+#define PM_DISK_INVALID		((__force suspend_disk_method_t) 0)
 #define	PM_DISK_FIRMWARE	((__force suspend_disk_method_t) 1)
 #define	PM_DISK_PLATFORM	((__force suspend_disk_method_t) 2)
 #define	PM_DISK_SHUTDOWN	((__force suspend_disk_method_t) 3)
@@ -137,17 +139,16 @@ typedef int __bitwise suspend_disk_metho
  * @finish: Called when the system has left the given state and all devices
  *	are resumed. The return value is ignored.
  *
- * @pm_disk_mode: Set to the disk method that the user should be able to
- *	configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN,
- *	%PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC
- *	are always allowed, currently only %PM_DISK_PLATFORM
- *	makes sense. If the user then choses %PM_DISK_PLATFORM,
- *	the @prepare call will be called before suspending to disk
- *	(if present), the @enter call should be present and will
- *	be called after all state has been saved and the machine
- *	is ready to be shut down/suspended/..., and the @finish
- *	callback is called after state has been restored. All
- *	these calls are called with %PM_SUSPEND_DISK as the state.
+ * @pm_disk_mode: The generic code always allows one of the shutdown methods
+ *	%PM_DISK_SHUTDOWN, %PM_DISK_REBOOT, %PM_DISK_TEST and
+ *	%PM_DISK_TESTPROC. If this variable is set, the mode it is set
+ *	to is allowed in addition to those modes and is also made default.
+ *	When this mode is sent selected, the @prepare call will be called
+ *	before suspending to disk (if present), the @enter call should be
+ *	present and will be called after all state has been saved and the
+ *	machine is ready to be powered off; the @finish callback is called
+ *	after state has been restored. All these calls are called with
+ *	%PM_SUSPEND_DISK as the state.
  */
 struct pm_ops {
 	int (*valid)(suspend_state_t state);
--- linux-2.6.orig/kernel/power/disk.c	2007-03-20 12:41:38.463214909 +0100
+++ linux-2.6/kernel/power/disk.c	2007-03-20 12:42:02.263214909 +0100
@@ -39,7 +39,13 @@ static inline int platform_prepare(void)
 {
 	int error = 0;
 
-	if (pm_disk_mode == PM_DISK_PLATFORM) {
+	switch (pm_disk_mode) {
+	case PM_DISK_TEST:
+	case PM_DISK_TESTPROC:
+	case PM_DISK_SHUTDOWN:
+	case PM_DISK_REBOOT:
+		break;
+	default:
 		if (pm_ops && pm_ops->prepare)
 			error = pm_ops->prepare(PM_SUSPEND_DISK);
 	}
@@ -48,30 +54,32 @@ static inline int platform_prepare(void)
 
 /**
  *	power_down - Shut machine down for hibernate.
- *	@mode:		Suspend-to-disk mode
  *
- *	Use the platform driver, if configured so, and return gracefully if it
- *	fails.
- *	Otherwise, try to power off and reboot. If they fail, halt the machine,
- *	there ain't no turning back.
+ *	Use the platform driver, if configured so; otherwise try
+ *	to power off or reboot.
  */
 
-static void power_down(suspend_disk_method_t mode)
+static void power_down(void)
 {
-	switch(mode) {
-	case PM_DISK_PLATFORM:
-		if (pm_ops && pm_ops->enter) {
-			kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-			pm_ops->enter(PM_SUSPEND_DISK);
-			break;
-		}
+
+	switch (pm_disk_mode) {
+	case PM_DISK_TEST:
+	case PM_DISK_TESTPROC:
+		break;
 	case PM_DISK_SHUTDOWN:
 		kernel_power_off();
 		break;
 	case PM_DISK_REBOOT:
 		kernel_restart(NULL);
 		break;
+	default:
+		if (pm_ops && pm_ops->enter) {
+			kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+			pm_ops->enter(PM_SUSPEND_DISK);
+			break;
+		}
 	}
+
 	kernel_halt();
 	/* Valid image is on the disk, if we continue we risk serious data corruption
 	   after resume. */
@@ -82,7 +90,13 @@ static void power_down(suspend_disk_meth
 
 static inline void platform_finish(void)
 {
-	if (pm_disk_mode == PM_DISK_PLATFORM) {
+	switch (pm_disk_mode) {
+	case PM_DISK_TEST:
+	case PM_DISK_TESTPROC:
+	case PM_DISK_SHUTDOWN:
+	case PM_DISK_REBOOT:
+		break;
+	default:
 		if (pm_ops && pm_ops->finish)
 			pm_ops->finish(PM_SUSPEND_DISK);
 	}
@@ -167,7 +181,7 @@ int pm_suspend_disk(void)
 		pr_debug("PM: writing image.\n");
 		error = swsusp_write();
 		if (!error)
-			power_down(pm_disk_mode);
+			power_down();
 		else {
 			swsusp_free();
 			goto Thaw;
@@ -347,10 +361,14 @@ static ssize_t disk_store(struct subsyst
 		}
 	}
 	if (mode) {
-		if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT ||
-		     mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) {
+		switch (mode) {
+		case PM_DISK_SHUTDOWN:
+		case PM_DISK_REBOOT:
+		case PM_DISK_TEST:
+		case PM_DISK_TESTPROC:
 			pm_disk_mode = mode;
-		} else {
+			break;
+		default:
 			if (pm_ops && pm_ops->enter &&
 			    (mode == pm_ops->pm_disk_mode))
 				pm_disk_mode = mode;
--- linux-2.6.orig/kernel/power/main.c	2007-03-20 12:41:38.543214909 +0100
+++ linux-2.6/kernel/power/main.c	2007-03-20 12:42:02.263214909 +0100
@@ -30,7 +30,7 @@
 DEFINE_MUTEX(pm_mutex);
 
 struct pm_ops *pm_ops;
-suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM;
+suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
 
 /**
  *	pm_set_ops - Set the global power method table. 
@@ -41,6 +41,10 @@ void pm_set_ops(struct pm_ops * ops)
 {
 	mutex_lock(&pm_mutex);
 	pm_ops = ops;
+	if (ops && ops->pm_disk_mode != PM_DISK_INVALID) {
+		pm_disk_mode = ops->pm_disk_mode;
+	} else
+		pm_disk_mode = PM_DISK_SHUTDOWN;
 	mutex_unlock(&pm_mutex);
 }
 
--- linux-2.6.orig/arch/arm/common/sharpsl_pm.c	2007-03-20 12:41:38.673214909 +0100
+++ linux-2.6/arch/arm/common/sharpsl_pm.c	2007-03-20 12:42:02.263214909 +0100
@@ -766,7 +766,6 @@ static void sharpsl_apm_get_power_status
 }
 
 static struct pm_ops sharpsl_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
 	.prepare	= pxa_pm_prepare,
 	.enter		= corgi_pxa_pm_enter,
 	.finish		= pxa_pm_finish,
--- linux-2.6.orig/arch/arm/mach-at91/pm.c	2007-03-20 12:41:38.743214909 +0100
+++ linux-2.6/arch/arm/mach-at91/pm.c	2007-03-20 12:42:02.263214909 +0100
@@ -201,7 +201,6 @@ error:
 
 
 static struct pm_ops at91_pm_ops ={
-	.pm_disk_mode	= 0,
 	.valid		= at91_pm_valid_state,
 	.prepare	= at91_pm_prepare,
 	.enter		= at91_pm_enter,
--- linux-2.6.orig/arch/arm/mach-omap1/pm.c	2007-03-20 12:41:38.763214909 +0100
+++ linux-2.6/arch/arm/mach-omap1/pm.c	2007-03-20 12:42:02.263214909 +0100
@@ -698,7 +698,6 @@ static struct irqaction omap_wakeup_irq 
 
 
 static struct pm_ops omap_pm_ops ={
-	.pm_disk_mode	= 0,
 	.prepare	= omap_pm_prepare,
 	.enter		= omap_pm_enter,
 	.finish		= omap_pm_finish,
--- linux-2.6.orig/arch/arm/mach-omap2/pm.c	2007-03-20 12:41:38.833214909 +0100
+++ linux-2.6/arch/arm/mach-omap2/pm.c	2007-03-20 12:42:02.263214909 +0100
@@ -370,7 +370,6 @@ static int omap2_pm_finish(suspend_state
 }
 
 static struct pm_ops omap_pm_ops = {
-	.pm_disk_mode	= 0,
 	.prepare	= omap2_pm_prepare,
 	.enter		= omap2_pm_enter,
 	.finish		= omap2_pm_finish,
--- linux-2.6.orig/arch/arm/mach-pxa/pm.c	2007-03-20 12:41:38.853214909 +0100
+++ linux-2.6/arch/arm/mach-pxa/pm.c	2007-03-20 12:42:02.263214909 +0100
@@ -223,11 +223,7 @@ int pxa_pm_finish(suspend_state_t state)
 
 EXPORT_SYMBOL_GPL(pxa_pm_finish);
 
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
 static struct pm_ops pxa_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
 	.prepare	= pxa_pm_prepare,
 	.enter		= pxa_pm_enter,
 	.finish		= pxa_pm_finish,
--- linux-2.6.orig/arch/arm/mach-sa1100/pm.c	2007-03-20 12:41:38.903214909 +0100
+++ linux-2.6/arch/arm/mach-sa1100/pm.c	2007-03-20 12:42:02.273214909 +0100
@@ -59,9 +59,6 @@ static int sa11x0_pm_enter(suspend_state
 	unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
 	struct timespec delta, rtc;
 
-	if (state != PM_SUSPEND_MEM)
-		return -EINVAL;
-
 	/* preserve current time */
 	rtc.tv_sec = RCNR;
 	rtc.tv_nsec = 0;
@@ -134,11 +131,7 @@ unsigned long sleep_phys_sp(void *sp)
 	return virt_to_phys(sp);
 }
 
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
 static struct pm_ops sa11x0_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
 	.enter		= sa11x0_pm_enter,
 };
 
--- linux-2.6.orig/arch/arm/plat-s3c24xx/pm.c	2007-03-20 12:41:38.953214909 +0100
+++ linux-2.6/arch/arm/plat-s3c24xx/pm.c	2007-03-20 12:42:02.273214909 +0100
@@ -511,11 +511,6 @@ static int s3c2410_pm_enter(suspend_stat
 		return -EINVAL;
 	}
 
-	if (state != PM_SUSPEND_MEM) {
-		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
-		return -EINVAL;
-	}
-
 	/* check if we have anything to wake-up with... bad things seem
 	 * to happen if you suspend with no wakeup (system will often
 	 * require a full power-cycle)
@@ -633,11 +628,7 @@ static int s3c2410_pm_finish(suspend_sta
 	return 0;
 }
 
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
 static struct pm_ops s3c2410_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
 	.prepare	= s3c2410_pm_prepare,
 	.enter		= s3c2410_pm_enter,
 	.finish		= s3c2410_pm_finish,
--- linux-2.6.orig/arch/sh/boards/hp6xx/pm.c	2007-03-20 12:41:39.163214909 +0100
+++ linux-2.6/arch/sh/boards/hp6xx/pm.c	2007-03-20 12:42:02.273214909 +0100
@@ -27,9 +27,6 @@ static int hp6x0_pm_enter(suspend_state_
 	u16 hd64461_stbcr;
 #endif
 
-	if (state != PM_SUSPEND_MEM)
-		return -EINVAL;
-
 #ifdef CONFIG_HD64461_ENABLER
 	outb(0, HD64461_PCC1CSCIER);
 
@@ -70,11 +67,7 @@ static int hp6x0_pm_enter(suspend_state_
 	return 0;
 }
 
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
 static struct pm_ops hp6x0_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
 	.enter		= hp6x0_pm_enter,
 };
 

--

linux-2.6-fix-pmops-2.patch:
 Documentation/power/interface.txt |   21 +++++----------------
 Documentation/power/states.txt    |   13 +++++++------
 Documentation/power/swsusp.txt    |   14 +++++---------
 include/linux/pm.h                |   13 ++++++-------
 kernel/power/disk.c               |   27 +++++++++++----------------
 5 files changed, 34 insertions(+), 54 deletions(-)

--- NEW FILE linux-2.6-fix-pmops-2.patch ---
>From johannes at sipsolutions.net Wed Mar 21 15:56:26 2007
Date: Wed, 21 Mar 2007 15:56:26 +0100
From: Johannes Berg <johannes at sipsolutions.net>
To: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-pm at lists.linux-foundation.org, Pavel Machek <pavel at ucw.cz>
Subject: [PATCH 2/3] power management: remove firmware disk mode

This patch removes the firmware disk suspend mode which is the wrong
approach, it is supposed to be used for implementing firmware-based disk
suspend but cannot actually be used for that.

Signed-off-by: Johannes Berg <johannes at sipsolutions.net>
Cc: Pavel Machek <pavel at ucw.cz>
Cc: linux-pm at lists.linux-foundation.org

---
 Documentation/power/interface.txt |   21 +++++----------------
 Documentation/power/states.txt    |   13 +++++++------
 Documentation/power/swsusp.txt    |   14 +++++---------
 include/linux/pm.h                |   13 ++++++-------
 kernel/power/disk.c               |   27 +++++++++++----------------
 5 files changed, 34 insertions(+), 54 deletions(-)

--- linux-2.6.orig/include/linux/pm.h	2007-03-21 15:44:54.663148946 +0100
+++ linux-2.6/include/linux/pm.h	2007-03-21 15:45:04.403148946 +0100
@@ -114,13 +114,12 @@ typedef int __bitwise suspend_disk_metho
 
 /* invalid must be 0 so struct pm_ops initialisers can leave it out */
 #define PM_DISK_INVALID		((__force suspend_disk_method_t) 0)
-#define	PM_DISK_FIRMWARE	((__force suspend_disk_method_t) 1)
-#define	PM_DISK_PLATFORM	((__force suspend_disk_method_t) 2)
-#define	PM_DISK_SHUTDOWN	((__force suspend_disk_method_t) 3)
-#define	PM_DISK_REBOOT		((__force suspend_disk_method_t) 4)
-#define	PM_DISK_TEST		((__force suspend_disk_method_t) 5)
-#define	PM_DISK_TESTPROC	((__force suspend_disk_method_t) 6)
-#define	PM_DISK_MAX		((__force suspend_disk_method_t) 7)
+#define	PM_DISK_PLATFORM	((__force suspend_disk_method_t) 1)
+#define	PM_DISK_SHUTDOWN	((__force suspend_disk_method_t) 2)
+#define	PM_DISK_REBOOT		((__force suspend_disk_method_t) 3)
+#define	PM_DISK_TEST		((__force suspend_disk_method_t) 4)
+#define	PM_DISK_TESTPROC	((__force suspend_disk_method_t) 5)
+#define	PM_DISK_MAX		((__force suspend_disk_method_t) 6)
 
 /**
  * struct pm_ops - Callbacks for managing platform dependent suspend states.
--- linux-2.6.orig/kernel/power/disk.c	2007-03-21 15:44:54.693148946 +0100
+++ linux-2.6/kernel/power/disk.c	2007-03-21 15:48:06.073148946 +0100
@@ -123,8 +123,6 @@ static int prepare_processes(void)
 /**
  *	pm_suspend_disk - The granpappy of hibernation power management.
  *
- *	If we're going through the firmware, then get it over with quickly.
- *
  *	If not, then call swsusp to do its thing, then figure out how
  *	to power down the system.
  */
@@ -301,7 +299,6 @@ late_initcall(software_resume);
 
 
 static const char * const pm_disk_modes[] = {
-	[PM_DISK_FIRMWARE]	= "firmware",
 	[PM_DISK_PLATFORM]	= "platform",
 	[PM_DISK_SHUTDOWN]	= "shutdown",
 	[PM_DISK_REBOOT]	= "reboot",
@@ -312,27 +309,25 @@ static const char * const pm_disk_modes[
 /**
  *	disk - Control suspend-to-disk mode
  *
- *	Suspend-to-disk can be handled in several ways. The greatest
- *	distinction is who writes memory to disk - the firmware or the OS.
- *	If the firmware does it, we assume that it also handles suspending
- *	the system.
- *	If the OS does it, then we have three options for putting the system
- *	to sleep - using the platform driver (e.g. ACPI or other PM registers),
- *	powering off the system or rebooting the system (for testing).
+ *	Suspend-to-disk can be handled in several ways. We have a few options
+ *	for putting the system to sleep - using the platform driver (e.g. ACPI
+ *	or other pm_ops), powering off the system or rebooting the system
+ *	(for testing) as well as the two test modes.
  *
- *	The system will support either 'firmware' or 'platform', and that is
- *	known a priori (and encoded in pm_ops). But, the user may choose
- *	'shutdown' or 'reboot' as alternatives.
+ *	The system can support 'platform', and that is known a priori (and
+ *	encoded in pm_ops). However, the user may choose 'shutdown' or 'reboot'
+ *	as alternatives, as well as the test modes 'test' and 'testproc'.
  *
  *	show() will display what the mode is currently set to.
  *	store() will accept one of
  *
- *	'firmware'
  *	'platform'
  *	'shutdown'
  *	'reboot'
+ *	'test'
+ *	'testproc'
  *
- *	It will only change to 'firmware' or 'platform' if the system
+ *	It will only change to 'platform' if the system
  *	supports it (as determined from pm_ops->pm_disk_mode).
  */
 
@@ -354,7 +349,7 @@ static ssize_t disk_store(struct subsyst
 	len = p ? p - buf : n;
 
 	mutex_lock(&pm_mutex);
-	for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) {
+	for (i = PM_DISK_PLATFORM; i < PM_DISK_MAX; i++) {
 		if (!strncmp(buf, pm_disk_modes[i], len)) {
 			mode = i;
 			break;
--- linux-2.6.orig/Documentation/power/interface.txt	2007-03-21 15:45:17.873148946 +0100
+++ linux-2.6/Documentation/power/interface.txt	2007-03-21 15:49:26.673148946 +0100
@@ -18,17 +18,10 @@ states.
 
 
 /sys/power/disk controls the operating mode of the suspend-to-disk
-mechanism. Suspend-to-disk can be handled in several ways. The
-greatest distinction is who writes memory to disk - the firmware or
-the kernel. If the firmware does it, we assume that it also handles
-suspending the system. 
-
-If the kernel does it, then we have three options for putting the system
-to sleep - using the platform driver (e.g. ACPI or other PM
-registers), powering off the system or rebooting the system (for
-testing). The system will support either 'firmware' or 'platform', and
-that is known a priori. But, the user may choose 'shutdown' or
-'reboot' as alternatives. 
+mechanism. Suspend-to-disk can be handled in several ways. We have a
+few options for putting the system to sleep - using the platform driver
+(e.g. ACPI or other pm_ops), powering off the system or rebooting the
+system (for testing).
 
 Additionally, /sys/power/disk can be used to turn on one of the two testing
 modes of the suspend-to-disk mechanism: 'testproc' or 'test'.  If the
@@ -44,16 +37,12 @@ is being slow and which device drivers a
 Reading from this file will display what the mode is currently set
 to. Writing to this file will accept one of
 
-       'firmware'
-       'platform'
+       'platform' (only if the platform supports it)
        'shutdown'
        'reboot'
        'testproc'
        'test'
 
-It will only change to 'firmware' or 'platform' if the system supports
-it. 
-
 /sys/power/image_size controls the size of the image created by
 the suspend-to-disk mechanism.  It can be written a string
 representing a non-negative integer that will be used as an upper
--- linux-2.6.orig/Documentation/power/states.txt	2007-03-21 15:45:17.993148946 +0100
+++ linux-2.6/Documentation/power/states.txt	2007-03-21 15:51:18.763148946 +0100
@@ -62,17 +62,18 @@ setup via another operating system for i
 inconvenience, this method requires minimal work by the kernel, since
 the firmware will also handle restoring memory contents on resume. 
 
-If the kernel is responsible for persistently saving state, a mechanism
-called 'swsusp' (Swap Suspend) is used to write memory contents to
-free swap space. swsusp has some restrictive requirements, but should
-work in most cases. Some, albeit outdated, documentation can be found
-in Documentation/power/swsusp.txt. 
+For suspend-to-disk, a mechanism called swsusp called 'swsusp' (Swap
+Suspend) is used to write memory contents to free swap space.
+swsusp has some restrictive requirements, but should work in most
+cases. Some, albeit outdated, documentation can be found in
+Documentation/power/swsusp.txt. Alternatively, userspace can do most
+of the actual suspend to disk work, see userland-swsusp.txt.
 
 Once memory state is written to disk, the system may either enter a
 low-power state (like ACPI S4), or it may simply power down. Powering
 down offers greater savings, and allows this mechanism to work on any
 system. However, entering a real low-power state allows the user to
-trigger wake up events (e.g. pressing a key or opening a laptop lid). 
+trigger wake up events (e.g. pressing a key or opening a laptop lid).
 
 A transition from Suspend-to-Disk to the On state should take about 30
 seconds, though it's typically a bit more with the current
--- linux-2.6.orig/Documentation/power/swsusp.txt	2007-03-21 15:45:18.133148946 +0100
+++ linux-2.6/Documentation/power/swsusp.txt	2007-03-21 15:52:20.423148946 +0100
@@ -156,8 +156,7 @@ instead set the PF_NOFREEZE process flag
 be very careful).
 
 
-Q: What is the difference between "platform", "shutdown" and
-"firmware" in /sys/power/disk?
+Q: What is the difference between "platform" and "shutdown"?
 
 A:
 
@@ -166,11 +165,8 @@ shutdown: save state in linux, then tell
 platform: save state in linux, then tell bios to powerdown and blink
           "suspended led"
 
-firmware: tell bios to save state itself [needs BIOS-specific suspend
-	  partition, and has very little to do with swsusp]
-
-"platform" is actually right thing to do, but "shutdown" is most
-reliable.
+"platform" is actually right thing to do where supported, but
+"shutdown" is most reliable (except on ACPI systems).
 
 Q: I do not understand why you have such strong objections to idea of
 selective suspend.
@@ -388,8 +384,8 @@ while the system is asleep, maintaining 
 modes like "suspend-to-RAM" or "standby".  (Don't write "disk" to the
 /sys/power/state file; write "standby" or "mem".)  We've not seen any
 hardware that can use these modes through software suspend, although in
-theory some systems might support "platform" or "firmware" modes that
-won't break the USB connections.
+theory some systems might support "platform" modes that won't break the
+USB connections.
 
 Remember that it's always a bad idea to unplug a disk drive containing a
 mounted filesystem.  That's true even when your system is asleep!  The

--

linux-2.6-fix-pmops-3.patch:
 arch/arm/common/sharpsl_pm.c |    1 +
 arch/arm/mach-omap1/pm.c     |    1 +
 arch/arm/mach-omap2/pm.c     |    1 +
 arch/arm/mach-pnx4008/pm.c   |   35 +----------------------------------
 arch/arm/mach-pxa/pm.c       |    1 +
 arch/arm/mach-sa1100/pm.c    |    1 +
 arch/arm/plat-s3c24xx/pm.c   |   19 +------------------
 arch/sh/boards/hp6xx/pm.c    |    1 +
 drivers/acpi/sleep/main.c    |   13 +++++++++++--
 include/linux/pm.h           |    4 ++++
 kernel/power/main.c          |   13 +++++++++++++
 11 files changed, 36 insertions(+), 54 deletions(-)

--- NEW FILE linux-2.6-fix-pmops-3.patch ---
>From johannes at sipsolutions.net Wed Mar 21 15:56:31 2007
Date: Wed, 21 Mar 2007 15:56:31 +0100
From: Johannes Berg <johannes at sipsolutions.net>
To: Andrew Morton <akpm at linux-foundation.org>
Cc: linux-pm at lists.linux-foundation.org, David Brownell <david-b at pacbell.net>, Pavel Machek <pavel at ucw.cz>
Subject: [PATCH 3/3] power management: implement pm_ops.valid for everybody

Almost all users of pm_ops only support mem sleep, don't check in .valid
and don't reject any others in .prepare so users can be confused if they
check /sys/power/state, especially when new states are added (these would
then result in s-t-r although they're supposed to be something different).

This patch implements a generic pm_valid_only_mem function that is then
exported for users and puts it to use in almost all existing pm_ops.

Signed-off-by: Johannes Berg <johannes at sipsolutions.net>
Cc: David Brownell <david-b at pacbell.net>
Cc: Pavel Machek <pavel at ucw.cz>
Cc: linux-pm at lists.linux-foundation.org

---
 arch/arm/common/sharpsl_pm.c |    1 +
 arch/arm/mach-omap1/pm.c     |    1 +
 arch/arm/mach-omap2/pm.c     |    1 +
 arch/arm/mach-pnx4008/pm.c   |   35 +----------------------------------
 arch/arm/mach-pxa/pm.c       |    1 +
 arch/arm/mach-sa1100/pm.c    |    1 +
 arch/arm/plat-s3c24xx/pm.c   |   19 +------------------
 arch/sh/boards/hp6xx/pm.c    |    1 +
 drivers/acpi/sleep/main.c    |   13 +++++++++++--
 include/linux/pm.h           |    4 ++++
 kernel/power/main.c          |   13 +++++++++++++
 11 files changed, 36 insertions(+), 54 deletions(-)

--- linux-2.6.orig/include/linux/pm.h	2007-03-20 12:42:04.813214909 +0100
+++ linux-2.6/include/linux/pm.h	2007-03-20 12:42:05.693214909 +0100
@@ -128,6 +128,9 @@ typedef int __bitwise suspend_disk_metho
  *	always valid and never passed to this call.
  *	If not assigned, all suspend states are advertised as valid
  *	in /sys/power/state (but can still be rejected by prepare or enter.)
+ *	Since new states can be added for other platforms, you should
+ *	assign this callback. There is a %pm_valid_only_mem function
+ *	available if you only implemented mem sleep.
  *
  * @prepare: Prepare the platform for the given suspend state. Can return a
  *	negative error code if necessary.
@@ -165,6 +168,7 @@ extern void pm_set_ops(struct pm_ops *pm
 extern struct pm_ops *pm_ops;
 extern int pm_suspend(suspend_state_t state);
 
+extern int pm_valid_only_mem(suspend_state_t state);
 
 /*
  * Device power management
--- linux-2.6.orig/arch/arm/common/sharpsl_pm.c	2007-03-20 12:42:02.263214909 +0100
+++ linux-2.6/arch/arm/common/sharpsl_pm.c	2007-03-20 12:42:05.693214909 +0100
@@ -769,6 +769,7 @@ static struct pm_ops sharpsl_pm_ops = {
 	.prepare	= pxa_pm_prepare,
 	.enter		= corgi_pxa_pm_enter,
 	.finish		= pxa_pm_finish,
+	.valid		= pm_valid_only_mem,
 };
 
 static int __init sharpsl_pm_probe(struct platform_device *pdev)
--- linux-2.6.orig/arch/arm/mach-omap1/pm.c	2007-03-20 12:42:02.263214909 +0100
+++ linux-2.6/arch/arm/mach-omap1/pm.c	2007-03-20 12:42:05.703214909 +0100
@@ -701,6 +701,7 @@ static struct pm_ops omap_pm_ops ={
 	.prepare	= omap_pm_prepare,
 	.enter		= omap_pm_enter,
 	.finish		= omap_pm_finish,
+	.valid		= pm_valid_only_mem,
 };
 
 static int __init omap_pm_init(void)
--- linux-2.6.orig/arch/arm/mach-omap2/pm.c	2007-03-20 12:42:02.263214909 +0100
+++ linux-2.6/arch/arm/mach-omap2/pm.c	2007-03-20 12:42:05.703214909 +0100
@@ -373,6 +373,7 @@ static struct pm_ops omap_pm_ops = {
 	.prepare	= omap2_pm_prepare,
 	.enter		= omap2_pm_enter,
 	.finish		= omap2_pm_finish,
+	.valid		= pm_valid_only_mem,
 };
 
 int __init omap2_pm_init(void)
--- linux-2.6.orig/arch/arm/mach-pnx4008/pm.c	2007-03-20 12:41:36.133214909 +0100
+++ linux-2.6/arch/arm/mach-pnx4008/pm.c	2007-03-20 12:42:05.703214909 +0100
@@ -115,42 +115,9 @@ static int pnx4008_pm_enter(suspend_stat
 	return 0;
 }
 
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int pnx4008_pm_prepare(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_STANDBY:
-	case PM_SUSPEND_MEM:
-		break;
-
-	case PM_SUSPEND_DISK:
-		return -ENOTSUPP;
-		break;
-
-	default:
-		return -EINVAL;
-		break;
-	}
-	return 0;
-}
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int pnx4008_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
 static struct pm_ops pnx4008_pm_ops = {
-	.prepare = pnx4008_pm_prepare,
 	.enter = pnx4008_pm_enter,
-	.finish = pnx4008_pm_finish,
+	.valid = pm_valid_only_mem,
 };
 
 static int __init pnx4008_pm_init(void)
--- linux-2.6.orig/arch/arm/mach-pxa/pm.c	2007-03-20 12:42:02.263214909 +0100
+++ linux-2.6/arch/arm/mach-pxa/pm.c	2007-03-20 12:42:05.703214909 +0100
@@ -227,6 +227,7 @@ static struct pm_ops pxa_pm_ops = {
 	.prepare	= pxa_pm_prepare,
 	.enter		= pxa_pm_enter,
 	.finish		= pxa_pm_finish,
+	.valid		= pm_valid_only_mem,
 };
 
 static int __init pxa_pm_init(void)
--- linux-2.6.orig/arch/arm/mach-sa1100/pm.c	2007-03-20 12:42:02.273214909 +0100
+++ linux-2.6/arch/arm/mach-sa1100/pm.c	2007-03-20 12:42:05.703214909 +0100
@@ -133,6 +133,7 @@ unsigned long sleep_phys_sp(void *sp)
 
 static struct pm_ops sa11x0_pm_ops = {
 	.enter		= sa11x0_pm_enter,
+	.valid		= pm_valid_only_mem,
 };
 
 static int __init sa11x0_pm_init(void)
--- linux-2.6.orig/arch/arm/plat-s3c24xx/pm.c	2007-03-20 12:42:02.273214909 +0100
+++ linux-2.6/arch/arm/plat-s3c24xx/pm.c	2007-03-20 12:42:05.703214909 +0100
@@ -612,26 +612,9 @@ static int s3c2410_pm_enter(suspend_stat
 	return 0;
 }
 
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int s3c2410_pm_prepare(suspend_state_t state)
-{
-	return 0;
-}
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int s3c2410_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
 static struct pm_ops s3c2410_pm_ops = {
-	.prepare	= s3c2410_pm_prepare,
 	.enter		= s3c2410_pm_enter,
-	.finish		= s3c2410_pm_finish,
+	.valid		= pm_valid_only_mem,
 };
 
 /* s3c2410_pm_init
--- linux-2.6.orig/arch/sh/boards/hp6xx/pm.c	2007-03-20 12:42:02.273214909 +0100
+++ linux-2.6/arch/sh/boards/hp6xx/pm.c	2007-03-20 12:42:05.713214909 +0100
@@ -69,6 +69,7 @@ static int hp6x0_pm_enter(suspend_state_
 
 static struct pm_ops hp6x0_pm_ops = {
 	.enter		= hp6x0_pm_enter,
+	.valid		= pm_valid_only_mem,
 };
 
 static int __init hp6x0_pm_init(void)
--- linux-2.6.orig/drivers/acpi/sleep/main.c	2007-03-20 12:41:36.863214909 +0100
+++ linux-2.6/drivers/acpi/sleep/main.c	2007-03-20 12:42:05.713214909 +0100
@@ -168,9 +168,18 @@ int acpi_suspend(u32 acpi_state)
 
 static int acpi_pm_state_valid(suspend_state_t pm_state)
 {
-	u32 acpi_state = acpi_suspend_states[pm_state];
+	u32 acpi_state;
 
-	return sleep_states[acpi_state];
+	switch (pm_state) {
+	case PM_SUSPEND_ON:
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		acpi_state = acpi_suspend_states[pm_state];
+
+		return sleep_states[acpi_state];
+	default:
+		return 0;
+	}
 }
 
 static struct pm_ops acpi_pm_ops = {
--- linux-2.6.orig/kernel/power/main.c	2007-03-20 12:42:02.263214909 +0100
+++ linux-2.6/kernel/power/main.c	2007-03-20 12:42:05.713214909 +0100
@@ -48,6 +48,19 @@ void pm_set_ops(struct pm_ops * ops)
 	mutex_unlock(&pm_mutex);
 }
 
+/**
+ * pm_valid_only_mem - generic memory-only valid callback
+ *
+ * pm_ops drivers that implement mem suspend only and only need
+ * to check for that in their .valid callback can use this instead
+ * of rolling their own .valid callback.
+ */
+int pm_valid_only_mem(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM;
+}
+
+
 static inline void pm_finish(suspend_state_t state)
 {
 	if (pm_ops->finish)

--

linux-2.6-fix-pmops-4.patch:
 include/linux/pm.h  |   10 ++++++++++
 kernel/power/main.c |   10 ++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

--- NEW FILE linux-2.6-fix-pmops-4.patch ---
---
 include/linux/pm.h  |   10 ++++++++++
 kernel/power/main.c |   10 ++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

--- wireless-dev.orig/include/linux/pm.h	2007-04-05 18:14:07.948549941 +0200
+++ wireless-dev/include/linux/pm.h	2007-04-05 18:14:13.568549941 +0200
@@ -131,9 +131,17 @@ typedef int __bitwise suspend_disk_metho
  * @prepare: Prepare the platform for the given suspend state. Can return a
  *	negative error code if necessary.
  *
+ * @irq_off: If assigned, the generic suspend code does not turn off IRQs
+ *	but relies on this callback instead. It is currently not called for
+ *	%PM_SUSPEND_DISK.
+ *
  * @enter: Enter the given suspend state, must be assigned. Can return a
  *	negative error code if necessary.
  *
+ * @irq_on: If assigned, the generic suspend code does not turn on IRQs
+ *	but relies on this callback instead. it is currently not called for
+ *	%PM_SUSPEND_DISK.
+ *
  * @finish: Called when the system has left the given state and all devices
  *	are resumed. The return value is ignored.
  *
@@ -152,7 +160,9 @@ typedef int __bitwise suspend_disk_metho
 struct pm_ops {
 	int (*valid)(suspend_state_t state);
 	int (*prepare)(suspend_state_t state);
+	void (*irq_off)(suspend_state_t state);
 	int (*enter)(suspend_state_t state);
+	void (*irq_on)(suspend_state_t state);
 	int (*finish)(suspend_state_t state);
 	suspend_disk_method_t pm_disk_mode;
 };
--- wireless-dev.orig/kernel/power/main.c	2007-04-05 18:14:07.988549941 +0200
+++ wireless-dev/kernel/power/main.c	2007-04-05 18:25:21.108549941 +0200
@@ -117,7 +117,10 @@ int suspend_enter(suspend_state_t state)
 	int error = 0;
 	unsigned long flags;
 
-	local_irq_save(flags);
+	if (pm_ops->irq_off)
+		pm_ops->irq_off(state);
+	else
+		local_irq_save(flags);
 
 	if ((error = device_power_down(PMSG_SUSPEND))) {
 		printk(KERN_ERR "Some devices failed to power down\n");
@@ -126,7 +129,10 @@ int suspend_enter(suspend_state_t state)
 	error = pm_ops->enter(state);
 	device_power_up();
  Done:
-	local_irq_restore(flags);
+	if (pm_ops->irq_on)
+		pm_ops->irq_on(state);
+	else
+		local_irq_restore(flags);
 	return error;
 }
 

linux-2.6-i82875-edac-pci-setup.patch:
 i82875p_edac.c |   13 ++-----------
 1 files changed, 2 insertions(+), 11 deletions(-)

--- NEW FILE linux-2.6-i82875-edac-pci-setup.patch ---
From: John Feeney <jfeeney at redhat.com>
Subject: [PATCH RHEL-5] BZ219288 /proc/bus/pci/devices speaks LIES
Date: Mon, 08 Jan 2007 15:52:30 -0500
Bugzilla: 219288
Message-Id: <45A2AF0E.5080901 at redhat.com>
Changelog: edac: fix /proc/bus/pci/devices to allow X to start


RHBZ#: 219288 /proc/bus/pci/devices speaks LIES
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=219288

Description:
On specific Dell systems (e.g. PE 700), X fails to start with the following
errors in /var/log/Xorg.0.log:

(EE) No devices detected.

Fatal server error:
no screens found
XIO:  fatal IO error 104 (Connection reset by peer) on X server ":0.0"
    after 0 requests (0 known processed) with 0 events remaining.

After some investigation, by Ajax, it was determined that the
/proc/bus/pci/devices file and the /proc/bus/pci/* tree did not match,  
that is,
the devices file could list 15 devices while there would be 16 entries 
in the
tree. This discrepancy caused X to be unable to find its device, e.g. 
mach64.

Upon further review, it was determined that the device with the 8086:257e
pci id was missing from the devices file, hence the investigation lead to
drivers/edac/i82875p_edac.c where Dell determined that this driver was
adding an entry to the /proc tree with a call to pci_proc_attach_device()
but not to the global list of devices, the list that the devices file 
displays.

RHEL Version Found:
RHEL5-B2 (2.6.18-1.2767.el5)

The Proposed Fix:
The pci_bus_add_device function will replace pci_proc_attach_device()
because pci_bus_add_device() calls pci_proc_attach_device() while
populating the devices file as well.

In lieu of qualifying the call (with a "if(dev->procent==NULL)"), the
pci_bus_add_device() will be included in the if statement that detects a 
hidden
device. Thus, when the device previously hidden by BIOS is enabled and
detected, the /proc file system components will be fully implemented 
with the
pci_bus_add_device() call.

Note: In the drivers subdirectory, it appears as though i82875p_edac.c
is the only place outside of the pci directory where 
pci_proc_attach_device()
is called while pci_bus_add_device() is called by 17 other drivers. 
Perhaps,
this and the fact that pci_proc_attach_device() needed to be externed 
should
have been a red flag to the author of the original patch that added this
functionality.

Also note: even though the original code had pci_proc_attach_device() call
enveloped in "#ifdef CONFIG_PROC_FS", all other situations in drivers/*
where pci_bus_add_device() was called did not use this ifdef so it was not
carried forward.

Upstream Status:
It  does not  appear as though this fix is upstream at this point in
time. The offending function was added to 2.6.17-git17 in June of
2006. This patch will be submitted upstream.

--- linux-2.6.18.noarch/drivers/edac/i82875p_edac.c.dell
+++ linux-2.6.18.noarch/drivers/edac/i82875p_edac.c
@@ -261,10 +261,6 @@ static void i82875p_check(struct mem_ctl
 	i82875p_process_error_info(mci, &info, 1);
 }
 
-#ifdef CONFIG_PROC_FS
-extern int pci_proc_attach_device(struct pci_dev *);
-#endif
-
 /* Return 0 on success or 1 on failure. */
 static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
 		struct pci_dev **ovrfl_pdev, void __iomem **ovrfl_window)
@@ -287,17 +283,12 @@ static int i82875p_setup_overfl_dev(stru
 
 		if (dev == NULL)
 			return 1;
+
+        	pci_bus_add_device(dev);
 	}
 
 	*ovrfl_pdev = dev;
 
-#ifdef CONFIG_PROC_FS
-	if ((dev->procent == NULL) && pci_proc_attach_device(dev)) {
-		i82875p_printk(KERN_ERR, "%s(): Failed to attach overflow "
-			       "device\n", __func__);
-		return 1;
-	}
-#endif  /* CONFIG_PROC_FS */
 	if (pci_enable_device(dev)) {
 		i82875p_printk(KERN_ERR, "%s(): Failed to enable overflow "
 			       "device\n", __func__);


linux-2.6-mpc52xx-fec.patch:
 drivers/net/Kconfig                                         |    1 
 drivers/net/Makefile                                        |    1 
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/Kconfig            |   23 
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/Makefile           |    8 
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/fec.c              |  872 ++++++++++++
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/fec.h              |  308 ++++
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/fec_phy.c          |  532 +++++++
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/fec_phy.h          |   73 +
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec.c         |  173 ++
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec.h         |   71 
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec_rx_task.c |   71 
 linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec_tx_task.c |   84 +
 12 files changed, 2217 insertions(+)

--- NEW FILE linux-2.6-mpc52xx-fec.patch ---
diff -uNr linux-2.6.20.ppc64/drivers/net/fec_mpc52xx/fec.c linux-2.6.20.fec/drivers/net/fec_mpc52xx/fec.c
--- linux-2.6.20.ppc64/drivers/net/fec_mpc52xx/fec.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.20.fec/drivers/net/fec_mpc52xx/fec.c	2007-03-27 23:52:17.000000000 +0100
@@ -0,0 +1,872 @@
+/*
+ * drivers/net/fec_mpc52xx/fec.c
+ *
+ * Driver for the MPC5200 Fast Ethernet Controller
+ *
+ * Author: Dale Farnsworth <dfarnsworth at mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/ppcboot.h>
+#include <asm/mpc52xx.h>
+
+#if defined(CONFIG_PPC_MERGE)
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <platforms/52xx/bestcomm.h>
+#include "sdma_fec.h"
+#else
+#include <syslib/bestcomm/bestcomm.h>
+#include <syslib/bestcomm/fec.h>
+#endif
+
+#include "fec_phy.h"
+#include "fec.h"
+
+#define DRIVER_NAME "mpc52xx-fec"
+
+static irqreturn_t fec_interrupt(int, void *);
+static irqreturn_t fec_rx_interrupt(int, void *);
+static irqreturn_t fec_tx_interrupt(int, void *);
+static struct net_device_stats *fec_get_stats(struct net_device *);
+static void fec_set_multicast_list(struct net_device *dev);
+static void fec_reinit(struct net_device *dev);
+
+static u8 mpc52xx_fec_mac_addr[6];
+static u8 null_mac[6];
+
+static void fec_tx_timeout(struct net_device *dev)
+{
+	struct fec_priv *priv = (struct fec_priv *)dev->priv;
+
+	priv->stats.tx_errors++;
+
+	if (!priv->tx_full)
+		netif_wake_queue(dev);
+}
+
+static void fec_set_paddr(struct net_device *dev, u8 *mac)
+{
+	struct fec_priv *priv = (struct fec_priv *)dev->priv;
+	struct mpc52xx_fec *fec = priv->fec;
+
+	out_be32(&fec->paddr1, *(u32*)(&mac[0]));
+	out_be32(&fec->paddr2, (*(u16*)(&mac[4]) << 16) | 0x8808);
+}
+
+static void fec_get_paddr(struct net_device *dev, u8 *mac)
+{
+	struct fec_priv *priv = (struct fec_priv *)dev->priv;
+	struct mpc52xx_fec *fec = priv->fec;
+
+	*(u32*)(&mac[0]) = in_be32(&fec->paddr1);
+	*(u16*)(&mac[4]) = in_be32(&fec->paddr2) >> 16;
+}
+
+static int fec_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct sockaddr *sock = (struct sockaddr *)addr;
+
+	memcpy(dev->dev_addr, sock->sa_data, dev->addr_len);
+
+	fec_set_paddr(dev, sock->sa_data);
+	return 0;
+}
+
+/* This function is called to start or restart the FEC during a link
+ * change.  This happens on fifo errors or when switching between half
+ * and full duplex.
+ */
+static void fec_restart(struct net_device *dev, int duplex)
+{
+	struct fec_priv *priv = (struct fec_priv *)dev->priv;
+	struct mpc52xx_fec *fec = priv->fec;
+	u32 rcntrl;
+	u32 tcntrl;
+	int i;
+
+	out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & 0x700000);
+	out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & 0x700000);
+	out_be32(&fec->reset_cntrl, 0x1000000);
+
+	/* Whack a reset.  We should wait for this. */
+	out_be32(&fec->ecntrl, FEC_ECNTRL_RESET);
+	for (i = 0; i < FEC_RESET_DELAY; ++i) {
+		if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0)
+			break;
+		udelay(1);
+	}
+	if (i == FEC_RESET_DELAY)
+		printk (KERN_ERR DRIVER_NAME ": FEC Reset timeout!\n");
+
+	/* Set station address. */
+	fec_set_paddr(dev, dev->dev_addr);
+
+	fec_set_multicast_list(dev);
+
+	rcntrl = FEC_RX_BUFFER_SIZE << 16;	/* max frame length */
+	rcntrl |= FEC_RCNTRL_FCE;
+	rcntrl |= MII_RCNTL_MODE;
+	if (duplex)
+		tcntrl = FEC_TCNTRL_FDEN;		/* FD enable */
+	else {
+		rcntrl |= FEC_RCNTRL_DRT;
+		tcntrl = 0;
+	}
+	out_be32(&fec->r_cntrl, rcntrl);
+	out_be32(&fec->x_cntrl, tcntrl);
+
+	set_phy_speed(fec, priv->phy_speed);
+
+	priv->full_duplex = duplex;
+
+	/* Clear any outstanding interrupt. */
+	out_be32(&fec->ievent, 0xffffffff);	/* clear intr events */
+
+	/* Enable interrupts we wish to service.
+	*/
+	out_be32(&fec->imask, FEC_IMASK_ENABLE);
+
+	/* And last, enable the transmit and receive processing.
+	*/
+	out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN);
+	out_be32(&fec->r_des_active, 0x01000000);
+
+	/* The tx ring is no longer full. */
+	if (priv->tx_full)
+	{
+		priv->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+}
+
+static void fec_free_rx_buffers(struct sdma *s)
+{
+	struct sk_buff *skb;
+
+	while (!sdma_queue_empty(s)) {
+		skb = sdma_retrieve_buffer(s, NULL);
+		kfree_skb(skb);
+	}
+}
+
+static int fec_open(struct net_device *dev)
+{
+	struct fec_priv *priv = (struct fec_priv *)dev->priv;
+	struct sk_buff *skb;
+	void *data;
+
+	sdma_fec_rx_init(priv->rx_sdma, priv->rx_fifo, FEC_RX_BUFFER_SIZE);
+	sdma_fec_tx_init(priv->tx_sdma, priv->tx_fifo);
+
+	while (!sdma_queue_full(priv->rx_sdma)) {
+		skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+		if (skb == 0)
+			goto eagain;
+
+		/* zero out the initial receive buffers to aid debugging */
+		memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
+		data = (void *)virt_to_phys(skb->data);
+		sdma_submit_buffer(priv->rx_sdma, skb, data, FEC_RX_BUFFER_SIZE);
+	}
+
+	fec_set_paddr(dev, dev->dev_addr);
+
+	if (fec_mii_wait(dev) != 0)
[...1876 lines suppressed...]
+struct sdma_fec_tx_inc {
+	u16 pad0;
+	s16 incr_bytes;
+	u16 pad1;
+	s16 incr_src;
+	u16 pad2;
+	s16 incr_src_ma;
+};
+
+extern int sdma_fec_rx_init(struct sdma *s, phys_addr_t fifo, int maxbufsize);
+extern int sdma_fec_tx_init(struct sdma *s, phys_addr_t fifo);
+
+extern u32 sdma_fec_rx_task[];
+extern u32 sdma_fec_tx_task[];
+
+
+#endif  /* __BESTCOMM_FEC_H__ */
diff -uNr linux-2.6.20.ppc64/drivers/net/fec_mpc52xx/sdma_fec_rx_task.c linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec_rx_task.c
--- linux-2.6.20.ppc64/drivers/net/fec_mpc52xx/sdma_fec_rx_task.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec_rx_task.c	2007-03-27 22:57:09.000000000 +0100
@@ -0,0 +1,71 @@
+/*
+ * sdma_fec_rx_task.c
+ *
+ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 22 11:19:38 2005 GMT
+ */
+
+#include <linux/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	uint32_t	magic;
+ *	uint8_t		desc_size;
+ *	uint8_t		var_size;
+ *	uint8_t		inc_size;
+ *	uint8_t		first_var;
+ *	uint8_t		reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+*/
+
+uint32_t sdma_fec_rx_task[] = {
+	/* header */
+	0x4243544b,
+	0x18060709,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
+	0x10601010, /*   DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
+	0xb8800264, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
+	0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0xb8c58029, /*   LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
+	0x60000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
+	0x088cf8cc, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var12)  */
+	0x991982f2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
+	0x006acf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x034cfc4e, /*     DRD2B1: var13 = EU3(); EU3(*idx1,var14)  */
+	0x00008868, /*     DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
+	0x99198341, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
+	0x007ecf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
+	0x99198272, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
+	0x046acf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
+	0x9819002d, /*   LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
+	0x0060c790, /*     DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
+	0x000001f8, /*   NOP */
+
+	/* VAR[9]-VAR[14] */
+	0x40000000,
+	0x7fff7fff,
+	0x00000000,
+	0x00000003,
+	0x40000008,
+	0x43ffffff,
+
+	/* INC[0]-INC[6] */
+	0x40000000,
+	0xe0000000,
+	0xe0000000,
+	0xa0000008,
+	0x20000000,
+	0x00000000,
+	0x4000ffff,
+};
diff -uNr linux-2.6.20.ppc64/drivers/net/fec_mpc52xx/sdma_fec_tx_task.c linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec_tx_task.c
--- linux-2.6.20.ppc64/drivers/net/fec_mpc52xx/sdma_fec_tx_task.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.20.fec/drivers/net/fec_mpc52xx/sdma_fec_tx_task.c	2007-03-27 22:57:09.000000000 +0100
@@ -0,0 +1,84 @@
+/*
+ * sdma_fec_tx_task.c
+ *
+ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
+ * on Tue Mar 22 11:19:29 2005 GMT
+ */
+
+#include <linux/types.h>
+
+/*
+ * The header consists of the following fields:
+ *	uint32_t	magic;
+ *	uint8_t		desc_size;
+ *	uint8_t		var_size;
+ *	uint8_t		inc_size;
+ *	uint8_t		first_var;
+ *	uint8_t		reserved[8];
+ *
+ * The size fields contain the number of 32-bit words.
+*/
+
+uint32_t sdma_fec_tx_task[] = {
+	/* header */
+	0x4243544b,
+	0x2407070d,
+	0x00000000,
+	0x00000000,
+
+	/* Task descriptors */
+	0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
+	0x60000005, /*   DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+	0x01ccfc0d, /*   DRD2B1: var7 = EU3(); EU3(*idx0,var13)  */
+	0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
+	0x10801418, /*   DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
+	0xf88103a4, /*   LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
+	0x801a6024, /*   LCD: idx4 = var0; ; idx4 += inc4 */
+	0x10001708, /*     DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+	0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
+	0x0cccfccf, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var15)  */
+	0x991a002c, /*   LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x024cfc4d, /*     DRD2B1: var9 = EU3(); EU3(*idx1,var13)  */
+	0x60000003, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
+	0x0cccf247, /*     DRD2B1: *idx3 = EU3(); EU3(var9,var7)  */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0xb8c80029, /*   LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x088cf8d1, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var17)  */
+	0x00002f10, /*     DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
+	0x99198432, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
+	0x008ac398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
+	0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
+	0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
+	0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
+	0x048cfc53, /*     DRD2B1: var18 = EU3(); EU3(*idx1,var19)  */
+	0x60000008, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
+	0x088cf48b, /*     DRD2B1: idx2 = EU3(); EU3(var18,var11)  */
+	0x99198481, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
+	0x009ec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
+	0x991983b2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
+	0x088ac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
+	0x9919002d, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
+	0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
+	0x0c4cf88e, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var14)  */
+	0x000001f8, /*   NOP */
+
+	/* VAR[13]-VAR[19] */
+	0x0c000000,
+	0x40000000,
+	0x7fff7fff,
+	0x00000000,
+	0x00000003,
+	0x40000004,
+	0x43ffffff,
+
+	/* INC[0]-INC[6] */
+	0x40000000,
+	0xe0000000,
+	0xe0000000,
+	0xa0000008,
+	0x20000000,
+	0x00000000,
+	0x4000ffff,
+};
--- linux-2.6.20.ppc64/drivers/net/Makefile	2007-03-22 11:18:04.000000000 +0000
+++ linux-2.6.20.fec/drivers/net/Makefile	2007-03-27 19:09:21.000000000 +0100
@@ -196,6 +196,7 @@ obj-$(CONFIG_SMC91X) += smc91x.o
 obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
+obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
 obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
 
 obj-$(CONFIG_MACB) += macb.o
--- linux-2.6.20.ppc64/drivers/net/Kconfig	2007-03-22 11:17:54.000000000 +0000
+++ linux-2.6.20.fec/drivers/net/Kconfig	2007-03-27 19:09:21.000000000 +0100
@@ -1889,6 +1889,7 @@ config NE_H8300
 	  controller on the Renesas H8/300 processor.
 
 source "drivers/net/fec_8xx/Kconfig"
+source "drivers/net/fec_mpc52xx/Kconfig"
 source "drivers/net/fs_enet/Kconfig"
 
 endmenu

linux-2.6-mpc52xx-sdma.patch:
 arch/powerpc/Kconfig                                    |    5 
 linux-2.6.20.fec/arch/powerpc/platforms/52xx/Makefile   |    1 
 linux-2.6.20.fec/arch/powerpc/platforms/52xx/bestcomm.c |  399 +++++++++++++
 linux-2.6.20.fec/arch/powerpc/platforms/52xx/bestcomm.h |  478 ++++++++++++++++
 4 files changed, 883 insertions(+)

--- NEW FILE linux-2.6-mpc52xx-sdma.patch ---
--- linux-2.6.20.ppc64/arch/powerpc/Kconfig	2007-03-22 11:17:52.000000000 +0000
+++ linux-2.6.20.fec/arch/powerpc/Kconfig	2007-03-27 19:09:27.000000000 +0100
@@ -451,6 +456,11 @@
 
 	  It is safe to say 'Y' here
 
+config PPC_BESTCOMM
+	bool
+	depends on PPC_MPC52xx
+	default y
+
 config PPC_EFIKA
 	bool "bPlan Efika 5k2. MPC5200B based computer"
 	depends on PPC_MULTIPLATFORM && PPC32
diff -uNr linux-2.6.20.ppc64/arch/powerpc/platforms/52xx/bestcomm.c linux-2.6.20.fec/arch/powerpc/platforms/52xx/bestcomm.c
--- linux-2.6.20.ppc64/arch/powerpc/platforms/52xx/bestcomm.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.20.fec/arch/powerpc/platforms/52xx/bestcomm.c	2007-03-27 23:40:42.000000000 +0100
@@ -0,0 +1,399 @@
+/*
+ * arch/ppc/syslib/bestcomm/bestcomm.c
+ *
+ * Driver for MPC52xx processor BestComm peripheral controller
+ *
+ * Author: Dale Farnsworth <dfarnsworth at mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * HISTORY:
+ *
+ * 2005-08-14	Converted to platform driver by 
+ *		Andrey Volkov <avolkov at varma-el.com>, Varma Electronics Oy
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include <asm/of_platform.h>
+
+#include "bestcomm.h"
+
+#define DRIVER_NAME "mpc52xx-bestcomm"
+
+struct sdma_io sdma;
+struct device_node *sdma_node;
+struct device_node *sram_node;
+
+static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
+
+#ifdef CONFIG_BESTCOMM_DEBUG
+void sdma_dump(void)
+{
+	int i;
+	printk("** SDMA registers: pa = %.8lx, va = %p\n",
+	       sdma.base_reg_addr, sdma.io);
+	printk("**  taskBar = %08x\n", sdma.io->taskBar);
+	printk("**  currentPointer = %08x\n", sdma.io->currentPointer);
+	printk("**  endPointer = %08x\n", sdma.io->endPointer);
+	printk("**  variablePointer = %08x\n", sdma.io->variablePointer);
+
+	printk("**  IntVect1 = %08x\n", sdma.io->IntVect1);
+	printk("**  IntVect2 = %08x\n", sdma.io->IntVect2);
+	printk("**  PtdCntrl = %08x\n", sdma.io->PtdCntrl);
+
+	printk("**  IntPend = %08x\n", sdma.io->IntPend);
+	printk("**  IntMask = %08x\n", sdma.io->IntMask);
+
+	printk("**  TCR dump:");	
+
+	for (i=0;i<16;i++)  {
+		if(i%8 == 0)
+			printk("\n**   %02X:",i);
+		printk(" %04X",sdma.io->tcr[i]);
+	}
+	printk("\n**  IPR dump:");	
+	for (i=0;i<32;i++)  {
+		if(i%16 == 0)
+			printk("\n**   %02X:",i);
+		printk(" %02X",sdma.io->ipr[i]);
+	}
+	printk("\n**  cReqSelect = %08x\n", sdma.io->cReqSelect);
+	printk("**  task_size0 = %08x\n", sdma.io->task_size0);
+	printk("**  task_size1 = %08x\n", sdma.io->task_size1);
+	printk("**  MDEDebug = %08x\n", sdma.io->MDEDebug);
+	printk("**  ADSDebug = %08x\n", sdma.io->ADSDebug);
+	printk("**  Value1 = %08x\n", sdma.io->Value1);
+	printk("**  Value2 = %08x\n", sdma.io->Value2);
+	printk("**  Control = %08x\n", sdma.io->Control);
+	printk("**  Status = %08x\n", sdma.io->Status);
+	printk("**  PTDDebug = %08x\n", sdma.io->PTDDebug);
+}
+#endif
+
+#ifdef CONFIG_BESTCOMM_DEBUG
+#define SDMA_DUMP_REGS()	sdma_dump()
+#else
+#define SDMA_DUMP_REGS()
+#endif
+
+/*
+ * Use a very simple SRAM allocator.
+ * There is no mechanism for freeing space.
+ * In an attempt to minimize internal fragmentation, the SRAM is
+ * divided into two areas.
+ *
+ * Area 1 is at the beginning of SRAM
+ * and is used for allocations requiring alignments of 16 bytes or less.
+ * Successive allocations return higher addresses.
+ *
+ * Area 2 is at the end of SRAM and is used for the remaining allocations.
+ * Successive allocations return lower addresses.
+ *
+ * I've considered adding routines to support the freeing of SRAM allocations,
+ * but the SRAM is so small (16K) that fragmentation can quickly cause the
+ * SRAM to be unusable.  If you can come up with a slick way to free SRAM
+ * memory without the fragmentation problem, please do so.
+ */
+
+static u8 *area1_end;
+static u8 *area2_begin;
+
+void *sdma_sram_alloc(int size, int alignment, u32 *dma_handle)
+{
+	u8 *a;
+
+	spin_lock(&sdma_lock);
+
+	/* alignment must be a power of 2 */
+	BUG_ON(alignment & (alignment - 1));
+
+	if (alignment < 16) {
+		a = (u8 *)(((u32)area1_end + (alignment-1)) & ~(alignment-1));
+		if (a + size <= area2_begin)
+			area1_end = a + size;
+		else
+			a = 0;				/* out of memory */
+	} else {
+		a = (u8 *)(((u32)area2_begin - size) & ~(alignment - 1));
+		if (a >= area1_end)
+			area2_begin = a;
+		else
+			a = 0;				/* out of memory */
+	}
+	if(a && dma_handle)
+		*dma_handle = sdma_sram_pa(a);
+	spin_unlock(&sdma_lock);
+	return (void *)a;
+}
+
+/* this will need to be updated if Freescale changes their task code FDT */
+static u32 fdt_ops[] = {
+	0xa0045670,	/* FDT[48] */
+	0x80045670,	/* FDT[49] */
+	0x21800000,	/* FDT[50] */
+	0x21e00000,	/* FDT[51] */
+	0x21500000,	/* FDT[52] */
+	0x21400000,	/* FDT[53] */
+	0x21500000,	/* FDT[54] */
+	0x20400000,	/* FDT[55] */
+	0x20500000,	/* FDT[56] */
+	0x20800000,	/* FDT[57] */
+	0x20a00000,	/* FDT[58] */
+	0xc0170000,	/* FDT[59] */
+	0xc0145670,	/* FDT[60] */
+	0xc0345670,	/* FDT[61] */
+	0xa0076540,	/* FDT[62] */
+	0xa0000760,	/* FDT[63] */
+};
+
+static int new_task_number(void)
+{
+	struct sdma_tdt *tdt;
+	int i;
+
+	spin_lock(&sdma_lock);
+
+	tdt = sdma.tdt;
+	for (i=0; i<SDMA_MAX_TASKS; i++, tdt++)
+		if (tdt->start == 0)
+			break;
+	if (i == SDMA_MAX_TASKS)
+		i = -1;
+
+	spin_unlock(&sdma_lock);
+
+	return i;
+}
+
+int sdma_load_task(u32 *task_image)
+{
+	struct sdma_task_header *head = (struct sdma_task_header *)task_image;
+	struct sdma_tdt *tdt;
+	int tasknum;
+	u32 *desc;
+	u32 *var_src, *var_dst;
+	u32 *inc_src;
+	void *start;
+
+	BUG_ON(head->magic != SDMA_TASK_MAGIC);
+
+	tasknum = new_task_number();
+	if (tasknum < 0)
+		return -ENOMEM;
+
+	desc = (u32 *)(head + 1);
+	var_src = desc + head->desc_size;
+	inc_src = var_src + head->var_size;
+
+	tdt = &sdma.tdt[tasknum];
+
+	start = sdma_sram_alloc(head->desc_size * sizeof(u32), 4, &tdt->start);
+	if (!start)
+		return -ENOMEM;
+	tdt->stop = tdt->start + (head->desc_size - 1)*sizeof(u32);
+	var_dst = sdma_sram_va(tdt->var);
+
+	memcpy(start, desc, head->desc_size * sizeof(u32));
+	memcpy(&var_dst[head->first_var], var_src, head->var_size * sizeof(u32));
+	memcpy(&var_dst[SDMA_MAX_VAR], inc_src, head->inc_size * sizeof(u32));
+
+	return tasknum;
+}
+
+void sdma_set_initiator(int task, int initiator)
+{
+	int i;
+	int num_descs;
+	u32 *desc;
+	int next_drd_has_initiator;
+
+	sdma_set_tcr_initiator(task, initiator);
+
+	desc = sdma_task_desc(task);
+	next_drd_has_initiator = 1;
+	num_descs = sdma_task_num_descs(task);
+
+	for (i=0; i<num_descs; i++, desc++) {
+		if (!sdma_desc_is_drd(*desc))
+			continue;
+		if (next_drd_has_initiator)
+			if (sdma_desc_initiator(*desc) != SDMA_INITIATOR_ALWAYS)
+				sdma_set_desc_initiator(desc, initiator);
+		next_drd_has_initiator = !sdma_drd_is_extended(*desc);
+	}
+}
+
+struct sdma *sdma_alloc(int queue_size)
+{
+	struct sdma *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	void **cookie;
+
+	if (!s)
+		return NULL;
+
+	memset(s, 0, sizeof(*s));
+
+	if (queue_size) {
+		cookie = kmalloc(sizeof(*cookie) * queue_size, GFP_KERNEL);
+		if (!cookie) {
+			kfree(s);
+			return NULL;
+		}
+		s->cookie = cookie;
+	}
+
+	s->num_bd = queue_size;
+	s->node = sdma_node;
+	return s;
+}
+EXPORT_SYMBOL_GPL(sdma_alloc);
+
+void sdma_free(struct sdma *s)
+{
+	if (s->cookie)
+		kfree(s->cookie);
+	kfree(s);
+}
+
+static int __init mpc52xx_sdma_init(void)
+{
+	int task;
+	u32 *context;
+	u32 *fdt;
+	struct sdma_tdt *tdt;
+	struct resource mem_io, mem_sram;
+	u32 tdt_pa, var_pa, context_pa, fdt_pa;
+	int ret = -ENODEV;
+
+	/* Find SDMA registers */
+	sdma_node = of_find_compatible_node(NULL, "dma-controller", "mpc5200-bestcomm");
+	if (!sdma_node) {
+		printk (KERN_ERR DRIVER_NAME ": could not locate DMA controller\n");
+		goto out;
+	}
+
+	if ((ret = of_address_to_resource(sdma_node, 0, &mem_io)) != 0) {
+		printk(KERN_ERR "Could not get address of SDMA controller\n");
+		goto out;
+	}
+
+	/* Find SRAM location */
+	sram_node = of_find_compatible_node(NULL, "sram", "mpc5200-sram");
+	if (!sram_node) {
+		printk (KERN_ERR DRIVER_NAME ": could not locate SRAM\n");
+		goto out;
+	}
+
+	if ((ret = of_address_to_resource(sram_node, 0, &mem_sram)) != 0) {
+		printk(KERN_ERR "Could not get address of SRAM\n");
+		goto out;
+	}
+
+	/* Map register regions */
+	if (!request_mem_region(mem_io.start, mem_io.end - mem_io.start + 1,
+	                        DRIVER_NAME)) {
+		printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
+		goto out;
+	}
+	sdma.base_reg_addr = mem_io.start;
+
+	sdma.io = ioremap_nocache(mem_io.start, sizeof(struct mpc52xx_sdma));
+
+	if (!sdma.io ) {
+		printk(KERN_ERR DRIVER_NAME " - failed to map sdma regs\n");
+		ret = -ENOMEM;
+		goto map_io_error;
+	}
+
+	SDMA_DUMP_REGS();
+
+	sdma.sram_size = mem_sram.end - mem_sram.start + 1;
+	if (!request_mem_region(mem_sram.start, sdma.sram_size, DRIVER_NAME)) {
+		printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
+		goto req_sram_error;
+	}
+
+	sdma.base_sram_addr = mem_sram.start;
+	sdma.sram = ioremap_nocache(mem_sram.start, sdma.sram_size);
+	if (!sdma.sram ) {
+		printk(KERN_ERR DRIVER_NAME " - failed to map sdma sram\n");
+		ret = -ENOMEM;
+		goto map_sram_error;
+	}
+
+	area1_end = sdma.sram;
+	area2_begin = area1_end + sdma.sram_size;
+
+	memset(area1_end, 0, sdma.sram_size);
+
+	/* allocate space for task descriptors, contexts, and var tables */
+	sdma.tdt = sdma_sram_alloc(sizeof(struct sdma_tdt) * SDMA_MAX_TASKS, 4, &tdt_pa);
+
+	context = sdma_sram_alloc(SDMA_CONTEXT_SIZE * SDMA_MAX_TASKS,
+							  SDMA_CONTEXT_ALIGN, &context_pa);
+	sdma.var = sdma_sram_alloc( (SDMA_VAR_SIZE + SDMA_INC_SIZE) * SDMA_MAX_TASKS, 
+								SDMA_VAR_ALIGN, &var_pa);
+	fdt = sdma_sram_alloc(SDMA_FDT_SIZE, SDMA_FDT_ALIGN, &fdt_pa);
+	memcpy(&fdt[48], fdt_ops, sizeof(fdt_ops));
+
+	out_be32(&sdma.io->taskBar, tdt_pa);
+
+	tdt = sdma.tdt;
+	for (task=0; task < SDMA_MAX_TASKS; task++) {
+		out_be16(&sdma.io->tcr[task], 0);
+		out_8(&sdma.io->ipr[task], 0);
+
+		tdt->context = context_pa;
+		tdt->var = var_pa;
+		tdt->fdt = fdt_pa;
+		var_pa += (SDMA_MAX_VAR + SDMA_MAX_INC)*sizeof(u32);
+		context_pa += SDMA_MAX_CONTEXT*sizeof(u32);
+		tdt++;
+	}
+
+	out_8(&sdma.io->ipr[SDMA_INITIATOR_ALWAYS], SDMA_IPR_ALWAYS);
+
+	/* Disable COMM Bus Prefetch, apparently it's not reliable yet */
+	out_be16(&sdma.io->PtdCntrl, in_be16(&sdma.io->PtdCntrl) | 1);
+
+	printk(KERN_INFO "MPC52xx BestComm inited\n");
+
+	return 0;
+
+map_sram_error:
+	release_mem_region(mem_sram.start, sdma.sram_size);
+req_sram_error:
+	iounmap(sdma.io);
+map_io_error:
+	release_mem_region(mem_io.start, mem_io.end - mem_io.start + 1);
+out:
+	printk(KERN_ERR "DMA: MPC52xx BestComm init FAILED !!!\n");
+	return ret;
+}
+
+subsys_initcall(mpc52xx_sdma_init);
+
+
+MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(sdma_sram_alloc);
+EXPORT_SYMBOL(sdma_load_task);
+EXPORT_SYMBOL(sdma_set_initiator);
+EXPORT_SYMBOL(sdma_free);
+EXPORT_SYMBOL(sdma);
+
+
diff -uNr linux-2.6.20.ppc64/arch/powerpc/platforms/52xx/bestcomm.h linux-2.6.20.fec/arch/powerpc/platforms/52xx/bestcomm.h
--- linux-2.6.20.ppc64/arch/powerpc/platforms/52xx/bestcomm.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.20.fec/arch/powerpc/platforms/52xx/bestcomm.h	2007-03-27 22:57:08.000000000 +0100
@@ -0,0 +1,478 @@
+/*
+ * arch/ppc/syslib/bestcomm/bestcomm.h
+ *
+ * Driver for MPC52xx processor BestComm peripheral controller
+ *
+ * Author: Dale Farnsworth <dfarnsworth at mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * HISTORY:
+ *
+ * 2005-08-14	Converted to platform driver by 
+ *		Andrey Volkov <avolkov at varma-el.com>, Varma Electronics Oy
+ */
+
+#ifndef __BESTCOMM_BESTCOMM_H__
+#define __BESTCOMM_BESTCOMM_H__
+
+#include "mpc52xx_pic.h"
+
+/* Buffer Descriptor definitions */
+struct sdma_bd {
+	u32 status;
+	void *data;
+};
+
+struct sdma_bd2 {
+	u32 status;
+	void *data1;
+	void *data2;
+};
+
+struct sdma_io {
+	unsigned long			base_reg_addr;
+	struct mpc52xx_sdma __iomem	*io;
+	unsigned long			base_sram_addr;
+	void __iomem			*sram;
+	size_t				sram_size;
+
+	struct sdma_tdt __iomem  	*tdt;
+	u32 __iomem			*var;
+};
+extern struct sdma_io sdma;
+
+#define	sdma_sram_pa(virt)	(((unsigned long)(((void __iomem *)(virt))-sdma.sram))+sdma.base_sram_addr)
+#define	sdma_sram_va(pa)	((void __iomem *)((((unsigned long)(pa))-sdma.base_sram_addr)+((unsigned long)sdma.sram)))
+
+#define	sdma_io_pa(virt)	(((unsigned long)(((void __iomem *)(virt))-((void __iomem *)sdma.io)))+sdma.base_reg_addr)
+#define	sdma_io_va(pa)	((void __iomem *)((((unsigned long)(pa))-sdma.base_reg_addr)+((unsigned long)sdma.io)))
+
+#define SDMA_LEN_BITS		26
+#define SDMA_LEN_MASK		((1 << SDMA_LEN_BITS) - 1)
+
+#define SDMA_BD_READY		0x40000000UL
+
+#define SDMA_FEC_TX_BD_TFD	0x08000000UL	/* transmit frame done */
+#define SDMA_FEC_TX_BD_INT	0x04000000UL	/* Interrupt */
+#define SDMA_FEC_TX_BD_TFD_INIT	(SDMA_BD_READY | SDMA_FEC_TX_BD_TFD | \
+							SDMA_FEC_TX_BD_INT)
+
+struct sdma {
+	union {
+		struct sdma_bd *bd;
+		struct sdma_bd2 *bd2;
+	};
+	void **cookie;
+	u16 index;
+	u16 outdex;
+	u16 num_bd;
+	s16 tasknum;
+	u32 flags;
+	struct device_node *node;
+};
+
+#define SDMA_FLAGS_NONE		0x0000
+#define SDMA_FLAGS_ENABLE_TASK	0x0001
+#define SDMA_FLAGS_BD2		0x0002
+
+/* Task Descriptor Table Entry */
+struct sdma_tdt {
+	u32 start;
+	u32 stop;
+	u32 var;
+	u32 fdt;
+	u32 exec_status; /* used internally by SmartComm engine */
+	u32 mvtp;		 /* used internally by SmartComm engine */
+	u32 context;
+	u32 litbase;
+};
+
+//extern struct sdma_tdt *sdma_tdt;
+
+#define SDMA_MAX_TASKS		16
+#define SDMA_MAX_VAR		24
+#define SDMA_MAX_INC		8
+#define SDMA_MAX_FDT		64
+#define SDMA_MAX_CONTEXT	20
+#define SDMA_CONTEXT_SIZE	SDMA_MAX_CONTEXT * sizeof(u32)
+#define SDMA_CONTEXT_ALIGN	0x100
+#define SDMA_VAR_SIZE		SDMA_MAX_VAR * sizeof(u32)
+#define SDMA_VAR_ALIGN		0x80
+#define SDMA_INC_SIZE		SDMA_MAX_INC * sizeof(u32)
+#define SDMA_FDT_SIZE		SDMA_MAX_FDT * sizeof(u32)
+#define SDMA_FDT_ALIGN		0x100
+#define SDMA_BD_ALIGN		0x10
+
+#define TASK_ENABLE		0x8000
+
+#ifndef DPRINK
+	#ifdef CONFIG_BESTCOMM_DEBUG
+	#define DPRINTK(a,b...)	printk(KERN_DEBUG "sdma: %s: " a, __FUNCTION__ , ## b)
+	#else
+	#define DPRINTK(a,b...)
+	#endif
+#endif
+
+static inline void sdma_enable_task(int task)
+{
+	u16 reg;
+
+	DPRINTK("***DMA enable task (%d): tdt = %p\n",task, sdma.tdt);
+	DPRINTK("***tdt->start   = %08x\n",sdma.tdt[task].start);
+	DPRINTK("***tdt->stop    = %08x\n",sdma.tdt[task].stop);
+	DPRINTK("***tdt->var     = %08x\n",sdma.tdt[task].var);
+	DPRINTK("***tdt->fdt     = %08x\n",sdma.tdt[task].fdt);
+	DPRINTK("***tdt->status  = %08x\n",sdma.tdt[task].exec_status);
+	DPRINTK("***tdt->mvtp    = %08x\n",sdma.tdt[task].mvtp);
+	DPRINTK("***tdt->context = %08x\n",sdma.tdt[task].context);
+	DPRINTK("***tdt->litbase = %08x\n",sdma.tdt[task].litbase);
+	DPRINTK("***--------------\n");
+
+	reg = in_be16(&sdma.io->tcr[task]);
+	DPRINTK("***enable task: &sdma.io->tcr=%p, reg = %04x\n", &sdma.io->tcr, reg);
+	out_be16(&sdma.io->tcr[task],  reg | TASK_ENABLE);
+}
+
+static inline void sdma_disable_task(int task)
+{
+	u16 reg = in_be16(&sdma.io->tcr[task]);
+	DPRINTK("***disable task(%d): reg = %04x\n", task, reg);
+	out_be16(&sdma.io->tcr[task], reg & ~TASK_ENABLE);
+}
+
+static inline int sdma_irq(struct sdma *s)
+{
+	return irq_of_parse_and_map(s->node, s->tasknum);
+}
+
+static inline void sdma_enable(struct sdma *s)
+{
+	sdma_enable_task(s->tasknum);
+}
+
+static inline void sdma_disable(struct sdma *s)
+{
+	sdma_disable_task(s->tasknum);
+}
+
+static inline int sdma_queue_empty(struct sdma *s)
+{
+	return s->index == s->outdex;
+}
+
+static inline void sdma_clear_irq(struct sdma *s)
+{
+	out_be32(&sdma.io->IntPend, 1 << s->tasknum);
+}
+
+static inline int sdma_next_index(struct sdma *s)
+{
+	return ((s->index + 1) == s->num_bd) ? 0 : s->index + 1;
+}
+
+static inline int sdma_next_outdex(struct sdma *s)
+{
+	return ((s->outdex + 1) == s->num_bd) ? 0 : s->outdex + 1;
+}
+
+static inline int sdma_queue_full(struct sdma *s)
+{
+	return s->outdex == sdma_next_index(s);
+}
+
+static inline int sdma_buffer_done(struct sdma *s)
+{
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(s->flags & SDMA_FLAGS_BD2);
+#endif
+	if (sdma_queue_empty(s))
+		return 0;
+	return (s->bd[s->outdex].status & SDMA_BD_READY) == 0;
+}
+
+static inline int sdma_buffer2_done(struct sdma *s)
+{
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
+#endif
+	if (sdma_queue_empty(s))
+		return 0;
+
+	return (s->bd2[s->outdex].status & SDMA_BD_READY) == 0;
+}
+
+static inline u32 *sdma_task_desc(int task)
+{
+	return sdma_sram_va(sdma.tdt[task].start);
+}
+
+static inline u32 sdma_task_num_descs(int task)
+{
+	return (sdma.tdt[task].stop - sdma.tdt[task].start)/sizeof(u32) + 1;
+}
+
+static inline u32 *sdma_task_var(int task)
+{
+	return sdma_sram_va(sdma.tdt[task].var);
+}
+
+static inline u32 *sdma_task_inc(int task)
+{
+	return &sdma_task_var(task)[SDMA_MAX_VAR];
+}
+
+static inline void sdma_set_tcr_initiator(int task, int initiator) {
+	u16 *tcr = &sdma.io->tcr[task];
+	out_be16(tcr, (in_be16(tcr) & ~0x1f00) | (initiator << 8));
+}
+
+#define SDMA_DRD_INITIATOR_SHIFT	21
+
+static inline int sdma_desc_initiator(u32 desc)
+{
+	return (desc >> SDMA_DRD_INITIATOR_SHIFT) & 0x1f;
+}
+
+static inline void sdma_set_desc_initiator(u32 *desc, int initiator)
+{
+	*desc = (*desc & ~(0x1f << SDMA_DRD_INITIATOR_SHIFT)) |
+			((initiator << SDMA_DRD_INITIATOR_SHIFT) & 0x1f);
+}
+
+static inline void sdma_submit_buffer(struct sdma *s, void *cookie, void *data,
+								int length)
+{
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(s->flags & SDMA_FLAGS_BD2);
+#endif
+	s->cookie[s->index] = cookie;
+	s->bd[s->index].data = data;
+	s->bd[s->index].status = SDMA_BD_READY | length;
+	s->index = sdma_next_index(s);
+	if (s->flags & SDMA_FLAGS_ENABLE_TASK)
+		sdma_enable_task(s->tasknum);
+}
+
+/*
+ * Special submit_buffer function to submit last buffer of a frame to
+ * the FEC tx task.  tfd means "transmit frame done".
+ */
+static inline void sdma_fec_tfd_submit_buffer(struct sdma *s, void *cookie,
+							void *data, int length)
+{
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(s->flags & SDMA_FLAGS_BD2);
+#endif
+	s->cookie[s->index] = cookie;
+	s->bd[s->index].data = data;
+	s->bd[s->index].status = SDMA_FEC_TX_BD_TFD_INIT | length;
+	s->index = sdma_next_index(s);
+	sdma_enable_task(s->tasknum);
+}
+
+static inline void *sdma_retrieve_buffer(struct sdma *s, int *length)
+{
+	void *cookie = s->cookie[s->outdex];
+
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(s->flags & SDMA_FLAGS_BD2);
+#endif
+	if (length)
+		*length = s->bd[s->outdex].status & SDMA_LEN_MASK;
+	s->outdex = sdma_next_outdex(s);
+	return cookie;
+}
+
+static inline void sdma_submit_buffer2(struct sdma *s, void *cookie,
+					void *data1, void *data2, int length)
+{
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
+#endif
+	s->cookie[s->index] = cookie;
+	s->bd2[s->index].data1 = data1;
+	s->bd2[s->index].data2 = data2;
+	s->bd2[s->index].status = SDMA_BD_READY | length;
+	s->index = sdma_next_index(s);
+	if (s->flags & SDMA_FLAGS_ENABLE_TASK)
+		sdma_enable_task(s->tasknum);
+}
+
+static inline void *sdma_retrieve_buffer2(struct sdma *s, int *length)
+{
+	void *cookie = s->cookie[s->outdex];
+
+#ifdef CONFIG_BESTCOMM_DEBUG
+	BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
+#endif
+	if (length)
+		*length = s->bd2[s->outdex].status & SDMA_LEN_MASK;
+	s->outdex = sdma_next_outdex(s);
+	return cookie;
+}
+
+#define SDMA_TASK_MAGIC		0x4243544B	/* 'BCTK' */
+
+/* the size fields are given in number of 32-bit words */
+struct sdma_task_header {
+	u32	magic;
+	u8	desc_size;
+	u8	var_size;
+	u8	inc_size;
+	u8	first_var;
+	u8	reserved[8];
+};
+
+#define SDMA_DESC_NOP		0x000001f8
+#define SDMA_LCD_MASK		0x80000000
+#define SDMA_DRD_EXTENDED	0x40000000
+
+#define sdma_drd_is_extended(desc) ((desc) & SDMA_DRD_EXTENDED)
+
+static inline int sdma_desc_is_drd(u32 desc) {
+	return !(desc & SDMA_LCD_MASK) && desc != SDMA_DESC_NOP;
+};
+
+#define SDMA_PRAGMA_BIT_RSV		7	/* reserved pragma bit */
+#define SDMA_PRAGMA_BIT_PRECISE_INC	6	/* increment 0=when possible, */
+						/*	1=iter end */
+#define SDMA_PRAGMA_BIT_RST_ERROR_NO	5	/* don't reset errors on */
+						/* task enable */
+#define SDMA_PRAGMA_BIT_PACK		4	/* pack data enable */
+#define SDMA_PRAGMA_BIT_INTEGER		3	/* data alignment */
+						/* 0=frac(msb), 1=int(lsb) */
+#define SDMA_PRAGMA_BIT_SPECREAD	2	/* XLB speculative read */
+#define SDMA_PRAGMA_BIT_CW		1	/* write line buffer enable */
+#define SDMA_PRAGMA_BIT_RL		0	/* read line buffer enable */
+
+#define SDMA_STD_PRAGMA		((0 << SDMA_PRAGMA_BIT_RSV)		| \
+				 (0 << SDMA_PRAGMA_BIT_PRECISE_INC)	| \
+				 (0 << SDMA_PRAGMA_BIT_RST_ERROR_NO)	| \
+				 (0 << SDMA_PRAGMA_BIT_PACK)		| \
+				 (0 << SDMA_PRAGMA_BIT_INTEGER)		| \
+				 (1 << SDMA_PRAGMA_BIT_SPECREAD)	| \
+				 (1 << SDMA_PRAGMA_BIT_CW)		| \
+				 (1 << SDMA_PRAGMA_BIT_RL))
+
+#define SDMA_PCI_PRAGMA		((0 << SDMA_PRAGMA_BIT_RSV)		| \
+				 (0 << SDMA_PRAGMA_BIT_PRECISE_INC)	| \
+				 (0 << SDMA_PRAGMA_BIT_RST_ERROR_NO)	| \
+				 (0 << SDMA_PRAGMA_BIT_PACK)		| \
+				 (1 << SDMA_PRAGMA_BIT_INTEGER)		| \
+				 (1 << SDMA_PRAGMA_BIT_SPECREAD)	| \
+				 (1 << SDMA_PRAGMA_BIT_CW)		| \
+				 (1 << SDMA_PRAGMA_BIT_RL))
+
+#define SDMA_ATA_PRAGMA		SDMA_STD_PRAGMA
+#define SDMA_CRC16_DP_0_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_CRC16_DP_1_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_FEC_RX_BD_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_FEC_TX_BD_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_DP_0_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_DP_1_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_DP_2_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_DP_3_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_DP_BD_0_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_DP_BD_1_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_RX_BD_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_TX_BD_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_GEN_LPC_PRAGMA	SDMA_STD_PRAGMA
+#define SDMA_PCI_RX_PRAGMA	SDMA_PCI_PRAGMA
+#define SDMA_PCI_TX_PRAGMA	SDMA_PCI_PRAGMA
+
+static inline void sdma_set_task_pragma(int task, int pragma)
+{
+	u32 *fdt = &sdma.tdt[task].fdt;
+	*fdt = (*fdt & ~0xff) | pragma;
+}
+
+static inline void sdma_set_task_auto_start(int task, int next_task)
+{
+	u16 *tcr = &sdma.io->tcr[task];
+	out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
+}
+
+#define SDMA_INITIATOR_ALWAYS	 0
+#define SDMA_INITIATOR_SCTMR_0	 1
+#define SDMA_INITIATOR_SCTMR_1	 2
+#define SDMA_INITIATOR_FEC_RX	 3
+#define SDMA_INITIATOR_FEC_TX	 4
+#define SDMA_INITIATOR_ATA_RX	 5
+#define SDMA_INITIATOR_ATA_TX	 6
+#define SDMA_INITIATOR_SCPCI_RX	 7
+#define SDMA_INITIATOR_SCPCI_TX	 8
+#define SDMA_INITIATOR_PSC3_RX	 9
+#define SDMA_INITIATOR_PSC3_TX	10
+#define SDMA_INITIATOR_PSC2_RX	11
+#define SDMA_INITIATOR_PSC2_TX	12
+#define SDMA_INITIATOR_PSC1_RX	13
+#define SDMA_INITIATOR_PSC1_TX	14
+#define SDMA_INITIATOR_SCTMR_2	15
+#define SDMA_INITIATOR_SCLPC	16
+#define SDMA_INITIATOR_PSC5_RX	17
+#define SDMA_INITIATOR_PSC5_TX	18
+#define SDMA_INITIATOR_PSC4_RX	19
+#define SDMA_INITIATOR_PSC4_TX	20
+#define SDMA_INITIATOR_I2C2_RX	21
+#define SDMA_INITIATOR_I2C2_TX	22
+#define SDMA_INITIATOR_I2C1_RX	23
+#define SDMA_INITIATOR_I2C1_TX	24
+#define SDMA_INITIATOR_PSC6_RX	25
+#define SDMA_INITIATOR_PSC6_TX	26
+#define SDMA_INITIATOR_IRDA_RX	25
+#define SDMA_INITIATOR_IRDA_TX	26
+#define SDMA_INITIATOR_SCTMR_3	27
+#define SDMA_INITIATOR_SCTMR_4	28
+#define SDMA_INITIATOR_SCTMR_5	29
+#define SDMA_INITIATOR_SCTMR_6	30
+#define SDMA_INITIATOR_SCTMR_7	31
+
+#define SDMA_IPR_ALWAYS	7
+#define SDMA_IPR_SCTMR_0 	2
+#define SDMA_IPR_SCTMR_1 	2
+#define SDMA_IPR_FEC_RX 	6
+#define SDMA_IPR_FEC_TX 	5
+#define SDMA_IPR_ATA_RX 	4
+#define SDMA_IPR_ATA_TX 	3
+#define SDMA_IPR_SCPCI_RX	2
+#define SDMA_IPR_SCPCI_TX	2
+#define SDMA_IPR_PSC3_RX	2
+#define SDMA_IPR_PSC3_TX	2
+#define SDMA_IPR_PSC2_RX	2
+#define SDMA_IPR_PSC2_TX	2
+#define SDMA_IPR_PSC1_RX	2
+#define SDMA_IPR_PSC1_TX	2
+#define SDMA_IPR_SCTMR_2	2
+#define SDMA_IPR_SCLPC		2
+#define SDMA_IPR_PSC5_RX	2
+#define SDMA_IPR_PSC5_TX	2
+#define SDMA_IPR_PSC4_RX	2
+#define SDMA_IPR_PSC4_TX	2
+#define SDMA_IPR_I2C2_RX	2
+#define SDMA_IPR_I2C2_TX	2
+#define SDMA_IPR_I2C1_RX	2
+#define SDMA_IPR_I2C1_TX	2
+#define SDMA_IPR_PSC6_RX	2
+#define SDMA_IPR_PSC6_TX	2
+#define SDMA_IPR_IRDA_RX	2
+#define SDMA_IPR_IRDA_TX	2
+#define SDMA_IPR_SCTMR_3	2
+#define SDMA_IPR_SCTMR_4	2
+#define SDMA_IPR_SCTMR_5	2
+#define SDMA_IPR_SCTMR_6	2
+#define SDMA_IPR_SCTMR_7	2
+
+extern struct sdma *sdma_alloc(int request_queue_size);
+extern void sdma_free(struct sdma *sdma_struct);
+extern int sdma_load_task(u32 *task_image);
+extern void *sdma_sram_alloc(int size, int alignment, u32 *dma_handle);
+extern void sdma_init_bd(struct sdma *s);
+extern void sdma_init_bd2(struct sdma *s);
+
+#define FIELD_OFFSET(s,f) ((unsigned long)(&(((struct s*)0)->f)))
+
+#endif  /* __BESTCOMM_BESTCOMM_H__ */
diff -uNr linux-2.6.20.ppc64/arch/powerpc/platforms/52xx/Makefile linux-2.6.20.fec/arch/powerpc/platforms/52xx/Makefile
--- linux-2.6.20.ppc64/arch/powerpc/platforms/52xx/Makefile	2007-03-22 11:17:52.000000000 +0000
+++ linux-2.6.20.fec/arch/powerpc/platforms/52xx/Makefile	2007-03-27 23:23:04.000000000 +0100
@@ -4,6 +4,7 @@
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-y				+= mpc52xx_pic.o mpc52xx_common.o
 obj-$(CONFIG_PCI)		+= mpc52xx_pci.o
+obj-$(CONFIG_PPC_BESTCOMM) 	+= bestcomm.o
 endif
 
 obj-$(CONFIG_PPC_EFIKA)		+= efika.o

linux-2.6-ondemand-timer.patch:
 drivers/cpufreq/cpufreq_ondemand.c |    2 -
 include/linux/timer.h              |    1 
 include/linux/workqueue.h          |    6 +++
 kernel/timer.c                     |   65 ++++++++++++++++++++++++++++++++-----
 4 files changed, 65 insertions(+), 9 deletions(-)

--- NEW FILE linux-2.6-ondemand-timer.patch ---
>From davej  Wed Mar 28 19:01:19 2007
Return-path: <venkatesh.pallipadi at intel.com>
X-Spam-Checker-Version: SpamAssassin 3.1.8 (2007-02-13) on
	gelk.kernelslacker.org
X-Spam-Level: 
X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00 autolearn=ham
	version=3.1.8
Envelope-to: davej at codemonkey.org.uk
Delivery-date: Thu, 29 Mar 2007 00:01:12 +0100
Received: from testure.choralone.org [194.9.77.134]
	by gelk.kernelslacker.org with IMAP (fetchmail-6.3.6)
	for <davej at localhost> (single-drop); Wed, 28 Mar 2007 19:01:19 -0400 (EDT)
Received: from mga01.intel.com ([192.55.52.88])
	by testure.choralone.org with esmtp (Exim 4.63)
	(envelope-from <venkatesh.pallipadi at intel.com>)
	id 1HWh8h-0006J9-Es
	for davej at codemonkey.org.uk; Thu, 29 Mar 2007 00:01:11 +0100
Received: from fmsmga001.fm.intel.com ([10.253.24.23])
  by mga01.intel.com with ESMTP; 28 Mar 2007 16:01:04 -0700
Received: from linux-os.sc.intel.com ([172.25.110.8])
  by fmsmga001.fm.intel.com with ESMTP; 28 Mar 2007 16:01:03 -0700
X-ExtLoop1: 1
X-IronPort-AV: i="4.14,342,1170662400"; 
   d="scan'208"; a="221109611:sNHT21096852"
Received: by linux-os.sc.intel.com (Postfix, from userid 47009)
	id AADD228006; Wed, 28 Mar 2007 16:00:21 -0700 (PDT)
Date: Wed, 28 Mar 2007 16:00:21 -0700
From: Venki Pallipadi <venkatesh.pallipadi at intel.com>
To: Oleg Nesterov <oleg at tv-sign.ru>
Cc: linux-kernel <linux-kernel at vger.kernel.org>,
	akpm at linux-foundation.org, davej at codemonkey.org.uk,
	johnstul at us.ibm.com, mingo at elte.hu, tglx at linutronix.de,
	Andi Kleen <ak at suse.de>
Subject: Re: [PATCH] Add support for deferrable timers (respun-Mar28)
Message-ID: <20070328230021.GA29774 at linux-os.sc.intel.com>
References: <200703212353.l2LNrNOj007453 at shell0.pdx.osdl.net> <20070322140532.GA120 at tv-sign.ru> <20070322151817.GA29840 at linux-os.sc.intel.com> <20070322161355.GA160 at tv-sign.ru> <20070327204344.GA21529 at linux-os.sc.intel.com> <20070327211145.GB216 at tv-sign.ru> <20070327215542.GA27408 at linux-os.sc.intel.com> <20070327222227.GA279 at tv-sign.ru>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20070327222227.GA279 at tv-sign.ru>
User-Agent: Mutt/1.4.1i
Status: RO
Content-Length: 6118
Lines: 195


Andrew,

Please drop the patch you included yesterday and two incremental patches and
use the patch below.

This patch is - yesterday's patch + Your tidy cleanup +
minor changes based on comments from Oleg and Andi. This is a lot
cleaner (and smaller) than earlier patches.

Thanks,
Venki


Introduce a new flag for timers - deferrable:
Timers that work normally when system is busy. But, will not cause CPU to
come out of idle (just to service this timer), when CPU is idle. Instead,
this timer will be serviced when CPU eventually wakes up with a subsequent
non-deferrable timer.

The main advantage of this is to avoid unnecessary timer interrupts when
CPU is idle. If the routine currently called by a timer can wait until next
event without any issues, this new timer can be used to setup timer event
for that routine. This, with dynticks, allows CPUs to be lazy, allowing them
to stay in idle for extended period of time by reducing unnecesary wakeup and
thereby reducing the power consumption.

This patch:
Builds this new timer on top of existing timer infrastructure. It uses
last bit in 'base' pointer of timer_list structure to store this
deferrable timer flag. __next_timer_interrupt() function
skips over these deferrable timers when CPU looks for
next timer event for which it has to wake up.

This is exported by a new interface init_timer_deferrable() that can
be called in place of regular init_timer().

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>

Index: new/kernel/timer.c
===================================================================
--- new.orig/kernel/timer.c	2007-03-22 16:27:44.000000000 -0800
+++ new/kernel/timer.c	2007-03-28 10:05:38.000000000 -0800
@@ -74,7 +74,7 @@
 	tvec_t tv3;
 	tvec_t tv4;
 	tvec_t tv5;
-} ____cacheline_aligned_in_smp;
+} ____cacheline_aligned;
 
 typedef struct tvec_t_base_s tvec_base_t;
 
@@ -82,6 +82,37 @@
 EXPORT_SYMBOL(boot_tvec_bases);
 static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
 
+/*
+ * Note that all tvec_bases is 2 byte aligned and lower bit of
+ * base in timer_list is guaranteed to be zero. Use the LSB for
+ * the new flag to indicate whether the timer is deferrable
+ */
+#define TBASE_DEFERRABLE_FLAG		(0x1)
+
+/* Functions below help us manage 'deferrable' flag */
+static inline unsigned int tbase_get_deferrable(tvec_base_t *base)
+{
+	return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
+}
+
+static inline tvec_base_t *tbase_get_base(tvec_base_t *base)
+{
+	return ((tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG));
+}
+
+static inline void timer_set_deferrable(struct timer_list *timer)
+{
+	timer->base = ((tvec_base_t *)((unsigned long)(timer->base) |
+	                               TBASE_DEFERRABLE_FLAG));
+}
+
+static inline void
+timer_set_base(struct timer_list *timer, tvec_base_t *new_base)
+{
+	timer->base = (tvec_base_t *)((unsigned long)(new_base) |
+	                              tbase_get_deferrable(timer->base));
+}
+
 /**
  * __round_jiffies - function to round jiffies to a full second
  * @j: the time in (absolute) jiffies that should be rounded
@@ -295,6 +326,13 @@
 }
 EXPORT_SYMBOL(init_timer);
 
+void fastcall init_timer_deferrable(struct timer_list *timer)
+{
+	init_timer(timer);
+	timer_set_deferrable(timer);
+}
+EXPORT_SYMBOL(init_timer_deferrable);
+
 static inline void detach_timer(struct timer_list *timer,
 				int clear_pending)
 {
@@ -325,10 +363,11 @@
 	tvec_base_t *base;
 
 	for (;;) {
-		base = timer->base;
+		tvec_base_t *prelock_base = timer->base;
+		base = tbase_get_base(prelock_base);
 		if (likely(base != NULL)) {
 			spin_lock_irqsave(&base->lock, *flags);
-			if (likely(base == timer->base))
+			if (likely(prelock_base == timer->base))
 				return base;
 			/* The timer has migrated to another CPU */
 			spin_unlock_irqrestore(&base->lock, *flags);
@@ -365,11 +404,11 @@
 		 */
 		if (likely(base->running_timer != timer)) {
 			/* See the comment in lock_timer_base() */
-			timer->base = NULL;
+			timer_set_base(timer, NULL);
 			spin_unlock(&base->lock);
 			base = new_base;
 			spin_lock(&base->lock);
-			timer->base = base;
+			timer_set_base(timer, base);
 		}
 	}
 
@@ -397,7 +436,7 @@
 	timer_stats_timer_set_start_info(timer);
   	BUG_ON(timer_pending(timer) || !timer->function);
 	spin_lock_irqsave(&base->lock, flags);
-	timer->base = base;
+	timer_set_base(timer, base);
 	internal_add_timer(base, timer);
 	spin_unlock_irqrestore(&base->lock, flags);
 }
@@ -548,7 +587,7 @@
 	 * don't have to detach them individually.
 	 */
 	list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
-		BUG_ON(timer->base != base);
+		BUG_ON(tbase_get_base(timer->base) != base);
 		internal_add_timer(base, timer);
 	}
 
@@ -634,6 +673,9 @@
 	index = slot = timer_jiffies & TVR_MASK;
 	do {
 		list_for_each_entry(nte, base->tv1.vec + slot, entry) {
+ 			if (tbase_get_deferrable(nte->base))
+ 				continue;
+ 
 			found = 1;
 			expires = nte->expires;
 			/* Look at the cascade bucket(s)? */
@@ -1602,6 +1644,13 @@
 						cpu_to_node(cpu));
 			if (!base)
 				return -ENOMEM;
+
+			/* Make sure that tvec_base is 2 byte aligned */
+			if (tbase_get_deferrable(base)) {
+				WARN_ON(1);
+				kfree(base);
+				return -ENOMEM;
+			}
 			memset(base, 0, sizeof(*base));
 			per_cpu(tvec_bases, cpu) = base;
 		} else {
@@ -1643,7 +1692,7 @@
 	while (!list_empty(head)) {
 		timer = list_entry(head->next, struct timer_list, entry);
 		detach_timer(timer, 0);
-		timer->base = new_base;
+		timer_set_base(timer, new_base);
 		internal_add_timer(new_base, timer);
 	}
 }
Index: new/include/linux/timer.h
===================================================================
--- new.orig/include/linux/timer.h	2007-03-22 16:27:44.000000000 -0800
+++ new/include/linux/timer.h	2007-03-28 10:03:14.000000000 -0800
@@ -37,6 +37,7 @@
 		TIMER_INITIALIZER(_function, _expires, _data)
 
 void fastcall init_timer(struct timer_list * timer);
+void fastcall init_timer_deferrable(struct timer_list *timer);
 
 static inline void setup_timer(struct timer_list * timer,
 				void (*function)(unsigned long),




More information about the fedora-cvs-commits mailing list