[kernel] r10924 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series

Maximilian Attems maks at alioth.debian.org
Thu Mar 20 11:32:15 UTC 2008


Author: maks
Date: Thu Mar 20 11:32:14 2008
New Revision: 10924

Log:
update to 2.6.25-rc6-git3

acpi memstick, input + x86 merge, fixes regressions
no conflicts.


Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc6-git3
Removed:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc6-git1
Modified:
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1

Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc6-git3
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc6-git3	Thu Mar 20 11:32:14 2008
@@ -0,0 +1,4062 @@
+diff --git a/Documentation/input/notifier.txt b/Documentation/input/notifier.txt
+new file mode 100644
+index 0000000..95172ca
+--- /dev/null
++++ b/Documentation/input/notifier.txt
+@@ -0,0 +1,52 @@
++Keyboard notifier
++
++One can use register_keyboard_notifier to get called back on keyboard
++events (see kbd_keycode() function for details).  The passed structure is
++keyboard_notifier_param:
++
++- 'vc' always provide the VC for which the keyboard event applies;
++- 'down' is 1 for a key press event, 0 for a key release;
++- 'shift' is the current modifier state, mask bit indexes are KG_*;
++- 'value' depends on the type of event.
++
++- KBD_KEYCODE events are always sent before other events, value is the keycode.
++- KBD_UNBOUND_KEYCODE events are sent if the keycode is not bound to a keysym.
++  value is the keycode.
++- KBD_UNICODE events are sent if the keycode -> keysym translation produced a
++  unicode character. value is the unicode value.
++- KBD_KEYSYM events are sent if the keycode -> keysym translation produced a
++  non-unicode character. value is the keysym.
++- KBD_POST_KEYSYM events are sent after the treatment of non-unicode keysyms.
++  That permits one to inspect the resulting LEDs for instance.
++
++For each kind of event but the last, the callback may return NOTIFY_STOP in
++order to "eat" the event: the notify loop is stopped and the keyboard event is
++dropped.
++
++In a rough C snippet, we have:
++
++kbd_keycode(keycode) {
++	...
++	params.value = keycode;
++	if (notifier_call_chain(KBD_KEYCODE,&params) == NOTIFY_STOP)
++	    || !bound) {
++		notifier_call_chain(KBD_UNBOUND_KEYCODE,&params);
++		return;
++	}
++
++	if (unicode) {
++		param.value = unicode;
++		if (notifier_call_chain(KBD_UNICODE,&params) == NOTIFY_STOP)
++			return;
++		emit unicode;
++		return;
++	}
++
++	params.value = keysym;
++	if (notifier_call_chain(KBD_KEYSYM,&params) == NOTIFY_STOP)
++		return;
++	apply keysym;
++	notifier_call_chain(KBD_POST_KEYSYM,&params);
++}
++
++NOTE: This notifier is usually called from interrupt context.
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 622f784..650b0d8 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -732,6 +732,8 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			     (Don't attempt to blink the leds)
+ 	i8042.noaux	[HW] Don't check for auxiliary (== mouse) port
+ 	i8042.nokbd	[HW] Don't check/create keyboard port
++	i8042.noloop	[HW] Disable the AUX Loopback command while probing
++			     for the AUX port
+ 	i8042.nomux	[HW] Don't check presence of an active multiplexing
+ 			     controller
+ 	i8042.nopnp	[HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
+diff --git a/Documentation/mca.txt b/Documentation/mca.txt
+index aabce4a..510375d 100644
+--- a/Documentation/mca.txt
++++ b/Documentation/mca.txt
+@@ -143,14 +143,7 @@ MCA Device Drivers
+ 
+ Currently, there are a number of MCA-specific device drivers.
+ 
+-1) PS/2 ESDI
+-	drivers/block/ps2esdi.c
+-	include/linux/ps2esdi.h
+-   Uses major number 36, and should use /dev files /dev/eda, /dev/edb.
+-   Supports two drives, but only one controller.  May use the
+-   command-line args "ed=cyl,head,sec" and "tp720".
+-
+-2) PS/2 SCSI
++1) PS/2 SCSI
+ 	drivers/scsi/ibmmca.c
+ 	drivers/scsi/ibmmca.h
+    The driver for the IBM SCSI subsystem.  Includes both integrated
+@@ -159,25 +152,25 @@ Currently, there are a number of MCA-specific device drivers.
+    machine with a front-panel display (i.e. model 95), you can use
+    "ibmmcascsi=display" to enable a drive activity indicator.
+ 
+-3) 3c523
++2) 3c523
+ 	drivers/net/3c523.c
+ 	drivers/net/3c523.h
+    3Com 3c523 Etherlink/MC ethernet driver.
+ 
+-4) SMC Ultra/MCA and IBM Adapter/A
++3) SMC Ultra/MCA and IBM Adapter/A
+ 	drivers/net/smc-mca.c
+ 	drivers/net/smc-mca.h
+ 	Driver for the MCA version of the SMC Ultra and various other
+ 	OEM'ed and work-alike cards (Elite, Adapter/A, etc).
+ 
+-5) NE/2
++4) NE/2
+ 	driver/net/ne2.c
+ 	driver/net/ne2.h
+ 	The NE/2 is the MCA version of the NE2000.  This may not work
+ 	with clones that have a different adapter id than the original
+ 	NE/2.
+ 
+-6) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and
++5) Future Domain MCS-600/700, OEM'd IBM Fast SCSI Adapter/A and
+    Reply Sound Blaster/SCSI (SCSI part)
+ 	Better support for these cards than the driver for ISA.
+    Supports multiple cards with IRQ sharing.
+diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
+index 7a9db35..1c445c7 100644
+--- a/crypto/async_tx/async_xor.c
++++ b/crypto/async_tx/async_xor.c
+@@ -271,7 +271,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
+ 
+ 	BUG_ON(src_cnt <= 1);
+ 
+-	if (device) {
++	if (device && src_cnt <= device->max_xor) {
+ 		dma_addr_t *dma_src = (dma_addr_t *) src_list;
+ 		unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
+ 		int i;
+diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
+index d25ef96..44ad90c 100644
+--- a/drivers/acpi/asus_acpi.c
++++ b/drivers/acpi/asus_acpi.c
+@@ -610,7 +610,7 @@ write_led(const char __user * buffer, unsigned long count,
+ 	    (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
+ 
+ 	if (invert)		/* invert target value */
+-		led_out = !led_out & 0x1;
++		led_out = !led_out;
+ 
+ 	if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
+ 		printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n",
+diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
+index f6215e8..d5729d5 100644
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -293,13 +293,12 @@ static int extract_package(struct acpi_battery *battery,
+ 				strncpy(ptr, (u8 *)&element->integer.value,
+ 					sizeof(acpi_integer));
+ 				ptr[sizeof(acpi_integer)] = 0;
+-			} else return -EFAULT;
++			} else
++				*ptr = 0; /* don't have value */
+ 		} else {
+-			if (element->type == ACPI_TYPE_INTEGER) {
+-				int *x = (int *)((u8 *)battery +
+-						offsets[i].offset);
+-				*x = element->integer.value;
+-			} else return -EFAULT;
++			int *x = (int *)((u8 *)battery + offsets[i].offset);
++			*x = (element->type == ACPI_TYPE_INTEGER) ?
++				element->integer.value : -1;
+ 		}
+ 	}
+ 	return 0;
+diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
+index 307cef6..fa44fb9 100644
+--- a/drivers/acpi/dock.c
++++ b/drivers/acpi/dock.c
+@@ -710,6 +710,7 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
+ 	if (!count)
+ 		return -EINVAL;
+ 
++	begin_undock(dock_station);
+ 	ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
+ 	return ret ? ret: count;
+ }
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index e7e197e..7222a18 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -129,7 +129,6 @@ static struct acpi_ec {
+ 	struct mutex lock;
+ 	wait_queue_head_t wait;
+ 	struct list_head list;
+-	atomic_t irq_count;
+ 	u8 handlers_installed;
+ } *boot_ec, *first_ec;
+ 
+@@ -182,8 +181,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+ {
+ 	int ret = 0;
+ 
+-	atomic_set(&ec->irq_count, 0);
+-
+ 	if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
+ 		     test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
+ 		force_poll = 1;
+@@ -230,7 +227,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
+ 		while (time_before(jiffies, delay)) {
+ 			if (acpi_ec_check_status(ec, event))
+ 				goto end;
+-			msleep(5);
+ 		}
+ 	}
+ 	pr_err(PREFIX "acpi_ec_wait timeout,"
+@@ -533,13 +529,6 @@ static u32 acpi_ec_gpe_handler(void *data)
+ 	struct acpi_ec *ec = data;
+ 
+ 	pr_debug(PREFIX "~~~> interrupt\n");
+-	atomic_inc(&ec->irq_count);
+-	if (atomic_read(&ec->irq_count) > 5) {
+-		pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
+-		acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR);
+-		clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
+-		return ACPI_INTERRUPT_HANDLED;
+-	}
+ 	clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
+ 	if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
+ 		wake_up(&ec->wait);
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 6f3b217..e8e2d88 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -216,8 +216,10 @@ static void acpi_safe_halt(void)
+ 	 * test NEED_RESCHED:
+ 	 */
+ 	smp_mb();
+-	if (!need_resched())
++	if (!need_resched()) {
+ 		safe_halt();
++		local_irq_disable();
++	}
+ 	current_thread_info()->status |= TS_POLLING;
+ }
+ 
+@@ -421,7 +423,9 @@ static void acpi_processor_idle(void)
+ 		else
+ 			acpi_safe_halt();
+ 
+-		local_irq_enable();
++		if (irqs_disabled())
++			local_irq_enable();
++
+ 		return;
+ 	}
+ 
+@@ -530,7 +534,9 @@ static void acpi_processor_idle(void)
+ 		 *       skew otherwise.
+ 		 */
+ 		sleep_ticks = 0xFFFFFFFF;
+-		local_irq_enable();
++		if (irqs_disabled())
++			local_irq_enable();
++
+ 		break;
+ 
+ 	case ACPI_STATE_C2:
+diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
+index 1bc0c74..12fb44f 100644
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -807,40 +807,11 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
+ static int acpi_video_bus_check(struct acpi_video_bus *video)
+ {
+ 	acpi_status status = -ENOENT;
+-	long device_id;
+-	struct device *dev;
+-	struct acpi_device *device;
++
+ 
+ 	if (!video)
+ 		return -EINVAL;
+ 
+-	device = video->device;
+-
+-	status =
+-	    acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
+-
+-	if (!ACPI_SUCCESS(status))
+-		return -ENODEV;
+-
+-	/* We need to attempt to determine whether the _ADR refers to a
+-	   PCI device or not. There's no terribly good way to do this,
+-	   so the best we can hope for is to assume that there'll never
+-	   be a video device in the host bridge */
+-	if (device_id >= 0x10000) {
+-		/* It looks like a PCI device. Does it exist? */
+-		dev = acpi_get_physical_device(device->handle);
+-	} else {
+-		/* It doesn't look like a PCI device. Does its parent
+-		   exist? */
+-		acpi_handle phandle;
+-		if (acpi_get_parent(device->handle, &phandle))
+-			return -ENODEV;
+-		dev = acpi_get_physical_device(phandle);
+-	}
+-	if (!dev)
+-		return -ENODEV;
+-	put_device(dev);
+-
+ 	/* Since there is no HID, CID and so on for VGA driver, we have
+ 	 * to check well known required nodes.
+ 	 */
+@@ -1366,37 +1337,8 @@ acpi_video_bus_write_DOS(struct file *file,
+ 
+ static int acpi_video_bus_add_fs(struct acpi_device *device)
+ {
+-	long device_id;
+-	int status;
+ 	struct proc_dir_entry *entry = NULL;
+ 	struct acpi_video_bus *video;
+-	struct device *dev;
+-
+-	status =
+-	    acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
+-
+-	if (!ACPI_SUCCESS(status))
+-		return -ENODEV;
+-
+-	/* We need to attempt to determine whether the _ADR refers to a
+-	   PCI device or not. There's no terribly good way to do this,
+-	   so the best we can hope for is to assume that there'll never
+-	   be a video device in the host bridge */
+-	if (device_id >= 0x10000) {
+-		/* It looks like a PCI device. Does it exist? */
+-		dev = acpi_get_physical_device(device->handle);
+-	} else {
+-		/* It doesn't look like a PCI device. Does its parent
+-		   exist? */
+-		acpi_handle phandle;
+-		if (acpi_get_parent(device->handle, &phandle))
+-			return -ENODEV;
+-		dev = acpi_get_physical_device(phandle);
+-	}
+-	if (!dev)
+-		return -ENODEV;
+-	put_device(dev);
+-
+ 
+ 
+ 	video = acpi_driver_data(device);
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index e469647..25aba69 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -30,6 +30,7 @@ config ATA_NONSTANDARD
+ config ATA_ACPI
+ 	bool
+ 	depends on ACPI && PCI
++	select ACPI_DOCK
+ 	default y
+ 	help
+ 	  This option adds support for ATA-related ACPI objects.
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 6978469..17ee6ed 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -49,6 +49,10 @@
+ #define DRV_NAME	"ahci"
+ #define DRV_VERSION	"3.0"
+ 
++static int ahci_skip_host_reset;
++module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
++MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
++
+ static int ahci_enable_alpm(struct ata_port *ap,
+ 		enum link_pm policy);
+ static void ahci_disable_alpm(struct ata_port *ap);
+@@ -587,6 +591,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ 
+ 	/* Marvell */
+ 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
++	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
+ 
+ 	/* Generic, PCI class code for AHCI */
+ 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+@@ -661,6 +666,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
+ 	void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
+ 	u32 cap, port_map;
+ 	int i;
++	int mv;
+ 
+ 	/* make sure AHCI mode is enabled before accessing CAP */
+ 	ahci_enable_ahci(mmio);
+@@ -696,12 +702,16 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
+ 	 * presence register, as bit 4 (counting from 0)
+ 	 */
+ 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
++		if (pdev->device == 0x6121)
++			mv = 0x3;
++		else
++			mv = 0xf;
+ 		dev_printk(KERN_ERR, &pdev->dev,
+ 			   "MV_AHCI HACK: port_map %x -> %x\n",
+-			   hpriv->port_map,
+-			   hpriv->port_map & 0xf);
++			   port_map,
++			   port_map & mv);
+ 
+-		port_map &= 0xf;
++		port_map &= mv;
+ 	}
+ 
+ 	/* cross check port_map and cap.n_ports */
+@@ -1088,29 +1098,35 @@ static int ahci_reset_controller(struct ata_host *host)
+ 	ahci_enable_ahci(mmio);
+ 
+ 	/* global controller reset */
+-	tmp = readl(mmio + HOST_CTL);
+-	if ((tmp & HOST_RESET) == 0) {
+-		writel(tmp | HOST_RESET, mmio + HOST_CTL);
+-		readl(mmio + HOST_CTL); /* flush */
+-	}
++	if (!ahci_skip_host_reset) {
++		tmp = readl(mmio + HOST_CTL);
++		if ((tmp & HOST_RESET) == 0) {
++			writel(tmp | HOST_RESET, mmio + HOST_CTL);
++			readl(mmio + HOST_CTL); /* flush */
++		}
+ 
+-	/* reset must complete within 1 second, or
+-	 * the hardware should be considered fried.
+-	 */
+-	ssleep(1);
++		/* reset must complete within 1 second, or
++		 * the hardware should be considered fried.
++		 */
++		ssleep(1);
+ 
+-	tmp = readl(mmio + HOST_CTL);
+-	if (tmp & HOST_RESET) {
+-		dev_printk(KERN_ERR, host->dev,
+-			   "controller reset failed (0x%x)\n", tmp);
+-		return -EIO;
+-	}
++		tmp = readl(mmio + HOST_CTL);
++		if (tmp & HOST_RESET) {
++			dev_printk(KERN_ERR, host->dev,
++				   "controller reset failed (0x%x)\n", tmp);
++			return -EIO;
++		}
+ 
+-	/* turn on AHCI mode */
+-	ahci_enable_ahci(mmio);
++		/* turn on AHCI mode */
++		ahci_enable_ahci(mmio);
+ 
+-	/* some registers might be cleared on reset.  restore initial values */
+-	ahci_restore_initial_config(host);
++		/* Some registers might be cleared on reset.  Restore
++		 * initial values.
++		 */
++		ahci_restore_initial_config(host);
++	} else
++		dev_printk(KERN_INFO, host->dev,
++			   "skipping global host reset\n");
+ 
+ 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ 		u16 tmp16;
+@@ -1162,9 +1178,14 @@ static void ahci_init_controller(struct ata_host *host)
+ 	int i;
+ 	void __iomem *port_mmio;
+ 	u32 tmp;
++	int mv;
+ 
+ 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
+-		port_mmio = __ahci_port_base(host, 4);
++		if (pdev->device == 0x6121)
++			mv = 2;
++		else
++			mv = 4;
++		port_mmio = __ahci_port_base(host, mv);
+ 
+ 		writel(0, port_mmio + PORT_IRQ_MASK);
+ 
+@@ -2241,7 +2262,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	if (rc)
+ 		return rc;
+ 
+-	rc = pcim_iomap_regions(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
++	/* AHCI controllers often implement SFF compatible interface.
++	 * Grab all PCI BARs just in case.
++	 */
++	rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
+ 	if (rc == -EBUSY)
+ 		pcim_pin_device(pdev);
+ 	if (rc)
+diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
+index 0770cb7..bf98a56 100644
+--- a/drivers/ata/libata-acpi.c
++++ b/drivers/ata/libata-acpi.c
+@@ -118,45 +118,77 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
+ 		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
+ }
+ 
+-static void ata_acpi_handle_hotplug(struct ata_port *ap, struct kobject *kobj,
++static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
+ 				    u32 event)
+ {
+ 	char event_string[12];
+ 	char *envp[] = { event_string, NULL };
+-	struct ata_eh_info *ehi = &ap->link.eh_info;
+-
+-	if (event == 0 || event == 1) {
+-	       unsigned long flags;
+-	       spin_lock_irqsave(ap->lock, flags);
+-	       ata_ehi_clear_desc(ehi);
+-	       ata_ehi_push_desc(ehi, "ACPI event");
+-	       ata_ehi_hotplugged(ehi);
+-	       ata_port_freeze(ap);
+-	       spin_unlock_irqrestore(ap->lock, flags);
++	struct ata_eh_info *ehi;
++	struct kobject *kobj = NULL;
++	int wait = 0;
++	unsigned long flags;
++
++	if (!ap)
++		ap = dev->link->ap;
++	ehi = &ap->link.eh_info;
++
++	spin_lock_irqsave(ap->lock, flags);
++
++	switch (event) {
++	case ACPI_NOTIFY_BUS_CHECK:
++	case ACPI_NOTIFY_DEVICE_CHECK:
++		ata_ehi_push_desc(ehi, "ACPI event");
++		ata_ehi_hotplugged(ehi);
++		ata_port_freeze(ap);
++		break;
++
++	case ACPI_NOTIFY_EJECT_REQUEST:
++		ata_ehi_push_desc(ehi, "ACPI event");
++		if (dev)
++			dev->flags |= ATA_DFLAG_DETACH;
++		else {
++			struct ata_link *tlink;
++			struct ata_device *tdev;
++
++			ata_port_for_each_link(tlink, ap)
++				ata_link_for_each_dev(tdev, tlink)
++					tdev->flags |= ATA_DFLAG_DETACH;
++		}
++
++		ata_port_schedule_eh(ap);
++		wait = 1;
++		break;
+ 	}
+ 
++	if (dev) {
++		if (dev->sdev)
++			kobj = &dev->sdev->sdev_gendev.kobj;
++	} else
++		kobj = &ap->dev->kobj;
++
+ 	if (kobj) {
+ 		sprintf(event_string, "BAY_EVENT=%d", event);
+ 		kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
+ 	}
++
++	spin_unlock_irqrestore(ap->lock, flags);
++
++	if (wait)
++		ata_port_wait_eh(ap);
+ }
+ 
+ static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
+ {
+ 	struct ata_device *dev = data;
+-	struct kobject *kobj = NULL;
+ 
+-	if (dev->sdev)
+-		kobj = &dev->sdev->sdev_gendev.kobj;
+-
+-	ata_acpi_handle_hotplug(dev->link->ap, kobj, event);
++	ata_acpi_handle_hotplug(NULL, dev, event);
+ }
+ 
+ static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
+ {
+ 	struct ata_port *ap = data;
+ 
+-	ata_acpi_handle_hotplug(ap, &ap->dev->kobj, event);
++	ata_acpi_handle_hotplug(ap, NULL, event);
+ }
+ 
+ /**
+@@ -191,20 +223,30 @@ void ata_acpi_associate(struct ata_host *host)
+ 		else
+ 			ata_acpi_associate_ide_port(ap);
+ 
+-		if (ap->acpi_handle)
+-			acpi_install_notify_handler (ap->acpi_handle,
+-						     ACPI_SYSTEM_NOTIFY,
+-						     ata_acpi_ap_notify,
+-						     ap);
++		if (ap->acpi_handle) {
++			acpi_install_notify_handler(ap->acpi_handle,
++						    ACPI_SYSTEM_NOTIFY,
++						    ata_acpi_ap_notify, ap);
++#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
++			/* we might be on a docking station */
++			register_hotplug_dock_device(ap->acpi_handle,
++						     ata_acpi_ap_notify, ap);
++#endif
++		}
+ 
+ 		for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
+ 			struct ata_device *dev = &ap->link.device[j];
+ 
+-			if (dev->acpi_handle)
+-				acpi_install_notify_handler (dev->acpi_handle,
+-							     ACPI_SYSTEM_NOTIFY,
+-							     ata_acpi_dev_notify,
+-							     dev);
++			if (dev->acpi_handle) {
++				acpi_install_notify_handler(dev->acpi_handle,
++						ACPI_SYSTEM_NOTIFY,
++						ata_acpi_dev_notify, dev);
++#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
++				/* we might be on a docking station */
++				register_hotplug_dock_device(dev->acpi_handle,
++						ata_acpi_dev_notify, dev);
++#endif
++			}
+ 		}
+ 	}
+ }
+diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
+index 7e68edf..8786455 100644
+--- a/drivers/ata/pata_ali.c
++++ b/drivers/ata/pata_ali.c
+@@ -295,7 +295,7 @@ static void ali_lock_sectors(struct ata_device *adev)
+ static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
+ {
+ 	/* If its not a media command, its not worth it */
+-	if (qc->nbytes < 2048)
++	if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC)
+ 		return -EOPNOTSUPP;
+ 	return 0;
+ }
+diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
+index b6d230b..0d1d213 100644
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -44,16 +44,6 @@ config MAC_FLOPPY
+ 	  If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
+ 	  floppy controller, say Y here. Most commonly found in PowerMacs.
+ 
+-config BLK_DEV_PS2
+-	tristate "PS/2 ESDI hard disk support"
+-	depends on MCA && MCA_LEGACY && BROKEN
+-	help
+-	  Say Y here if you have a PS/2 machine with a MCA bus and an ESDI
+-	  hard disk.
+-
+-	  To compile this driver as a module, choose M here: the
+-	  module will be called ps2esdi.
+-
+ config AMIGA_Z2RAM
+ 	tristate "Amiga Zorro II ramdisk support"
+ 	depends on ZORRO
+diff --git a/drivers/block/Makefile b/drivers/block/Makefile
+index 01c9724..5e58430 100644
+--- a/drivers/block/Makefile
++++ b/drivers/block/Makefile
+@@ -13,7 +13,6 @@ obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
+ obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
+ obj-$(CONFIG_BLK_DEV_RAM)	+= brd.o
+ obj-$(CONFIG_BLK_DEV_LOOP)	+= loop.o
+-obj-$(CONFIG_BLK_DEV_PS2)	+= ps2esdi.o
+ obj-$(CONFIG_BLK_DEV_XD)	+= xd.o
+ obj-$(CONFIG_BLK_CPQ_DA)	+= cpqarray.o
+ obj-$(CONFIG_BLK_CPQ_CISS_DA)  += cciss.o
+diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
+deleted file mode 100644
+index 3c796e2..0000000
+--- a/drivers/block/ps2esdi.c
++++ /dev/null
+@@ -1,1079 +0,0 @@
+-/* ps2esdi driver based on assembler code by Arindam Banerji,
+-   written by Peter De Schrijver */
+-/* Reassuring note to IBM : This driver was NOT developed by vice-versa
+-   engineering the PS/2's BIOS */
+-/* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those 
+-   other lovely fish out there... */
+-/* This code was written during the long and boring WINA 
+-   elections 1994 */
+-/* Thanks to Arindam Banerij for giving me the source of his driver */
+-/* This code may be freely distributed and modified in any way, 
+-   as long as these notes remain intact */
+-
+-/*  Revised: 05/07/94 by Arindam Banerji (axb at cse.nd.edu) */
+-/*  Revised: 09/08/94 by Peter De Schrijver (stud11 at cc4.kuleuven.ac.be)
+-   Thanks to Arindam Banerij for sending me the docs of the adapter */
+-
+-/* BA Modified for ThinkPad 720 by Boris Ashkinazi */
+-/*                    (bash at vnet.ibm.com) 08/08/95 */
+-
+-/* Modified further for ThinkPad-720C by Uri Blumenthal */
+-/*                    (uri at watson.ibm.com) Sep 11, 1995 */
+-
+-/* TODO : 
+-   + Timeouts
+-   + Get disk parameters
+-   + DMA above 16MB
+-   + reset after read/write error
+- */
+-
+-#define DEVICE_NAME "PS/2 ESDI"
+-
+-#include <linux/major.h>
+-#include <linux/errno.h>
+-#include <linux/wait.h>
+-#include <linux/interrupt.h>
+-#include <linux/fs.h>
+-#include <linux/kernel.h>
+-#include <linux/genhd.h>
+-#include <linux/ps2esdi.h>
+-#include <linux/blkdev.h>
+-#include <linux/mca-legacy.h>
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/module.h>
+-#include <linux/hdreg.h>
+-
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/dma.h>
+-#include <asm/mca_dma.h>
+-#include <asm/uaccess.h>
+-
+-#define PS2ESDI_IRQ 14
+-#define MAX_HD 2
+-#define MAX_RETRIES 5
+-#define MAX_16BIT 65536
+-#define ESDI_TIMEOUT   0xf000
+-#define ESDI_STAT_TIMEOUT 4
+-
+-#define TYPE_0_CMD_BLK_LENGTH 2
+-#define TYPE_1_CMD_BLK_LENGTH 4
+-
+-static void reset_ctrl(void);
+-
+-static int ps2esdi_geninit(void);
+-
+-static void do_ps2esdi_request(struct request_queue * q);
+-
+-static void ps2esdi_readwrite(int cmd, struct request *req);
+-
+-static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
+-u_short cyl, u_short head, u_short sector, u_short length, u_char drive);
+-
+-static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
+-
+-static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
+-
+-static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id);
+-static void (*current_int_handler) (u_int) = NULL;
+-static void ps2esdi_normal_interrupt_handler(u_int);
+-static void ps2esdi_initial_reset_int_handler(u_int);
+-static void ps2esdi_geometry_int_handler(u_int);
+-static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
+-
+-static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
+-
+-static void dump_cmd_complete_status(u_int int_ret_code);
+-
+-static void ps2esdi_get_device_cfg(void);
+-
+-static void ps2esdi_reset_timer(unsigned long unused);
+-
+-static u_int dma_arb_level;		/* DMA arbitration level */
+-
+-static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
+-
+-static int no_int_yet;
+-static int ps2esdi_drives;
+-static u_short io_base;
+-static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0);
+-static int reset_status;
+-static int ps2esdi_slot = -1;
+-static int tp720esdi = 0;	/* Is it Integrated ESDI of ThinkPad-720? */
+-static int intg_esdi = 0;       /* If integrated adapter */
+-struct ps2esdi_i_struct {
+-	unsigned int head, sect, cyl, wpcom, lzone, ctl;
+-};
+-static DEFINE_SPINLOCK(ps2esdi_lock);
+-static struct request_queue *ps2esdi_queue;
+-static struct request *current_req;
+-
+-#if 0
+-#if 0				/* try both - I don't know which one is better... UB */
+-static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
+-{
+-	{4, 48, 1553, 0, 0, 0},
+-	{0, 0, 0, 0, 0, 0}};
+-#else
+-static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
+-{
+-	{64, 32, 161, 0, 0, 0},
+-	{0, 0, 0, 0, 0, 0}};
+-#endif
+-#endif
+-static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
+-{
+-	{0, 0, 0, 0, 0, 0},
+-	{0, 0, 0, 0, 0, 0}};
+-
+-static struct block_device_operations ps2esdi_fops =
+-{
+-	.owner		= THIS_MODULE,
+-	.getgeo		= ps2esdi_getgeo,
+-};
+-
+-static struct gendisk *ps2esdi_gendisk[2];
+-
+-/* initialization routine called by ll_rw_blk.c   */
+-static int __init ps2esdi_init(void)
+-{
+-
+-	int error = 0;
+-
+-	/* register the device - pass the name and major number */
+-	if (register_blkdev(PS2ESDI_MAJOR, "ed"))
+-		return -EBUSY;
+-
+-	/* set up some global information - indicating device specific info */
+-	ps2esdi_queue = blk_init_queue(do_ps2esdi_request, &ps2esdi_lock);
+-	if (!ps2esdi_queue) {
+-		unregister_blkdev(PS2ESDI_MAJOR, "ed");
+-		return -ENOMEM;
+-	}
+-
+-	/* some minor housekeeping - setup the global gendisk structure */
+-	error = ps2esdi_geninit();
+-	if (error) {
+-		printk(KERN_WARNING "PS2ESDI: error initialising"
+-			" device, releasing resources\n");
+-		unregister_blkdev(PS2ESDI_MAJOR, "ed");
+-		blk_cleanup_queue(ps2esdi_queue);
+-		return error;
+-	}
+-	return 0;
+-}				/* ps2esdi_init */
+-
+-#ifndef MODULE
+-
+-module_init(ps2esdi_init);
+-
+-#else
+-
+-static int cyl[MAX_HD] = {-1,-1};
+-static int head[MAX_HD] = {-1, -1};
+-static int sect[MAX_HD] = {-1, -1};
+-
+-module_param(tp720esdi, bool, 0);
+-module_param_array(cyl, int, NULL, 0);
+-module_param_array(head, int, NULL, 0);
+-module_param_array(sect, int, NULL, 0);
+-MODULE_LICENSE("GPL");
+-
+-int init_module(void) {
+-	int drive;
+-
+-	for(drive = 0; drive < MAX_HD; drive++) {
+-	        struct ps2esdi_i_struct *info = &ps2esdi_info[drive];
+-
+-        	if (cyl[drive] != -1) {
+-		  	info->cyl = info->lzone = cyl[drive];
+-			info->wpcom = 0;
+-		}
+-        	if (head[drive] != -1) {
+-			info->head = head[drive];
+-			info->ctl = (head[drive] > 8 ? 8 : 0);
+-		}
+-        	if (sect[drive] != -1) info->sect = sect[drive];
+-	}
+-	return ps2esdi_init();
+-}
+-
+-void
+-cleanup_module(void) {
+-	int i;
+-	if(ps2esdi_slot) {
+-		mca_mark_as_unused(ps2esdi_slot);
+-		mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
+-	}
+-	release_region(io_base, 4);
+-	free_dma(dma_arb_level);
+-	free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
+-	unregister_blkdev(PS2ESDI_MAJOR, "ed");
+-	blk_cleanup_queue(ps2esdi_queue);
+-	for (i = 0; i < ps2esdi_drives; i++) {
+-		del_gendisk(ps2esdi_gendisk[i]);
+-		put_disk(ps2esdi_gendisk[i]);
+-	}
+-}
+-#endif /* MODULE */
+-
+-/* handles boot time command line parameters */
+-void __init tp720_setup(char *str, int *ints)
+-{
+-	/* no params, just sets the tp720esdi flag if it exists */
+-
+-	printk("%s: TP 720 ESDI flag set\n", DEVICE_NAME);
+-	tp720esdi = 1;
+-}
+-
+-void __init ed_setup(char *str, int *ints)
+-{
+-	int hdind = 0;
+-
+-	/* handles 3 parameters only - corresponding to
+-	   1. Number of cylinders
+-	   2. Number of heads
+-	   3. Sectors/track
+-	 */
+-
+-	if (ints[0] != 3)
+-		return;
+-
+-	/* print out the information - seen at boot time */
+-	printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n",
+-	       DEVICE_NAME, ints[0], ints[1], ints[2], ints[3]);
+-
+-	/* set the index into device specific information table */
+-	if (ps2esdi_info[0].head != 0)
+-		hdind = 1;
+-
+-	/* set up all the device information */
+-	ps2esdi_info[hdind].head = ints[2];
+-	ps2esdi_info[hdind].sect = ints[3];
+-	ps2esdi_info[hdind].cyl = ints[1];
+-	ps2esdi_info[hdind].wpcom = 0;
+-	ps2esdi_info[hdind].lzone = ints[1];
+-	ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
+-#if 0				/* this may be needed for PS2/Mod.80, but it hurts ThinkPad! */
+-	ps2esdi_drives = hdind + 1;	/* increment index for the next time */
+-#endif
+-}				/* ed_setup */
+-
+-static int ps2esdi_getinfo(char *buf, int slot, void *d)
+-{
+-	int len = 0;
+-
+-	len += sprintf(buf + len, "DMA Arbitration Level: %d\n",
+-		       dma_arb_level);
+-	len += sprintf(buf + len, "IO Port: %x\n", io_base);
+-	len += sprintf(buf + len, "IRQ: 14\n");
+-	len += sprintf(buf + len, "Drives: %d\n", ps2esdi_drives);
+-
+-	return len;
+-}
+-
+-/* ps2 esdi specific initialization - called thru the gendisk chain */
+-static int __init ps2esdi_geninit(void)
+-{
+-	/*
+-	   The first part contains the initialization code
+-	   for the ESDI disk subsystem.  All we really do
+-	   is search for the POS registers of the controller
+-	   to do some simple setup operations.  First, we
+-	   must ensure that the controller is installed,
+-	   enabled, and configured as PRIMARY.  Then we must
+-	   determine the DMA arbitration level being used by
+-	   the controller so we can handle data transfer
+-	   operations properly.  If all of this works, then
+-	   we will set the INIT_FLAG to a non-zero value.
+-	 */
+-
+-	int slot = 0, i, reset_start, reset_end;
+-	u_char status;
+-	unsigned short adapterID;
+-	int error = 0;
+-
+-	if ((slot = mca_find_adapter(INTG_ESDI_ID, 0)) != MCA_NOTFOUND) {
+-		adapterID = INTG_ESDI_ID;
+-		printk("%s: integrated ESDI adapter found in slot %d\n",
+-		       DEVICE_NAME, slot+1);
+-#ifndef MODULE
+-		mca_set_adapter_name(slot, "PS/2 Integrated ESDI");
+-#endif
+-	} else if ((slot = mca_find_adapter(NRML_ESDI_ID, 0)) != -1) {
+-		adapterID = NRML_ESDI_ID;
+-		printk("%s: normal ESDI adapter found in slot %d\n",
+-		       DEVICE_NAME, slot+1);
+-		mca_set_adapter_name(slot, "PS/2 ESDI");
+-	} else {
+-		return -ENODEV;
+-	}
+-
+-	ps2esdi_slot = slot;
+-	mca_mark_as_used(slot);
+-	mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL);
+-
+-	/* Found the slot - read the POS register 2 to get the necessary
+-	   configuration and status information.  POS register 2 has the
+-	   following information :
+-	   Bit           Function
+-	   7             reserved = 0
+-	   6             arbitration method
+-	   0 - fairness enabled
+-	   1 - fairness disabled, linear priority assignment
+-	   5-2           arbitration level
+-	   1             alternate address
+-	   1              alternate address
+-	   0 - use addresses 0x3510 - 0x3517
+-	   0             adapter enable
+-	 */
+-
+-	status = mca_read_stored_pos(slot, 2);
+-	/* is it enabled ? */
+-	if (!(status & STATUS_ENABLED)) {
+-		printk("%s: ESDI adapter disabled\n", DEVICE_NAME);
+-		error = -ENODEV;
+-		goto err_out1;
+-	}
+-	/* try to grab IRQ, and try to grab a slow IRQ if it fails, so we can
+-	   share with the SCSI driver */
+-	if (request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
+-		  IRQF_DISABLED | IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk)
+-	    && request_irq(PS2ESDI_IRQ, ps2esdi_interrupt_handler,
+-			   IRQF_SHARED, "PS/2 ESDI", &ps2esdi_gendisk)
+-	    ) {
+-		printk("%s: Unable to get IRQ %d\n", DEVICE_NAME, PS2ESDI_IRQ);
+-		error = -EBUSY;
+-		goto err_out1;
+-	}
+-	if (status & STATUS_ALTERNATE)
+-		io_base = ALT_IO_BASE;
+-	else
+-		io_base = PRIMARY_IO_BASE;
+-
+-	if (!request_region(io_base, 4, "ed")) {
+-		printk(KERN_WARNING"Unable to request region 0x%x\n", io_base);
+-		error = -EBUSY;
+-		goto err_out2;
+-	}
+-	/* get the dma arbitration level */
+-	dma_arb_level = (status >> 2) & 0xf;
+-
+-	/* BA */
+-	printk("%s: DMA arbitration level : %d\n",
+-	       DEVICE_NAME, dma_arb_level);
+-
+-	LITE_ON;
+-	current_int_handler = ps2esdi_initial_reset_int_handler;
+-	reset_ctrl();
+-	reset_status = 0;
+-	reset_start = jiffies;
+-	while (!reset_status) {
+-		init_timer(&esdi_timer);
+-		esdi_timer.expires = jiffies + HZ;
+-		esdi_timer.data = 0;
+-		add_timer(&esdi_timer);
+-		sleep_on(&ps2esdi_int);
+-	}
+-	reset_end = jiffies;
+-	LITE_OFF;
+-	printk("%s: reset interrupt after %d jiffies,  %u.%02u secs\n",
+-	       DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ,
+-	       (reset_end - reset_start) % HZ);
+-
+-
+-	/* Integrated ESDI Disk and Controller has only one drive! */
+-	if (adapterID == INTG_ESDI_ID) {/* if not "normal" PS2 ESDI adapter */
+-		ps2esdi_drives = 1;	/* then we have only one physical disk! */		intg_esdi = 1;
+-	}
+-
+-
+-
+-	/* finally this part sets up some global data structures etc. */
+-
+-	ps2esdi_get_device_cfg();
+-
+-	/* some annoyance in the above routine returns TWO drives?
+-	 Is something else happining in the background?
+-	 Regaurdless we fix the # of drives again. AJK */
+-	/* Integrated ESDI Disk and Controller has only one drive! */
+-	if (adapterID == INTG_ESDI_ID)	/* if not "normal" PS2 ESDI adapter */
+-		ps2esdi_drives = 1;	/* Not three or two, ONE DAMNIT! */
+-
+-	current_int_handler = ps2esdi_normal_interrupt_handler;
+-
+-	if (request_dma(dma_arb_level, "ed") !=0) {
+-		printk(KERN_WARNING "PS2ESDI: Can't request dma-channel %d\n"
+-			,(int) dma_arb_level);
+-		error = -EBUSY;
+-		goto err_out3;
+-	}
+-	blk_queue_max_sectors(ps2esdi_queue, 128);
+-
+-	error = -ENOMEM;
+-	for (i = 0; i < ps2esdi_drives; i++) {
+-		struct gendisk *disk = alloc_disk(64);
+-		if (!disk)
+-			goto err_out4;
+-		disk->major = PS2ESDI_MAJOR;
+-		disk->first_minor = i<<6;
+-		sprintf(disk->disk_name, "ed%c", 'a'+i);
+-		disk->fops = &ps2esdi_fops;
+-		ps2esdi_gendisk[i] = disk;
+-	}
+-
+-	for (i = 0; i < ps2esdi_drives; i++) {
+-		struct gendisk *disk = ps2esdi_gendisk[i];
+-		set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect *
+-				ps2esdi_info[i].cyl);
+-		disk->queue = ps2esdi_queue;
+-		disk->private_data = &ps2esdi_info[i];
+-		add_disk(disk);
+-	}
+-	return 0;
+-err_out4:
+-	while (i--)
+-		put_disk(ps2esdi_gendisk[i]);
+-err_out3:
+-	release_region(io_base, 4);
+-err_out2:
+-	free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
+-err_out1:
+-	if(ps2esdi_slot) {
+-		mca_mark_as_unused(ps2esdi_slot);
+-		mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
+-	}
+-	return error;
+-}
+-
+-static void __init ps2esdi_get_device_cfg(void)
+-{
+-	u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
+-
+-	/*BA */ printk("%s: Drive 0\n", DEVICE_NAME);
+-	current_int_handler = ps2esdi_geometry_int_handler;
+-	cmd_blk[0] = CMD_GET_DEV_CONFIG | 0x600;
+-	cmd_blk[1] = 0;
+-	no_int_yet = TRUE;
+-	ps2esdi_out_cmd_blk(cmd_blk);
+-	if (no_int_yet)
+-		sleep_on(&ps2esdi_int);
+-
+-	if (ps2esdi_drives > 1) {
+-		printk("%s: Drive 1\n", DEVICE_NAME);	/*BA */
+-		cmd_blk[0] = CMD_GET_DEV_CONFIG | (1 << 5) | 0x600;
+-		cmd_blk[1] = 0;
+-		no_int_yet = TRUE;
+-		ps2esdi_out_cmd_blk(cmd_blk);
+-		if (no_int_yet)
+-			sleep_on(&ps2esdi_int);
+-	}			/* if second physical drive is present */
+-	return;
+-}
+-
+-/* strategy routine that handles most of the IO requests */
+-static void do_ps2esdi_request(struct request_queue * q)
+-{
+-	struct request *req;
+-	/* since, this routine is called with interrupts cleared - they 
+-	   must be before it finishes  */
+-
+-	req = elv_next_request(q);
+-	if (!req)
+-		return;
+-
+-#if 0
+-	printk("%s:got request. device : %s command : %d  sector : %ld count : %ld, buffer: %p\n",
+-	       DEVICE_NAME,
+-	       req->rq_disk->disk_name,
+-	       req->cmd, req->sector,
+-	       req->current_nr_sectors, req->buffer);
+-#endif
+-
+-	/* check for above 16Mb dmas */
+-	if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) {
+-		printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
+-		end_request(req, FAIL);
+-		return;
+-	}
+-
+-	if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) {
+-		printk("Grrr. error. ps2esdi_drives: %d, %llu %llu\n",
+-		    ps2esdi_drives, req->sector,
+-		    (unsigned long long)get_capacity(req->rq_disk));
+-		end_request(req, FAIL);
+-		return;
+-	}
+-
+-	switch (rq_data_dir(req)) {
+-	case READ:
+-		ps2esdi_readwrite(READ, req);
+-		break;
+-	case WRITE:
+-		ps2esdi_readwrite(WRITE, req);
+-		break;
+-	default:
+-		printk("%s: Unknown command\n", req->rq_disk->disk_name);
+-		end_request(req, FAIL);
+-		break;
+-	}		/* handle different commands */
+-}				/* main strategy routine */
+-
+-/* resets the ESDI adapter */
+-static void reset_ctrl(void)
+-{
+-
+-	u_long expire;
+-	u_short status;
+-
+-	/* enable interrupts on the controller */
+-	status = inb(ESDI_INTRPT);
+-	outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);	/* to be sure we don't have
+-							   any interrupt pending... */
+-	outb_p(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-
+-	/* read the ESDI status port - if the controller is not busy,
+-	   simply do a soft reset (fast) - otherwise we'll have to do a
+-	   hard (slow) reset.  */
+-	if (!(inb_p(ESDI_STATUS) & STATUS_BUSY)) {
+-		/*BA */ printk("%s: soft reset...\n", DEVICE_NAME);
+-		outb_p(CTRL_SOFT_RESET, ESDI_ATTN);
+-	}
+-	/* soft reset */ 
+-	else {
+-		/*BA */
+-		printk("%s: hard reset...\n", DEVICE_NAME);
+-		outb_p(CTRL_HARD_RESET, ESDI_CONTROL);
+-		expire = jiffies + 2*HZ;
+-		while (time_before(jiffies, expire));
+-		outb_p(1, ESDI_CONTROL);
+-	}			/* hard reset */
+-
+-
+-}				/* reset the controller */
+-
+-/* called by the strategy routine to handle read and write requests */
+-static void ps2esdi_readwrite(int cmd, struct request *req)
+-{
+-	struct ps2esdi_i_struct *p = req->rq_disk->private_data;
+-	unsigned block = req->sector;
+-	unsigned count = req->current_nr_sectors;
+-	int drive = p - ps2esdi_info;
+-	u_short track, head, cylinder, sector;
+-	u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
+-
+-	/* do some relevant arithmatic */
+-	track = block / p->sect;
+-	head = track % p->head;
+-	cylinder = track / p->head;
+-	sector = block % p->sect;
+-
+-#if 0
+-	printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
+-#endif
+-	/* call the routine that actually fills out a command block */
+-	ps2esdi_fill_cmd_block
+-	    (cmd_blk,
+-	     (cmd == READ) ? CMD_READ : CMD_WRITE,
+-	     cylinder, head, sector, count, drive);
+-
+-	/* send the command block to the controller */
+-	current_req = req;
+-	spin_unlock_irq(&ps2esdi_lock);
+-	if (ps2esdi_out_cmd_blk(cmd_blk)) {
+-		spin_lock_irq(&ps2esdi_lock);
+-		printk("%s: Controller failed\n", DEVICE_NAME);
+-		if ((++req->errors) >= MAX_RETRIES)
+-			end_request(req, FAIL);
+-	}
+-	/* check for failure to put out the command block */ 
+-	else {
+-		spin_lock_irq(&ps2esdi_lock);
+-#if 0
+-		printk("%s: waiting for xfer\n", DEVICE_NAME);
+-#endif
+-		/* turn disk lights on */
+-		LITE_ON;
+-	}
+-
+-}				/* ps2esdi_readwrite */
+-
+-/* fill out the command block */
+-static void ps2esdi_fill_cmd_block(u_short * cmd_blk, u_short cmd,
+- u_short cyl, u_short head, u_short sector, u_short length, u_char drive)
+-{
+-
+-	cmd_blk[0] = (drive << 5) | cmd;
+-	cmd_blk[1] = length;
+-	cmd_blk[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
+-	cmd_blk[3] = (cyl & 0x3E0) >> 5;
+-
+-}				/* fill out the command block */
+-
+-/* write a command block to the controller */
+-static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
+-{
+-
+-	int i;
+-	unsigned long jif;
+-	u_char status;
+-
+-	/* enable interrupts */
+-	outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-
+-	/* do not write to the controller, if it is busy */
+-	for (jif = jiffies + ESDI_STAT_TIMEOUT;
+-		time_after(jif, jiffies) &&
+-			(inb(ESDI_STATUS) & STATUS_BUSY); )
+-		;
+-
+-#if 0
+-	printk("%s: i(1)=%ld\n", DEVICE_NAME, jif);
+-#endif
+-
+-	/* if device is still busy - then just time out */
+-	if (inb(ESDI_STATUS) & STATUS_BUSY) {
+-		printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME);
+-		return ERROR;
+-	}			/* timeout ??? */
+-	/* Set up the attention register in the controller */
+-	outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN);
+-
+-#if 0
+-	printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1);
+-#endif
+-
+-	/* one by one send each word out */
+-	for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) {
+-		status = inb(ESDI_STATUS);
+-		for (jif = jiffies + ESDI_STAT_TIMEOUT;
+-		     time_after(jif, jiffies) && (status & STATUS_BUSY) &&
+-		   (status & STATUS_CMD_INF); status = inb(ESDI_STATUS));
+-		if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) {
+-#if 0
+-			printk("%s: sending %04X\n", DEVICE_NAME, *cmd_blk);
+-#endif
+-			outw(*cmd_blk++, ESDI_CMD_INT);
+-		} else {
+-			printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n",
+-			       DEVICE_NAME, status);
+-			return ERROR;
+-		}
+-	}			/* send all words out */
+-	return OK;
+-}				/* send out the commands */
+-
+-
+-/* prepare for dma - do all the necessary setup */
+-static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
+-{
+-	unsigned long flags = claim_dma_lock();
+-
+-	mca_disable_dma(dma_arb_level);
+-
+-	mca_set_dma_addr(dma_arb_level, isa_virt_to_bus(buffer));
+-
+-	mca_set_dma_count(dma_arb_level, length * 512 / 2);
+-
+-	mca_set_dma_mode(dma_arb_level, dma_xmode);
+-
+-	mca_enable_dma(dma_arb_level);
+-
+-	release_dma_lock(flags);
+-
+-}				/* prepare for dma */
+-
+-
+-
+-static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id)
+-{
+-	u_int int_ret_code;
+-
+-	if (inb(ESDI_STATUS) & STATUS_INTR) {
+-		int_ret_code = inb(ESDI_INTRPT);
+-		if (current_int_handler) {
+-			/* Disable adapter interrupts till processing is finished */
+-			outb(CTRL_DISABLE_INTR, ESDI_CONTROL);
+-			current_int_handler(int_ret_code);
+-		} else
+-			printk("%s: help ! No interrupt handler.\n", DEVICE_NAME);
+-	} else {
+-		return IRQ_NONE;
+-	}
+-	return IRQ_HANDLED;
+-}
+-
+-static void ps2esdi_initial_reset_int_handler(u_int int_ret_code)
+-{
+-
+-	switch (int_ret_code & 0xf) {
+-	case INT_RESET:
+-		/*BA */
+-		printk("%s: initial reset completed.\n", DEVICE_NAME);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		wake_up(&ps2esdi_int);
+-		break;
+-	case INT_ATTN_ERROR:
+-		printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
+-		       int_ret_code);
+-		printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS));
+-		break;
+-	default:
+-		printk("%s: initial reset handler received interrupt: %02X\n",
+-		       DEVICE_NAME, int_ret_code);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		break;
+-	}
+-	outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-}
+-
+-
+-static void ps2esdi_geometry_int_handler(u_int int_ret_code)
+-{
+-	u_int status, drive_num;
+-	unsigned long rba;
+-	int i;
+-
+-	drive_num = int_ret_code >> 5;
+-	switch (int_ret_code & 0xf) {
+-	case INT_CMD_COMPLETE:
+-		for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
+-		if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
+-			printk("%s: timeout reading status word\n", DEVICE_NAME);
+-			outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-			break;
+-		}
+-		status = inw(ESDI_STT_INT);
+-		if ((status & 0x1F) == CMD_GET_DEV_CONFIG) {
+-#define REPLY_WORDS 5		/* we already read word 0 */
+-			u_short reply[REPLY_WORDS];
+-
+-			if (ps2esdi_read_status_words((status >> 8) - 1, REPLY_WORDS, reply)) {
+-				/*BA */
+-				printk("%s: Device Configuration Status for drive %u\n",
+-				       DEVICE_NAME, drive_num);
+-
+-				printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8);
+-
+-				printk
+-				    ("Config bits: %s%s%s%s%s\n",
+-				     (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "",
+-				     ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS))
+-				 ? "Zero Defect, " : "Defects Present, ",
+-				     (reply[0] & CONFIG_SF) ? "Skewed Format, " : "",
+-				     (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ",
+-				     (reply[0] & CONFIG_RT) ? "No Retries" : "Retries");
+-
+-				rba = reply[1] | ((unsigned long) reply[2] << 16);
+-				printk("%s: Number of RBA's: %lu\n", DEVICE_NAME, rba);
+-
+-				printk("%s: Physical number of cylinders: %u, Sectors/Track: %u, Heads: %u\n",
+-				       DEVICE_NAME, reply[3], reply[4] >> 8, reply[4] & 0xff);
+-
+-				if (!ps2esdi_info[drive_num].head) {
+-					ps2esdi_info[drive_num].head = 64;
+-					ps2esdi_info[drive_num].sect = 32;
+-					ps2esdi_info[drive_num].cyl = rba / (64 * 32);
+-					ps2esdi_info[drive_num].wpcom = 0;
+-					ps2esdi_info[drive_num].lzone = ps2esdi_info[drive_num].cyl;
+-					ps2esdi_info[drive_num].ctl = 8;
+-					if (tp720esdi) {	/* store the retrieved parameters */
+-						ps2esdi_info[0].head = reply[4] & 0Xff;
+-						ps2esdi_info[0].sect = reply[4] >> 8;
+-						ps2esdi_info[0].cyl = reply[3];
+-						ps2esdi_info[0].wpcom = 0;
+-						ps2esdi_info[0].lzone = reply[3];
+-					} else {
+-						if (!intg_esdi)
+-							ps2esdi_drives++;
+-					}
+-				}
+-#ifdef OBSOLETE
+-				if (!ps2esdi_info[drive_num].head) {
+-					ps2esdi_info[drive_num].head = reply[4] & 0Xff;
+-					ps2esdi_info[drive_num].sect = reply[4] >> 8;
+-					ps2esdi_info[drive_num].cyl = reply[3];
+-					ps2esdi_info[drive_num].wpcom = 0;
+-					ps2esdi_info[drive_num].lzone = reply[3];
+-					if (tp720esdi) {	/* store the retrieved parameters */
+-						ps2esdi_info[0].head = reply[4] & 0Xff;
+-						ps2esdi_info[0].sect = reply[4] >> 8;
+-						ps2esdi_info[0].cyl = reply[3];
+-						ps2esdi_info[0].wpcom = 0;
+-						ps2esdi_info[0].lzone = reply[3];
+-					} else {
+-						ps2esdi_drives++;
+-					}
+-				}
+-#endif
+-
+-			} else
+-				printk("%s: failed while getting device config\n", DEVICE_NAME);
+-#undef REPLY_WORDS
+-		} else
+-			printk("%s: command %02X unknown by geometry handler\n",
+-			       DEVICE_NAME, status & 0x1f);
+-
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		break;
+-
+-	case INT_ATTN_ERROR:
+-		printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
+-		       int_ret_code);
+-		printk("%s: Device not available\n", DEVICE_NAME);
+-		break;
+-	case INT_CMD_ECC:
+-	case INT_CMD_RETRY:
+-	case INT_CMD_ECC_RETRY:
+-	case INT_CMD_WARNING:
+-	case INT_CMD_ABORT:
+-	case INT_CMD_FAILED:
+-	case INT_DMA_ERR:
+-	case INT_CMD_BLK_ERR:
+-		/*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME);
+-		dump_cmd_complete_status(int_ret_code);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		break;
+-	default:
+-		printk("%s: Unknown interrupt reason: %02X\n",
+-		       DEVICE_NAME, int_ret_code & 0xf);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		break;
+-	}
+-
+-	wake_up(&ps2esdi_int);
+-	no_int_yet = FALSE;
+-	outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-
+-}
+-
+-static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
+-{
+-	unsigned long flags;
+-	u_int status;
+-	u_int ending;
+-	int i;
+-
+-	switch (int_ret_code & 0x0f) {
+-	case INT_TRANSFER_REQ:
+-		ps2esdi_prep_dma(current_req->buffer,
+-				 current_req->current_nr_sectors,
+-		    (rq_data_dir(current_req) == READ)
+-		    ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
+-		    : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
+-		outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = -1;
+-		break;
+-
+-	case INT_ATTN_ERROR:
+-		printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
+-		       int_ret_code);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = FAIL;
+-		break;
+-
+-	case INT_CMD_COMPLETE:
+-		for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
+-		if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
+-			printk("%s: timeout reading status word\n", DEVICE_NAME);
+-			outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-			outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-			if ((++current_req->errors) >= MAX_RETRIES)
+-				ending = FAIL;
+-			else
+-				ending = -1;
+-			break;
+-		}
+-		status = inw(ESDI_STT_INT);
+-		switch (status & 0x1F) {
+-		case (CMD_READ & 0xff):
+-		case (CMD_WRITE & 0xff):
+-			LITE_OFF;
+-			outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-			outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-			ending = SUCCES;
+-			break;
+-		default:
+-			printk("%s: interrupt for unknown command %02X\n",
+-			       DEVICE_NAME, status & 0x1f);
+-			outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-			outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-			ending = -1;
+-			break;
+-		}
+-		break;
+-	case INT_CMD_ECC:
+-	case INT_CMD_RETRY:
+-	case INT_CMD_ECC_RETRY:
+-		LITE_OFF;
+-		dump_cmd_complete_status(int_ret_code);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = SUCCES;
+-		break;
+-	case INT_CMD_WARNING:
+-	case INT_CMD_ABORT:
+-	case INT_CMD_FAILED:
+-	case INT_DMA_ERR:
+-		LITE_OFF;
+-		dump_cmd_complete_status(int_ret_code);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		if ((++current_req->errors) >= MAX_RETRIES)
+-			ending = FAIL;
+-		else
+-			ending = -1;
+-		break;
+-
+-	case INT_CMD_BLK_ERR:
+-		dump_cmd_complete_status(int_ret_code);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = FAIL;
+-		break;
+-
+-	case INT_CMD_FORMAT:
+-		printk("%s: huh ? Who issued this format command ?\n"
+-		       ,DEVICE_NAME);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = -1;
+-		break;
+-
+-	case INT_RESET:
+-		/* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ;
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = -1;
+-		break;
+-
+-	default:
+-		printk("%s: Unknown interrupt reason: %02X\n",
+-		       DEVICE_NAME, int_ret_code & 0xf);
+-		outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		ending = -1;
+-		break;
+-	}
+-	if(ending != -1) {
+-		spin_lock_irqsave(&ps2esdi_lock, flags);
+-		end_request(current_req, ending);
+-		current_req = NULL;
+-		do_ps2esdi_request(ps2esdi_queue);
+-		spin_unlock_irqrestore(&ps2esdi_lock, flags);
+-	}
+-}				/* handle interrupts */
+-
+-
+-
+-static int ps2esdi_read_status_words(int num_words,
+-				     int max_words,
+-				     u_short * buffer)
+-{
+-	int i;
+-
+-	for (; max_words && num_words; max_words--, num_words--, buffer++) {
+-		for (i = ESDI_TIMEOUT; i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--);
+-		if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) {
+-			printk("%s: timeout reading status word\n", DEVICE_NAME);
+-			return FAIL;
+-		}
+-		*buffer = inw(ESDI_STT_INT);
+-	}
+-	return SUCCES;
+-}
+-
+-
+-
+-
+-static void dump_cmd_complete_status(u_int int_ret_code)
+-{
+-#define WAIT_FOR_STATUS \
+-  for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \
+-    if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \
+-    printk("%s: timeout reading status word\n",DEVICE_NAME); \
+-    return; \
+-    }
+-
+-	int i, word_count;
+-	u_short stat_word;
+-	u_long rba;
+-
+-	printk("%s: Device: %u, interrupt ID: %02X\n",
+-	       DEVICE_NAME, int_ret_code >> 5,
+-	       int_ret_code & 0xf);
+-
+-	WAIT_FOR_STATUS;
+-	stat_word = inw(ESDI_STT_INT);
+-	word_count = (stat_word >> 8) - 1;
+-	printk("%s: %u status words, command: %02X\n", DEVICE_NAME, word_count,
+-	       stat_word & 0xff);
+-
+-	if (word_count--) {
+-		WAIT_FOR_STATUS;
+-		stat_word = inw(ESDI_STT_INT);
+-		printk("%s: command status code: %02X, command error code: %02X\n",
+-		       DEVICE_NAME, stat_word >> 8, stat_word & 0xff);
+-	}
+-	if (word_count--) {
+-		WAIT_FOR_STATUS;
+-		stat_word = inw(ESDI_STT_INT);
+-		printk("%s: device error code: %s%s%s%s%s,%02X\n", DEVICE_NAME,
+-		       (stat_word & 0x1000) ? "Ready, " : "Not Ready, ",
+-		  (stat_word & 0x0800) ? "Selected, " : "Not Selected, ",
+-		       (stat_word & 0x0400) ? "Write Fault, " : "",
+-		       (stat_word & 0x0200) ? "Track 0, " : "",
+-		(stat_word & 0x0100) ? "Seek or command complete, " : "",
+-		       stat_word >> 8);
+-	}
+-	if (word_count--) {
+-		WAIT_FOR_STATUS;
+-		stat_word = inw(ESDI_STT_INT);
+-		printk("%s: Blocks to do: %u", DEVICE_NAME, stat_word);
+-	}
+-	if (word_count -= 2) {
+-		WAIT_FOR_STATUS;
+-		rba = inw(ESDI_STT_INT);
+-		WAIT_FOR_STATUS;
+-		rba |= inw(ESDI_STT_INT) << 16;
+-		printk(", Last Cyl: %u Head: %u Sector: %u\n",
+-		       (u_short) ((rba & 0x1ff80000) >> 11),
+-		 (u_short) ((rba & 0x7E0) >> 5), (u_short) (rba & 0x1f));
+-	} else
+-		printk("\n");
+-
+-	if (word_count--) {
+-		WAIT_FOR_STATUS;
+-		stat_word = inw(ESDI_STT_INT);
+-		printk("%s: Blocks required ECC: %u", DEVICE_NAME, stat_word);
+-	}
+-	printk("\n");
+-
+-#undef WAIT_FOR_STATUS
+-
+-}
+-
+-static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+-{
+-	struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
+-
+-	geo->heads = p->head;
+-	geo->sectors = p->sect;
+-	geo->cylinders = p->cyl;
+-	return 0;
+-}
+-
+-static void ps2esdi_reset_timer(unsigned long unused)
+-{
+-
+-	int status;
+-
+-	status = inb(ESDI_INTRPT);
+-	if ((status & 0xf) == INT_RESET) {
+-		outb((status & 0xe0) | ATT_EOI, ESDI_ATTN);
+-		outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+-		reset_status = 1;
+-	}
+-	wake_up(&ps2esdi_int);
+-}
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index 3b1a68d..0cfbe8c 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -238,6 +238,7 @@ static int virtblk_probe(struct virtio_device *vdev)
+ 	vblk->disk->first_minor = index_to_minor(index);
+ 	vblk->disk->private_data = vblk;
+ 	vblk->disk->fops = &virtblk_fops;
++	vblk->disk->driverfs_dev = &vdev->dev;
+ 	index++;
+ 
+ 	/* If barriers are supported, tell block layer that queue is ordered */
+diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
+index d352dbb..e5a0e97 100644
+--- a/drivers/char/drm/ati_pcigart.c
++++ b/drivers/char/drm/ati_pcigart.c
+@@ -35,42 +35,23 @@
+ 
+ # define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
+ 
+-static void *drm_ati_alloc_pcigart_table(int order)
++static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
++				       struct drm_ati_pcigart_info *gart_info)
+ {
+-	unsigned long address;
+-	struct page *page;
+-	int i;
+-
+-	DRM_DEBUG("%d order\n", order);
+-
+-	address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
+-				   order);
+-	if (address == 0UL) {
+-		return NULL;
+-	}
+-
+-	page = virt_to_page(address);
++	gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
++						PAGE_SIZE,
++						gart_info->table_mask);
++	if (gart_info->table_handle == NULL)
++		return -ENOMEM;
+ 
+-	for (i = 0; i < order; i++, page++)
+-		SetPageReserved(page);
+-
+-	DRM_DEBUG("returning 0x%08lx\n", address);
+-	return (void *)address;
++	return 0;
+ }
+ 
+-static void drm_ati_free_pcigart_table(void *address, int order)
++static void drm_ati_free_pcigart_table(struct drm_device *dev,
++				       struct drm_ati_pcigart_info *gart_info)
+ {
+-	struct page *page;
+-	int i;
+-	int num_pages = 1 << order;
+-	DRM_DEBUG("\n");
+-
+-	page = virt_to_page((unsigned long)address);
+-
+-	for (i = 0; i < num_pages; i++, page++)
+-		ClearPageReserved(page);
+-
+-	free_pages((unsigned long)address, order);
++	drm_pci_free(dev, gart_info->table_handle);
++	gart_info->table_handle = NULL;
+ }
+ 
+ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
+@@ -78,8 +59,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
+ 	struct drm_sg_mem *entry = dev->sg;
+ 	unsigned long pages;
+ 	int i;
+-	int order;
+-	int num_pages, max_pages;
++	int max_pages;
+ 
+ 	/* we need to support large memory configurations */
+ 	if (!entry) {
+@@ -87,15 +67,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
+ 		return 0;
+ 	}
+ 
+-	order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE);
+-	num_pages = 1 << order;
+-
+ 	if (gart_info->bus_addr) {
+-		if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+-			pci_unmap_single(dev->pdev, gart_info->bus_addr,
+-					 num_pages * PAGE_SIZE,
+-					 PCI_DMA_TODEVICE);
+-		}
+ 
+ 		max_pages = (gart_info->table_size / sizeof(u32));
+ 		pages = (entry->pages <= max_pages)
+@@ -112,10 +84,9 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
+ 			gart_info->bus_addr = 0;
+ 	}
+ 
+-	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
+-	    && gart_info->addr) {
+-		drm_ati_free_pcigart_table(gart_info->addr, order);
+-		gart_info->addr = NULL;
++	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
++	    gart_info->table_handle) {
++		drm_ati_free_pcigart_table(dev, gart_info);
+ 	}
+ 
+ 	return 1;
+@@ -127,11 +98,10 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
+ 	struct drm_sg_mem *entry = dev->sg;
+ 	void *address = NULL;
+ 	unsigned long pages;
+-	u32 *pci_gart, page_base, bus_address = 0;
++	u32 *pci_gart, page_base;
++	dma_addr_t bus_address = 0;
+ 	int i, j, ret = 0;
+-	int order;
+ 	int max_pages;
+-	int num_pages;
+ 
+ 	if (!entry) {
+ 		DRM_ERROR("no scatter/gather memory!\n");
+@@ -141,31 +111,14 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
+ 	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+ 		DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
+ 
+-		order = drm_order((gart_info->table_size +
+-				   (PAGE_SIZE-1)) / PAGE_SIZE);
+-		num_pages = 1 << order;
+-		address = drm_ati_alloc_pcigart_table(order);
+-		if (!address) {
++		ret = drm_ati_alloc_pcigart_table(dev, gart_info);
++		if (ret) {
+ 			DRM_ERROR("cannot allocate PCI GART page!\n");
+ 			goto done;
+ 		}
+ 
+-		if (!dev->pdev) {
+-			DRM_ERROR("PCI device unknown!\n");
+-			goto done;
+-		}
+-
+-		bus_address = pci_map_single(dev->pdev, address,
+-					     num_pages * PAGE_SIZE,
+-					     PCI_DMA_TODEVICE);
+-		if (bus_address == 0) {
+-			DRM_ERROR("unable to map PCIGART pages!\n");
+-			order = drm_order((gart_info->table_size +
+-					   (PAGE_SIZE-1)) / PAGE_SIZE);
+-			drm_ati_free_pcigart_table(address, order);
+-			address = NULL;
+-			goto done;
+-		}
++		address = gart_info->table_handle->vaddr;
++		bus_address = gart_info->table_handle->busaddr;
+ 	} else {
+ 		address = gart_info->addr;
+ 		bus_address = gart_info->bus_addr;
+diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
+index a6789f2..8ea9dd1 100644
+--- a/drivers/char/drm/drmP.h
++++ b/drivers/char/drm/drmP.h
+@@ -54,6 +54,7 @@
+ #include <linux/pci.h>
+ #include <linux/jiffies.h>
+ #include <linux/smp_lock.h>	/* For (un)lock_kernel */
++#include <linux/dma-mapping.h>
+ #include <linux/mm.h>
+ #include <linux/cdev.h>
+ #include <linux/mutex.h>
+@@ -551,6 +552,8 @@ struct drm_ati_pcigart_info {
+ 	int gart_reg_if;
+ 	void *addr;
+ 	dma_addr_t bus_addr;
++	dma_addr_t table_mask;
++	struct drm_dma_handle *table_handle;
+ 	drm_local_map_t mapping;
+ 	int table_size;
+ };
+diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
+index 3992f73..f09d4b5 100644
+--- a/drivers/char/drm/drm_fops.c
++++ b/drivers/char/drm/drm_fops.c
+@@ -326,6 +326,7 @@ int drm_release(struct inode *inode, struct file *filp)
+ 	struct drm_file *file_priv = filp->private_data;
+ 	struct drm_device *dev = file_priv->head->dev;
+ 	int retcode = 0;
++	unsigned long irqflags;
+ 
+ 	lock_kernel();
+ 
+@@ -357,9 +358,11 @@ int drm_release(struct inode *inode, struct file *filp)
+ 			 */
+ 
+ 			do{
+-				spin_lock(&dev->lock.spinlock);
++				spin_lock_irqsave(&dev->lock.spinlock,
++						  irqflags);
+ 				locked = dev->lock.idle_has_lock;
+-				spin_unlock(&dev->lock.spinlock);
++				spin_unlock_irqrestore(&dev->lock.spinlock,
++						       irqflags);
+ 				if (locked)
+ 					break;
+ 				schedule();
+diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
+index bea2a7d..12dcdd1 100644
+--- a/drivers/char/drm/drm_lock.c
++++ b/drivers/char/drm/drm_lock.c
+@@ -53,6 +53,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
+ 	DECLARE_WAITQUEUE(entry, current);
+ 	struct drm_lock *lock = data;
+ 	int ret = 0;
++	unsigned long irqflags;
+ 
+ 	++file_priv->lock_count;
+ 
+@@ -71,9 +72,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
+ 			return -EINVAL;
+ 
+ 	add_wait_queue(&dev->lock.lock_queue, &entry);
+-	spin_lock(&dev->lock.spinlock);
++	spin_lock_irqsave(&dev->lock.spinlock, irqflags);
+ 	dev->lock.user_waiters++;
+-	spin_unlock(&dev->lock.spinlock);
++	spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
+ 	for (;;) {
+ 		__set_current_state(TASK_INTERRUPTIBLE);
+ 		if (!dev->lock.hw_lock) {
+@@ -95,9 +96,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
+ 			break;
+ 		}
+ 	}
+-	spin_lock(&dev->lock.spinlock);
++	spin_lock_irqsave(&dev->lock.spinlock, irqflags);
+ 	dev->lock.user_waiters--;
+-	spin_unlock(&dev->lock.spinlock);
++	spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
+ 	__set_current_state(TASK_RUNNING);
+ 	remove_wait_queue(&dev->lock.lock_queue, &entry);
+ 
+@@ -198,8 +199,9 @@ int drm_lock_take(struct drm_lock_data *lock_data,
+ {
+ 	unsigned int old, new, prev;
+ 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
++	unsigned long irqflags;
+ 
+-	spin_lock(&lock_data->spinlock);
++	spin_lock_irqsave(&lock_data->spinlock, irqflags);
+ 	do {
+ 		old = *lock;
+ 		if (old & _DRM_LOCK_HELD)
+@@ -211,7 +213,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
+ 		}
+ 		prev = cmpxchg(lock, old, new);
+ 	} while (prev != old);
+-	spin_unlock(&lock_data->spinlock);
++	spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
+ 
+ 	if (_DRM_LOCKING_CONTEXT(old) == context) {
+ 		if (old & _DRM_LOCK_HELD) {
+@@ -272,15 +274,16 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
+ {
+ 	unsigned int old, new, prev;
+ 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
++	unsigned long irqflags;
+ 
+-	spin_lock(&lock_data->spinlock);
++	spin_lock_irqsave(&lock_data->spinlock, irqflags);
+ 	if (lock_data->kernel_waiters != 0) {
+ 		drm_lock_transfer(lock_data, 0);
+ 		lock_data->idle_has_lock = 1;
+-		spin_unlock(&lock_data->spinlock);
++		spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
+ 		return 1;
+ 	}
+-	spin_unlock(&lock_data->spinlock);
++	spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
+ 
+ 	do {
+ 		old = *lock;
+@@ -344,19 +347,20 @@ static int drm_notifier(void *priv)
+ void drm_idlelock_take(struct drm_lock_data *lock_data)
+ {
+ 	int ret = 0;
++	unsigned long irqflags;
+ 
+-	spin_lock(&lock_data->spinlock);
++	spin_lock_irqsave(&lock_data->spinlock, irqflags);
+ 	lock_data->kernel_waiters++;
+ 	if (!lock_data->idle_has_lock) {
+ 
+-		spin_unlock(&lock_data->spinlock);
++		spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
+ 		ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
+-		spin_lock(&lock_data->spinlock);
++		spin_lock_irqsave(&lock_data->spinlock, irqflags);
+ 
+ 		if (ret == 1)
+ 			lock_data->idle_has_lock = 1;
+ 	}
+-	spin_unlock(&lock_data->spinlock);
++	spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
+ }
+ EXPORT_SYMBOL(drm_idlelock_take);
+ 
+@@ -364,8 +368,9 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
+ {
+ 	unsigned int old, prev;
+ 	volatile unsigned int *lock = &lock_data->hw_lock->lock;
++	unsigned long irqflags;
+ 
+-	spin_lock(&lock_data->spinlock);
++	spin_lock_irqsave(&lock_data->spinlock, irqflags);
+ 	if (--lock_data->kernel_waiters == 0) {
+ 		if (lock_data->idle_has_lock) {
+ 			do {
+@@ -376,7 +381,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
+ 			lock_data->idle_has_lock = 0;
+ 		}
+ 	}
+-	spin_unlock(&lock_data->spinlock);
++	spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
+ }
+ EXPORT_SYMBOL(drm_idlelock_release);
+ 
+diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
+index 715b361..a6a499f 100644
+--- a/drivers/char/drm/drm_pciids.h
++++ b/drivers/char/drm/drm_pciids.h
+@@ -205,9 +205,9 @@
+ 	{0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+-	{0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+-	{0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+-	{0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
++	{0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
++	{0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
++	{0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+@@ -238,6 +238,7 @@
+ 	{0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ 	{0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
++	{0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+ 	{0, 0, 0}
+ 
+ #define r128_PCI_IDS \
+diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
+index 892e0a5..f36adbd 100644
+--- a/drivers/char/drm/r128_cce.c
++++ b/drivers/char/drm/r128_cce.c
+@@ -558,6 +558,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
+ #if __OS_HAS_AGP
+ 	if (dev_priv->is_pci) {
+ #endif
++		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
+ 		dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
+ 		dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
+ 		dev_priv->gart_info.addr = NULL;
+diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
+index 833abc7..9072e4a 100644
+--- a/drivers/char/drm/radeon_cp.c
++++ b/drivers/char/drm/radeon_cp.c
+@@ -1807,6 +1807,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 	} else
+ #endif
+ 	{
++		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
+ 		/* if we have an offset set from userspace */
+ 		if (dev_priv->pcigart_offset_set) {
+ 			dev_priv->gart_info.bus_addr =
+diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
+index 94baec6..7a339db 100644
+--- a/drivers/char/drm/via_dma.c
++++ b/drivers/char/drm/via_dma.c
+@@ -126,6 +126,8 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
+ 			     hw_addr, cur_addr, next_addr);
+ 			return -1;
+ 		}
++		if  ((cur_addr < hw_addr) && (next_addr >= hw_addr))
++			msleep(1);
+ 	} while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
+ 	return 0;
+ }
+@@ -416,27 +418,50 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
+ 	int paused, count;
+ 	volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+ 	uint32_t reader,ptr;
++	uint32_t diff;
+ 
+ 	paused = 0;
+ 	via_flush_write_combine();
+ 	(void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
++
+ 	*paused_at = pause_addr_lo;
+ 	via_flush_write_combine();
+ 	(void) *paused_at;
++
+ 	reader = *(dev_priv->hw_addr_ptr);
+ 	ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
+ 		dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
++
+ 	dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+ 
+-	if ((ptr - reader) <= dev_priv->dma_diff ) {
+-		count = 10000000;
+-		while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
++	/*
++	 * If there is a possibility that the command reader will 
++	 * miss the new pause address and pause on the old one,
++	 * In that case we need to program the new start address
++	 * using PCI.
++	 */
++
++	diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
++	count = 10000000;
++	while(diff == 0 && count--) {
++		paused = (VIA_READ(0x41c) & 0x80000000);
++		if (paused) 
++			break;
++		reader = *(dev_priv->hw_addr_ptr);
++		diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+ 	}
+ 
++	paused = VIA_READ(0x41c) & 0x80000000;
++
+ 	if (paused && !no_pci_fire) {
+ 		reader = *(dev_priv->hw_addr_ptr);
+-		if ((ptr - reader) == dev_priv->dma_diff) {
+-
++		diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
++		diff &= (dev_priv->dma_high - 1);
++		if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
++			DRM_ERROR("Paused at incorrect address. "
++				  "0x%08x, 0x%08x 0x%08x\n",
++				  ptr, reader, dev_priv->dma_diff);
++		} else if (diff == 0) {
+ 			/*
+ 			 * There is a concern that these writes may stall the PCI bus
+ 			 * if the GPU is not idle. However, idling the GPU first
+@@ -577,6 +602,7 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
+ 	uint32_t pause_addr_lo, pause_addr_hi;
+ 	uint32_t jump_addr_lo, jump_addr_hi;
+ 	volatile uint32_t *last_pause_ptr;
++	uint32_t dma_low_save1, dma_low_save2;
+ 
+ 	agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+ 	via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
+@@ -603,8 +629,29 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
+ 		      &pause_addr_lo, 0);
+ 
+ 	*last_pause_ptr = pause_addr_lo;
++	dma_low_save1 = dev_priv->dma_low;
+ 
+-	via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
++	/*
++	 * Now, set a trap that will pause the regulator if it tries to rerun the old
++	 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
++	 * and reissues the jump command over PCI, while the regulator has already taken the jump
++	 * and actually paused at the current buffer end).
++	 * There appears to be no other way to detect this condition, since the hw_addr_pointer
++	 * does not seem to get updated immediately when a jump occurs.
++	 */
++
++	last_pause_ptr =
++		via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
++			      &pause_addr_lo, 0) - 1;
++	via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
++		      &pause_addr_lo, 0);
++	*last_pause_ptr = pause_addr_lo;
++
++	dma_low_save2 = dev_priv->dma_low;
++	dev_priv->dma_low = dma_low_save1;
++	via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
++	dev_priv->dma_low = dma_low_save2;
++	via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+ }
+ 
+ 
+diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
+index 33c5197..409e00a 100644
+--- a/drivers/char/drm/via_dmablit.c
++++ b/drivers/char/drm/via_dmablit.c
+@@ -603,7 +603,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli
+ 	 * (Not a big limitation anyway.)
+ 	 */
+ 
+-	if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) {
++	if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) {
+ 		DRM_ERROR("Too large system memory stride. Stride: %d, "
+ 			  "Length: %d\n", xfer->mem_stride, xfer->line_length);
+ 		return -EINVAL;
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index ad2f938..7269230 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -123,6 +123,11 @@ static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan)
+ 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
+ }
+ 
++static u32 get_bcr(struct fsl_dma_chan *fsl_chan)
++{
++	return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
++}
++
+ static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
+ {
+ 	u32 sr = get_sr(fsl_chan);
+@@ -426,6 +431,9 @@ fsl_dma_prep_interrupt(struct dma_chan *chan)
+ 	new->async_tx.cookie = -EBUSY;
+ 	new->async_tx.ack = 0;
+ 
++	/* Insert the link descriptor to the LD ring */
++	list_add_tail(&new->node, &new->async_tx.tx_list);
++
+ 	/* Set End-of-link to the last link descriptor of new list*/
+ 	set_ld_eol(fsl_chan, new);
+ 
+@@ -701,6 +709,23 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ 	if (stat & FSL_DMA_SR_TE)
+ 		dev_err(fsl_chan->dev, "Transfer Error!\n");
+ 
++	/* Programming Error
++	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
++	 * triger a PE interrupt.
++	 */
++	if (stat & FSL_DMA_SR_PE) {
++		dev_dbg(fsl_chan->dev, "event: Programming Error INT\n");
++		if (get_bcr(fsl_chan) == 0) {
++			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
++			 * Now, update the completed cookie, and continue the
++			 * next uncompleted transfer.
++			 */
++			fsl_dma_update_completed_cookie(fsl_chan);
++			fsl_chan_xfer_ld_queue(fsl_chan);
++		}
++		stat &= ~FSL_DMA_SR_PE;
++	}
++
+ 	/* If the link descriptor segment transfer finishes,
+ 	 * we will recycle the used descriptor.
+ 	 */
+@@ -841,6 +866,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ 	tx3 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0);
+ 	async_tx_ack(tx3);
+ 
++	/* Interrupt tx test */
++	tx1 = fsl_dma_prep_interrupt(chan);
++	async_tx_ack(tx1);
++	cookie = fsl_dma_tx_submit(tx1);
++
+ 	/* Test exchanging the prepared tx sort */
+ 	cookie = fsl_dma_tx_submit(tx3);
+ 	cookie = fsl_dma_tx_submit(tx2);
+diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
+index ba78c42..fddd6ae 100644
+--- a/drivers/dma/fsldma.h
++++ b/drivers/dma/fsldma.h
+@@ -40,6 +40,7 @@
+ #define FSL_DMA_MR_EOTIE	0x00000080
+ 
+ #define FSL_DMA_SR_CH		0x00000020
++#define FSL_DMA_SR_PE		0x00000010
+ #define FSL_DMA_SR_CB		0x00000004
+ #define FSL_DMA_SR_TE		0x00000080
+ #define FSL_DMA_SR_EOSI		0x00000002
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index d73a768..f0b00ec 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -968,7 +968,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
+ 		size--;
+ 	}
+ 
+-	/* dump the report descriptor */
++	/* dump the report */
+ 	dbg_hid("report %d (size %u) = ", n, size);
+ 	for (i = 0; i < size; i++)
+ 		dbg_hid_line(" %02x", data[i]);
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index 5a38fb2..c3eb3f1 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -98,18 +98,16 @@ struct hidinput_key_translation {
+ 
+ static struct hidinput_key_translation apple_fn_keys[] = {
+ 	{ KEY_BACKSPACE, KEY_DELETE },
+-	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
+-	{ KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
+-	{ KEY_F3,       KEY_CYCLEWINDOWS,       APPLE_FLAG_FKEY }, /* Exposé */
+-	{ KEY_F4,       KEY_FN_F4,              APPLE_FLAG_FKEY }, /* Dashboard */
+-	{ KEY_F5,       KEY_FN_F5 },
+-	{ KEY_F6,       KEY_FN_F6 },
+-	{ KEY_F7,       KEY_BACK,               APPLE_FLAG_FKEY },
+-	{ KEY_F8,       KEY_PLAYPAUSE,          APPLE_FLAG_FKEY },
+-	{ KEY_F9,       KEY_FORWARD,            APPLE_FLAG_FKEY },
+-	{ KEY_F10,      KEY_MUTE,               APPLE_FLAG_FKEY },
+-	{ KEY_F11,      KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
+-	{ KEY_F12,      KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
++	{ KEY_F1,       KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
++	{ KEY_F2,       KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
++	{ KEY_F3,       KEY_FN_F5,          APPLE_FLAG_FKEY }, /* Exposé */
++	{ KEY_F4,       KEY_FN_F4,          APPLE_FLAG_FKEY }, /* Dashboard */
++	{ KEY_F7,       KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
++	{ KEY_F8,       KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
++	{ KEY_F9,       KEY_NEXTSONG,       APPLE_FLAG_FKEY },
++	{ KEY_F10,      KEY_MUTE,           APPLE_FLAG_FKEY },
++	{ KEY_F11,      KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
++	{ KEY_F12,      KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
+ 	{ KEY_UP,       KEY_PAGEUP },
+ 	{ KEY_DOWN,     KEY_PAGEDOWN },
+ 	{ KEY_LEFT,     KEY_HOME },
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index b38e559..d95979f 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -278,7 +278,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
+ 		usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
+ 		maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0);
+ 		if (maxpacket > 0) {
+-			padlen = (len + maxpacket - 1) / maxpacket;
++			padlen = DIV_ROUND_UP(len, maxpacket);
+ 			padlen *= maxpacket;
+ 			if (padlen > usbhid->bufsize)
+ 				padlen = usbhid->bufsize;
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index e6d05f6..e29a057 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -345,6 +345,9 @@
+ #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
+ #define USB_DEVICE_ID_N_S_HARMONY       0xc359
+ 
++#define USB_VENDOR_ID_NATSU             0x08b7
++#define USB_DEVICE_ID_NATSU_GAMEPAD     0x0001
++
+ #define USB_VENDOR_ID_NEC		0x073e
+ #define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
+ 
+@@ -426,6 +429,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+ 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+ 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
++	{ USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD, HID_QUIRK_BADPAD },
+ 	{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
+ 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
+ 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+@@ -624,7 +628,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_HAS_FN },
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
+index 0518a2e..4c86a8d 100644
+--- a/drivers/ide/ide-taskfile.c
++++ b/drivers/ide/ide-taskfile.c
+@@ -423,6 +423,25 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
+ }
+ 
+ /*
++ * We got an interrupt on a task_in case, but no errors and no DRQ.
++ *
++ * It might be a spurious irq (shared irq), but it might be a
++ * command that had no output.
++ */
++static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat)
++{
++	/* Command all done? */
++	if (OK_STAT(stat, READY_STAT, BUSY_STAT)) {
++		task_end_request(drive, rq, stat);
++		return ide_stopped;
++	}
++
++	/* Assume it was a spurious irq */
++	ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
++	return ide_started;
++}
++
++/*
+  * Handler for command with PIO data-in phase (Read/Read Multiple).
+  */
+ static ide_startstop_t task_in_intr(ide_drive_t *drive)
+@@ -431,18 +450,17 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
+ 	struct request *rq = HWGROUP(drive)->rq;
+ 	u8 stat = ide_read_status(drive);
+ 
+-	/* new way for dealing with premature shared PCI interrupts */
+-	if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
+-		if (stat & (ERR_STAT | DRQ_STAT))
+-			return task_error(drive, rq, __FUNCTION__, stat);
+-		/* No data yet, so wait for another IRQ. */
+-		ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
+-		return ide_started;
+-	}
++	/* Error? */
++	if (stat & ERR_STAT)
++		return task_error(drive, rq, __FUNCTION__, stat);
++
++	/* Didn't want any data? Odd. */
++	if (!(stat & DRQ_STAT))
++		return task_in_unexpected(drive, rq, stat);
+ 
+ 	ide_pio_datablock(drive, rq, 0);
+ 
+-	/* If it was the last datablock check status and finish transfer. */
++	/* Are we done? Check status and finish transfer. */
+ 	if (!hwif->nleft) {
+ 		stat = wait_drive_not_busy(drive);
+ 		if (!OK_STAT(stat, 0, BAD_STAT))
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index 4833b1a..5511ef0 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -1,7 +1,7 @@
+ /*
+  *  Cobalt button interface driver.
+  *
+- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
++ *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa at tripeaks.co.jp>
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -15,7 +15,7 @@
+  *
+  *  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-1301  USA
++ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <linux/init.h>
+ #include <linux/input-polldev.h>
+@@ -55,7 +55,7 @@ static void handle_buttons(struct input_polled_dev *dev)
+ 	status = ~readl(bdev->reg) >> 24;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
+-		if (status & (1UL << i)) {
++		if (status & (1U << i)) {
+ 			if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
+ 				input_event(input, EV_MSC, MSC_SCAN, i);
+ 				input_report_key(input, bdev->keymap[i], 1);
+@@ -97,16 +97,16 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
+ 	input->name = "Cobalt buttons";
+ 	input->phys = "cobalt/input0";
+ 	input->id.bustype = BUS_HOST;
+-	input->cdev.dev = &pdev->dev;
++	input->dev.parent = &pdev->dev;
+ 
+-	input->keycode = pdev->keymap;
+-	input->keycodemax = ARRAY_SIZE(pdev->keymap);
++	input->keycode = bdev->keymap;
++	input->keycodemax = ARRAY_SIZE(bdev->keymap);
+ 	input->keycodesize = sizeof(unsigned short);
+ 
+ 	input_set_capability(input, EV_MSC, MSC_SCAN);
+ 	__set_bit(EV_KEY, input->evbit);
+-	for (i = 0; i < ARRAY_SIZE(buttons_map); i++)
+-		__set_bit(input->keycode[i], input->keybit);
++	for (i = 0; i < ARRAY_SIZE(cobalt_map); i++)
++		__set_bit(bdev->keymap[i], input->keybit);
+ 	__clear_bit(KEY_RESERVED, input->keybit);
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
+index b346a3b..385e32b 100644
+--- a/drivers/input/mouse/alps.c
++++ b/drivers/input/mouse/alps.c
+@@ -116,8 +116,8 @@ static void alps_process_packet(struct psmouse *psmouse)
+ 	}
+ 
+ 	if (priv->i->flags & ALPS_FW_BK_1) {
+-		back = packet[2] & 4;
+-		forward = packet[0] & 0x10;
++		back = packet[0] & 0x10;
++		forward = packet[2] & 4;
+ 	}
+ 
+ 	if (priv->i->flags & ALPS_FW_BK_2) {
+@@ -483,6 +483,7 @@ int alps_init(struct psmouse *psmouse)
+ 	dev2->id.vendor  = 0x0002;
+ 	dev2->id.product = PSMOUSE_ALPS;
+ 	dev2->id.version = 0x0000;
++	dev2->dev.parent = &psmouse->ps2dev.serio->dev;
+ 
+ 	dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ 	dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+diff --git a/drivers/input/serio/i8042-snirm.h b/drivers/input/serio/i8042-snirm.h
+new file mode 100644
+index 0000000..409a934
+--- /dev/null
++++ b/drivers/input/serio/i8042-snirm.h
+@@ -0,0 +1,75 @@
++#ifndef _I8042_SNIRM_H
++#define _I8042_SNIRM_H
++
++#include <asm/sni.h>
++
++/*
++ * 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.
++ */
++
++/*
++ * Names.
++ */
++
++#define I8042_KBD_PHYS_DESC "onboard/serio0"
++#define I8042_AUX_PHYS_DESC "onboard/serio1"
++#define I8042_MUX_PHYS_DESC "onboard/serio%d"
++
++/*
++ * IRQs.
++ */
++static int i8042_kbd_irq;
++static int i8042_aux_irq;
++#define I8042_KBD_IRQ i8042_kbd_irq
++#define I8042_AUX_IRQ i8042_aux_irq
++
++static void __iomem *kbd_iobase;
++
++#define I8042_COMMAND_REG	(kbd_iobase + 0x64UL)
++#define I8042_DATA_REG		(kbd_iobase + 0x60UL)
++
++static inline int i8042_read_data(void)
++{
++	return readb(kbd_iobase + 0x60UL);
++}
++
++static inline int i8042_read_status(void)
++{
++	return readb(kbd_iobase + 0x64UL);
++}
++
++static inline void i8042_write_data(int val)
++{
++	writeb(val, kbd_iobase + 0x60UL);
++}
++
++static inline void i8042_write_command(int val)
++{
++	writeb(val, kbd_iobase + 0x64UL);
++}
++static inline int i8042_platform_init(void)
++{
++	/* RM200 is strange ... */
++	if (sni_brd_type == SNI_BRD_RM200) {
++		kbd_iobase = ioremap(0x16000000, 4);
++		i8042_kbd_irq = 33;
++		i8042_aux_irq = 44;
++	} else {
++		kbd_iobase = ioremap(0x14000000, 4);
++		i8042_kbd_irq = 1;
++		i8042_aux_irq = 12;
++	}
++	if (!kbd_iobase)
++		return -ENOMEM;
++
++	return 0;
++}
++
++static inline void i8042_platform_exit(void)
++{
++
++}
++
++#endif /* _I8042_SNIRM_H */
+diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
+index 662e844..60931ac 100644
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -277,6 +277,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
+ 			DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
+ 		},
+ 	},
++	{
++		.ident = "Lenovo 3000 n100",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
++		},
++	},
+ 	{ }
+ };
+ 
+diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
+index 2763394..65a74cf 100644
+--- a/drivers/input/serio/i8042.c
++++ b/drivers/input/serio/i8042.c
+@@ -1151,7 +1151,6 @@ static int __devinit i8042_setup_kbd(void)
+ static int __devinit i8042_probe(struct platform_device *dev)
+ {
+ 	int error;
+-	char param;
+ 
+ 	error = i8042_controller_selftest();
+ 	if (error)
+@@ -1174,7 +1173,7 @@ static int __devinit i8042_probe(struct platform_device *dev)
+ 	}
+ #ifdef CONFIG_X86
+ 	if (i8042_dritek) {
+-		param = 0x90;
++		char param = 0x90;
+ 		error = i8042_command(&param, 0x1059);
+ 		if (error)
+ 			goto out_fail;
+diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
+index c972e5d..cbc1beb 100644
+--- a/drivers/input/serio/i8042.h
++++ b/drivers/input/serio/i8042.h
+@@ -18,6 +18,8 @@
+ #include "i8042-jazzio.h"
+ #elif defined(CONFIG_SGI_HAS_I8042)
+ #include "i8042-ip22io.h"
++#elif defined(CONFIG_SNI_RM)
++#include "i8042-snirm.h"
+ #elif defined(CONFIG_PPC)
+ #include "i8042-ppcio.h"
+ #elif defined(CONFIG_SPARC)
+diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
+index 6542edb..acf9830 100644
+--- a/drivers/input/tablet/wacom.h
++++ b/drivers/input/tablet/wacom.h
+@@ -11,7 +11,7 @@
+  *  Copyright (c) 2000 Daniel Egger		<egger at suse.de>
+  *  Copyright (c) 2001 Frederic Lepied		<flepied at mandrakesoft.com>
+  *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris at mech.kuleuven.ac.be>
+- *  Copyright (c) 2002-2007 Ping Cheng		<pingc at wacom.com>
++ *  Copyright (c) 2002-2008 Ping Cheng		<pingc at wacom.com>
+  *
+  *  ChangeLog:
+  *      v0.1 (vp)  - Initial release
+@@ -65,6 +65,7 @@
+  *		   - and wacom_wac.c deals with Wacom specific code
+  *		   - Support Intuos3 4x6
+  *      v1.47 (pc) - Added support for Bamboo
++ *      v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
+  */
+ 
+ /*
+@@ -85,7 +86,7 @@
+ /*
+  * Version Information
+  */
+-#define DRIVER_VERSION "v1.47"
++#define DRIVER_VERSION "v1.48"
+ #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech at ucw.cz>"
+ #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+ #define DRIVER_LICENSE "GPL"
+@@ -125,6 +126,7 @@ extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac
+ extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+ extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+ extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
++extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+ extern __u16 wacom_le16_to_cpu(unsigned char *data);
+ extern __u16 wacom_be16_to_cpu(unsigned char *data);
+ extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
+diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
+index d64b1ea..41caaef 100644
+--- a/drivers/input/tablet/wacom_sys.c
++++ b/drivers/input/tablet/wacom_sys.c
+@@ -171,6 +171,7 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+ 	input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ 		BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
+ 	input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
++	input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+ }
+ 
+ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+@@ -180,6 +181,11 @@ void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+ 	input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+ }
+ 
++void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
++{
++	input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
++}
++
+ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+ {
+ 	input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL);
+diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
+index fc03ba2..ffe3384 100644
+--- a/drivers/input/tablet/wacom_wac.c
++++ b/drivers/input/tablet/wacom_wac.c
+@@ -163,7 +163,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
+ 	}
+ 
+ 	id = STYLUS_DEVICE_ID;
+-	if (data[1] & 0x80) { /* in prox */
++	if ((data[1] & 0x80) && ((data[1] & 0x07) || data[2] || data[3] || data[4]
++			|| data[5] || data[6] || (data[7] & 0x07))) {
++		/* in prox and not a pad data */
+ 
+ 		switch ((data[1] >> 5) & 3) {
+ 
+@@ -233,7 +235,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
+ 		if (data[7] & 0xf8) {
+ 			wacom_input_sync(wcombo); /* sync last event */
+ 			wacom->id[1] = 1;
+-			wacom->serial[1] = (data[7] & 0xf8);
+ 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+ 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
+ 			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
+@@ -252,10 +253,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
+ 		}
+ 		break;
+ 	    case WACOM_MO:
+-		if ((data[7] & 0xf8) || (data[8] & 0x80)) {
++		if ((data[7] & 0xf8) || (data[8] & 0xff)) {
+ 			wacom_input_sync(wcombo); /* sync last event */
+ 			wacom->id[1] = 1;
+-			wacom->serial[1] = (data[7] & 0xf8);
+ 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ 			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+@@ -434,10 +434,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
+ 		wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
+ 		wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
+ 		wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
++		wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
++		wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
+ 		wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+ 		wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+ 
+-		if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) |
++		if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
+ 			data[2] | (data[3] & 0x1f) | data[4])
+ 			wacom_report_key(wcombo, wacom->tool[1], 1);
+ 		else
+@@ -481,13 +483,11 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
+ 		if (data[1] & 0x02) {
+ 			/* Rotation packet */
+ 			if (wacom->features->type >= INTUOS3S) {
+-				/* I3 marker pen rotation reported as wheel
+-				 * due to valuator limitation
+-				 */
++				/* I3 marker pen rotation */
+ 				t = (data[6] << 3) | ((data[7] >> 5) & 7);
+ 				t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+ 					((t-1) / 2 + 450)) : (450 - t / 2) ;
+-				wacom_report_abs(wcombo, ABS_WHEEL, t);
++				wacom_report_abs(wcombo, ABS_Z, t);
+ 			} else {
+ 				/* 4D mouse rotation packet */
+ 				t = (data[6] << 3) | ((data[7] >> 5) & 7);
+@@ -558,6 +558,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
+ 		case INTUOS3:
+ 		case INTUOS3L:
+ 		case CINTIQ:
++		case WACOM_BEE:
+ 			return (wacom_intuos_irq(wacom_wac, wcombo));
+ 			break;
+ 		default:
+@@ -577,6 +578,8 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
+ 		case GRAPHIRE:
+ 			input_dev_g(input_dev, wacom_wac);
+ 			break;
++		case WACOM_BEE:
++			input_dev_bee(input_dev, wacom_wac);
+ 		case INTUOS3:
+ 		case INTUOS3L:
+ 		case CINTIQ:
+@@ -607,12 +610,15 @@ static struct wacom_features wacom_features[] = {
+ 	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 63, GRAPHIRE },
+ 	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 63, WACOM_G4 },
+ 	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 63, WACOM_G4 },
++	{ "Wacom BambooFun 4x5", 9,  14760,  9225,  511, 63, WACOM_MO },
++	{ "Wacom BambooFun 6x8", 9,  21648, 13530,  511, 63, WACOM_MO },
+ 	{ "Wacom Volito",        8,   5104,  3712,  511, 63, GRAPHIRE },
+ 	{ "Wacom PenStation2",   8,   3250,  2320,  255, 63, GRAPHIRE },
+ 	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
+ 	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
+-	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 63, GRAPHIRE },
++	{ "Wacom PenPartner2",   8,   3250,  2320,  511, 63, GRAPHIRE },
+ 	{ "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO },
++	{ "Wacom Bamboo1",       8,   5104,  3712,  511, 63, GRAPHIRE },
+ 	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
+ 	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
+ 	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
+@@ -643,6 +649,7 @@ static struct wacom_features wacom_features[] = {
+ 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
+ 	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
+ 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
++	{ "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
+ 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+ 	{ }
+ };
+@@ -656,12 +663,15 @@ static struct usb_device_id wacom_ids[] = {
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
++	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
++	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
++	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
+@@ -692,6 +702,7 @@ static struct usb_device_id wacom_ids[] = {
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
++	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
+ 	{ }
+ };
+diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
+index a302e22..3342bc0 100644
+--- a/drivers/input/tablet/wacom_wac.h
++++ b/drivers/input/tablet/wacom_wac.h
+@@ -25,6 +25,7 @@ enum {
+ 	INTUOS3,
+ 	INTUOS3L,
+ 	CINTIQ,
++	WACOM_BEE,
+ 	WACOM_MO,
+ 	MAX_TYPE
+ };
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 58934a4..57a1c28 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -213,7 +213,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
+ 	struct ads7846		*ts = dev_get_drvdata(dev);
+ 	struct ser_req		*req = kzalloc(sizeof *req, GFP_KERNEL);
+ 	int			status;
+-	int			sample;
++	int			uninitialized_var(sample);
+ 	int			use_internal;
+ 
+ 	if (!req)
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 19fd4cb..b58472c 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -203,8 +203,11 @@ again:
+ 	if (received < budget) {
+ 		netif_rx_complete(vi->dev, napi);
+ 		if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
+-		    && netif_rx_reschedule(vi->dev, napi))
++		    && napi_schedule_prep(napi)) {
++			vi->rvq->vq_ops->disable_cb(vi->rvq);
++			__netif_rx_schedule(vi->dev, napi);
+ 			goto again;
++		}
+ 	}
+ 
+ 	return received;
+@@ -278,10 +281,11 @@ again:
+ 		pr_debug("%s: virtio not prepared to send\n", dev->name);
+ 		netif_stop_queue(dev);
+ 
+-		/* Activate callback for using skbs: if this fails it
++		/* Activate callback for using skbs: if this returns false it
+ 		 * means some were used in the meantime. */
+ 		if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
+-			printk("Unlikely: restart svq failed\n");
++			printk("Unlikely: restart svq race\n");
++			vi->svq->vq_ops->disable_cb(vi->svq);
+ 			netif_start_queue(dev);
+ 			goto again;
+ 		}
+@@ -294,6 +298,15 @@ again:
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void virtnet_netpoll(struct net_device *dev)
++{
++	struct virtnet_info *vi = netdev_priv(dev);
++
++	napi_schedule(&vi->napi);
++}
++#endif
++
+ static int virtnet_open(struct net_device *dev)
+ {
+ 	struct virtnet_info *vi = netdev_priv(dev);
+@@ -336,6 +349,9 @@ static int virtnet_probe(struct virtio_device *vdev)
+ 	dev->stop = virtnet_close;
+ 	dev->hard_start_xmit = start_xmit;
+ 	dev->features = NETIF_F_HIGHDMA;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	dev->poll_controller = virtnet_netpoll;
++#endif
+ 	SET_NETDEV_DEV(dev, &vdev->dev);
+ 
+ 	/* Do we support "hardware" checksums? */
+diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
+index 7f4836b..5fa4ba0 100644
+--- a/drivers/pci/hotplug/pciehp_core.c
++++ b/drivers/pci/hotplug/pciehp_core.c
+@@ -467,7 +467,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
+ 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+ 
+ 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+-	if (value) {
++	if (value && pciehp_force) {
+ 		rc = pciehp_enable_slot(t_slot);
+ 		if (rc)	/* -ENODEV: shouldn't happen, but deal with it */
+ 			value = 0;
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index 3ab313e..17e71d5 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -4,8 +4,6 @@
+ 
+ menuconfig THERMAL
+ 	bool "Generic Thermal sysfs driver"
+-	select HWMON
+-	default y
+ 	help
+ 	  Generic Thermal Sysfs driver offers a generic mechanism for
+ 	  thermal management. Usually it's made up of one or more thermal
+diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c
+index 41bd4c8..8b86e53 100644
+--- a/drivers/thermal/thermal.c
++++ b/drivers/thermal/thermal.c
+@@ -30,10 +30,8 @@
+ #include <linux/idr.h>
+ #include <linux/thermal.h>
+ #include <linux/spinlock.h>
+-#include <linux/hwmon.h>
+-#include <linux/hwmon-sysfs.h>
+ 
+-MODULE_AUTHOR("Zhang Rui");
++MODULE_AUTHOR("Zhang Rui")
+ MODULE_DESCRIPTION("Generic thermal management sysfs support");
+ MODULE_LICENSE("GPL");
+ 
+@@ -58,9 +56,6 @@ static LIST_HEAD(thermal_tz_list);
+ static LIST_HEAD(thermal_cdev_list);
+ static DEFINE_MUTEX(thermal_list_lock);
+ 
+-static struct device *thermal_hwmon;
+-#define MAX_THERMAL_ZONES	10
+-
+ static int get_idr(struct idr *idr, struct mutex *lock, int *id)
+ {
+ 	int err;
+@@ -92,67 +87,7 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
+ 		mutex_unlock(lock);
+ }
+ 
+-/* hwmon sys I/F*/
+-static ssize_t
+-name_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	return sprintf(buf, "thermal_sys_class\n");
+-}
+-
+-static ssize_t
+-temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct thermal_zone_device *tz;
+-	struct sensor_device_attribute *sensor_attr
+-						= to_sensor_dev_attr(attr);
+-
+-	list_for_each_entry(tz, &thermal_tz_list, node)
+-		if (tz->id == sensor_attr->index)
+-			return tz->ops->get_temp(tz, buf);
+-
+-	return -ENODEV;
+-}
+-
+-static ssize_t
+-temp_crit_show(struct device *dev, struct device_attribute *attr,
+-		char *buf)
+-{
+-	struct thermal_zone_device *tz;
+-	struct sensor_device_attribute *sensor_attr
+-						= to_sensor_dev_attr(attr);
+-
+-	list_for_each_entry(tz, &thermal_tz_list, node)
+-		if (tz->id == sensor_attr->index)
+-			return tz->ops->get_trip_temp(tz, 0, buf);
+-
+-	return -ENODEV;
+-}
+-
+-static DEVICE_ATTR(name, 0444, name_show, NULL);
+-static struct sensor_device_attribute sensor_attrs[] = {
+-	SENSOR_ATTR(temp1_input, 0444, temp_input_show, NULL, 0),
+-	SENSOR_ATTR(temp1_crit, 0444, temp_crit_show, NULL, 0),
+-	SENSOR_ATTR(temp2_input, 0444, temp_input_show, NULL, 1),
+-	SENSOR_ATTR(temp2_crit, 0444, temp_crit_show, NULL, 1),
+-	SENSOR_ATTR(temp3_input, 0444, temp_input_show, NULL, 2),
+-	SENSOR_ATTR(temp3_crit, 0444, temp_crit_show, NULL, 2),
+-	SENSOR_ATTR(temp4_input, 0444, temp_input_show, NULL, 3),
+-	SENSOR_ATTR(temp4_crit, 0444, temp_crit_show, NULL, 3),
+-	SENSOR_ATTR(temp5_input, 0444, temp_input_show, NULL, 4),
+-	SENSOR_ATTR(temp5_crit, 0444, temp_crit_show, NULL, 4),
+-	SENSOR_ATTR(temp6_input, 0444, temp_input_show, NULL, 5),
+-	SENSOR_ATTR(temp6_crit, 0444, temp_crit_show, NULL, 5),
+-	SENSOR_ATTR(temp7_input, 0444, temp_input_show, NULL, 6),
+-	SENSOR_ATTR(temp7_crit, 0444, temp_crit_show, NULL, 6),
+-	SENSOR_ATTR(temp8_input, 0444, temp_input_show, NULL, 7),
+-	SENSOR_ATTR(temp8_crit, 0444, temp_crit_show, NULL, 7),
+-	SENSOR_ATTR(temp9_input, 0444, temp_input_show, NULL, 8),
+-	SENSOR_ATTR(temp9_crit, 0444, temp_crit_show, NULL, 8),
+-	SENSOR_ATTR(temp10_input, 0444, temp_input_show, NULL, 9),
+-	SENSOR_ATTR(temp10_crit, 0444, temp_crit_show, NULL, 9),
+-};
+-
+-/* thermal zone sys I/F */
++/* sys I/F for thermal zone */
+ 
+ #define to_thermal_zone(_dev) \
+ 	container_of(_dev, struct thermal_zone_device, device)
+@@ -279,7 +214,7 @@ do {	\
+ 	device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);	\
+ } while (0)
+ 
+-/* cooling device sys I/F */
++/* sys I/F for cooling device */
+ #define to_cooling_device(_dev)	\
+ 	container_of(_dev, struct thermal_cooling_device, device)
+ 
+@@ -512,9 +447,6 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
+ 	struct thermal_zone_device *pos;
+ 	int result;
+ 
+-	if (!type)
+-		return ERR_PTR(-EINVAL);
+-
+ 	if (strlen(type) >= THERMAL_NAME_LENGTH)
+ 		return ERR_PTR(-EINVAL);
+ 
+@@ -545,9 +477,11 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
+ 	}
+ 
+ 	/* sys I/F */
+-	result = device_create_file(&cdev->device, &dev_attr_cdev_type);
+-	if (result)
+-		goto unregister;
++	if (type) {
++		result = device_create_file(&cdev->device, &dev_attr_cdev_type);
++		if (result)
++			goto unregister;
++	}
+ 
+ 	result = device_create_file(&cdev->device, &dev_attr_max_state);
+ 	if (result)
+@@ -613,8 +547,8 @@ void thermal_cooling_device_unregister(struct
+ 		tz->ops->unbind(tz, cdev);
+ 	}
+ 	mutex_unlock(&thermal_list_lock);
+-
+-	device_remove_file(&cdev->device, &dev_attr_cdev_type);
++	if (cdev->type[0])
++		device_remove_file(&cdev->device, &dev_attr_cdev_type);
+ 	device_remove_file(&cdev->device, &dev_attr_max_state);
+ 	device_remove_file(&cdev->device, &dev_attr_cur_state);
+ 
+@@ -646,9 +580,6 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
+ 	int result;
+ 	int count;
+ 
+-	if (!type)
+-		return ERR_PTR(-EINVAL);
+-
+ 	if (strlen(type) >= THERMAL_NAME_LENGTH)
+ 		return ERR_PTR(-EINVAL);
+ 
+@@ -670,13 +601,6 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
+ 		kfree(tz);
+ 		return ERR_PTR(result);
+ 	}
+-	if (tz->id >= MAX_THERMAL_ZONES) {
+-		printk(KERN_ERR PREFIX
+-			"Too many thermal zones\n");
+-		release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
+-		kfree(tz);
+-		return ERR_PTR(-EINVAL);
+-	}
+ 
+ 	strcpy(tz->type, type);
+ 	tz->ops = ops;
+@@ -691,27 +615,12 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
+ 		return ERR_PTR(result);
+ 	}
+ 
+-	/* hwmon sys I/F */
+-	result = device_create_file(thermal_hwmon,
+-					&sensor_attrs[tz->id * 2].dev_attr);
+-	if (result)
+-		goto unregister;
+-
+-	if (trips > 0) {
+-		char buf[40];
+-		result = tz->ops->get_trip_type(tz, 0, buf);
+-		if (result > 0 && !strcmp(buf, "critical\n")) {
+-			result = device_create_file(thermal_hwmon,
+-					&sensor_attrs[tz->id * 2 + 1].dev_attr);
+-			if (result)
+-				goto unregister;
+-		}
+-	}
+-
+ 	/* sys I/F */
+-	result = device_create_file(&tz->device, &dev_attr_type);
+-	if (result)
+-		goto unregister;
++	if (type) {
++		result = device_create_file(&tz->device, &dev_attr_type);
++		if (result)
++			goto unregister;
++	}
+ 
+ 	result = device_create_file(&tz->device, &dev_attr_temp);
+ 	if (result)
+@@ -778,17 +687,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+ 		    tz->ops->unbind(tz, cdev);
+ 	mutex_unlock(&thermal_list_lock);
+ 
+-	device_remove_file(thermal_hwmon,
+-				&sensor_attrs[tz->id * 2].dev_attr);
+-	if (tz->trips > 0) {
+-		char buf[40];
+-		if (tz->ops->get_trip_type(tz, 0, buf) > 0)
+-			if (!strcmp(buf, "critical\n"))
+-				device_remove_file(thermal_hwmon,
+-				&sensor_attrs[tz->id * 2 + 1].dev_attr);
+-	}
+-
+-	device_remove_file(&tz->device, &dev_attr_type);
++	if (tz->type[0])
++		device_remove_file(&tz->device, &dev_attr_type);
+ 	device_remove_file(&tz->device, &dev_attr_temp);
+ 	if (tz->ops->get_mode)
+ 		device_remove_file(&tz->device, &dev_attr_mode);
+@@ -805,19 +705,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
+ 
+ EXPORT_SYMBOL(thermal_zone_device_unregister);
+ 
+-static void thermal_exit(void)
+-{
+-	if (thermal_hwmon) {
+-		device_remove_file(thermal_hwmon, &dev_attr_name);
+-		hwmon_device_unregister(thermal_hwmon);
+-	}
+-	class_unregister(&thermal_class);
+-	idr_destroy(&thermal_tz_idr);
+-	idr_destroy(&thermal_cdev_idr);
+-	mutex_destroy(&thermal_idr_lock);
+-	mutex_destroy(&thermal_list_lock);
+-}
+-
+ static int __init thermal_init(void)
+ {
+ 	int result = 0;
+@@ -829,21 +716,17 @@ static int __init thermal_init(void)
+ 		mutex_destroy(&thermal_idr_lock);
+ 		mutex_destroy(&thermal_list_lock);
+ 	}
+-
+-	thermal_hwmon = hwmon_device_register(NULL);
+-	if (IS_ERR(thermal_hwmon)) {
+-		result = PTR_ERR(thermal_hwmon);
+-		thermal_hwmon = NULL;
+-		printk(KERN_ERR PREFIX
+-			"unable to register hwmon device\n");
+-		thermal_exit();
+-		return result;
+-	}
+-
+-	result = device_create_file(thermal_hwmon, &dev_attr_name);
+-
+ 	return result;
+ }
+ 
++static void __exit thermal_exit(void)
++{
++	class_unregister(&thermal_class);
++	idr_destroy(&thermal_tz_idr);
++	idr_destroy(&thermal_cdev_idr);
++	mutex_destroy(&thermal_idr_lock);
++	mutex_destroy(&thermal_list_lock);
++}
++
+ subsys_initcall(thermal_init);
+ module_exit(thermal_exit);
+diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
+index c8a4332..0b3efc3 100644
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -152,7 +152,7 @@ static void virtballoon_changed(struct virtio_device *vdev)
+ 	wake_up(&vb->config_change);
+ }
+ 
+-static inline int towards_target(struct virtio_balloon *vb)
++static inline s64 towards_target(struct virtio_balloon *vb)
+ {
+ 	u32 v;
+ 	__virtio_config_val(vb->vdev,
+@@ -176,7 +176,7 @@ static int balloon(void *_vballoon)
+ 
+ 	set_freezable();
+ 	while (!kthread_should_stop()) {
+-		int diff;
++		s64 diff;
+ 
+ 		try_to_freeze();
+ 		wait_event_interruptible(vb->config_change,
+diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
+index 26f787d..59a8f73 100644
+--- a/drivers/virtio/virtio_pci.c
++++ b/drivers/virtio/virtio_pci.c
+@@ -177,6 +177,7 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
+ 	struct virtio_pci_device *vp_dev = opaque;
+ 	struct virtio_pci_vq_info *info;
+ 	irqreturn_t ret = IRQ_NONE;
++	unsigned long flags;
+ 	u8 isr;
+ 
+ 	/* reading the ISR has the effect of also clearing it so it's very
+@@ -197,12 +198,12 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
+ 			drv->config_changed(&vp_dev->vdev);
+ 	}
+ 
+-	spin_lock(&vp_dev->lock);
++	spin_lock_irqsave(&vp_dev->lock, flags);
+ 	list_for_each_entry(info, &vp_dev->virtqueues, node) {
+ 		if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
+ 			ret = IRQ_HANDLED;
+ 	}
+-	spin_unlock(&vp_dev->lock);
++	spin_unlock_irqrestore(&vp_dev->lock, flags);
+ 
+ 	return ret;
+ }
+@@ -214,6 +215,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
+ 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+ 	struct virtio_pci_vq_info *info;
+ 	struct virtqueue *vq;
++	unsigned long flags;
+ 	u16 num;
+ 	int err;
+ 
+@@ -255,9 +257,9 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
+ 	vq->priv = info;
+ 	info->vq = vq;
+ 
+-	spin_lock(&vp_dev->lock);
++	spin_lock_irqsave(&vp_dev->lock, flags);
+ 	list_add(&info->node, &vp_dev->virtqueues);
+-	spin_unlock(&vp_dev->lock);
++	spin_unlock_irqrestore(&vp_dev->lock, flags);
+ 
+ 	return vq;
+ 
+@@ -274,10 +276,11 @@ static void vp_del_vq(struct virtqueue *vq)
+ {
+ 	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+ 	struct virtio_pci_vq_info *info = vq->priv;
++	unsigned long flags;
+ 
+-	spin_lock(&vp_dev->lock);
++	spin_lock_irqsave(&vp_dev->lock, flags);
+ 	list_del(&info->node);
+-	spin_unlock(&vp_dev->lock);
++	spin_unlock_irqrestore(&vp_dev->lock, flags);
+ 
+ 	vring_del_virtqueue(vq);
+ 
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index 3a28c13..aa71402 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -232,7 +232,6 @@ static bool vring_enable_cb(struct virtqueue *_vq)
+ 	vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+ 	mb();
+ 	if (unlikely(more_used(vq))) {
+-		vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+ 		END_USE(vq);
+ 		return false;
+ 	}
+diff --git a/fs/bio.c b/fs/bio.c
+index 3312fcc..553b5b7 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -1194,6 +1194,8 @@ EXPORT_SYMBOL(bio_hw_segments);
+ EXPORT_SYMBOL(bio_add_page);
+ EXPORT_SYMBOL(bio_add_pc_page);
+ EXPORT_SYMBOL(bio_get_nr_vecs);
++EXPORT_SYMBOL(bio_map_user);
++EXPORT_SYMBOL(bio_unmap_user);
+ EXPORT_SYMBOL(bio_map_kern);
+ EXPORT_SYMBOL(bio_pair_release);
+ EXPORT_SYMBOL(bio_split);
+diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
+index 878bf25..92fb358 100644
+--- a/fs/hfs/brec.c
++++ b/fs/hfs/brec.c
+@@ -229,7 +229,7 @@ skip:
+ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+ {
+ 	struct hfs_btree *tree;
+-	struct hfs_bnode *node, *new_node;
++	struct hfs_bnode *node, *new_node, *next_node;
+ 	struct hfs_bnode_desc node_desc;
+ 	int num_recs, new_rec_off, new_off, old_rec_off;
+ 	int data_start, data_end, size;
+@@ -248,6 +248,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+ 	new_node->type = node->type;
+ 	new_node->height = node->height;
+ 
++	if (node->next)
++		next_node = hfs_bnode_find(tree, node->next);
++	else
++		next_node = NULL;
++
++	if (IS_ERR(next_node)) {
++		hfs_bnode_put(node);
++		hfs_bnode_put(new_node);
++		return next_node;
++	}
++
+ 	size = tree->node_size / 2 - node->num_recs * 2 - 14;
+ 	old_rec_off = tree->node_size - 4;
+ 	num_recs = 1;
+@@ -261,6 +272,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+ 		/* panic? */
+ 		hfs_bnode_put(node);
+ 		hfs_bnode_put(new_node);
++		if (next_node)
++			hfs_bnode_put(next_node);
+ 		return ERR_PTR(-ENOSPC);
+ 	}
+ 
+@@ -315,8 +328,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+ 	hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
+ 
+ 	/* update next bnode header */
+-	if (new_node->next) {
+-		struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
++	if (next_node) {
+ 		next_node->prev = new_node->this;
+ 		hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
+ 		node_desc.prev = cpu_to_be32(next_node->prev);
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 9a4da0a..8a10f6f 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -1036,6 +1036,26 @@ static const struct file_operations proc_loginuid_operations = {
+ 	.read		= proc_loginuid_read,
+ 	.write		= proc_loginuid_write,
+ };
++
++static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
++				  size_t count, loff_t *ppos)
++{
++	struct inode * inode = file->f_path.dentry->d_inode;
++	struct task_struct *task = get_proc_task(inode);
++	ssize_t length;
++	char tmpbuf[TMPBUFLEN];
++
++	if (!task)
++		return -ESRCH;
++	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
++				audit_get_sessionid(task));
++	put_task_struct(task);
++	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
++}
++
++static const struct file_operations proc_sessionid_operations = {
++	.read		= proc_sessionid_read,
++};
+ #endif
+ 
+ #ifdef CONFIG_FAULT_INJECTION
+@@ -2319,6 +2339,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ 	REG("oom_adj",    S_IRUGO|S_IWUSR, oom_adjust),
+ #ifdef CONFIG_AUDITSYSCALL
+ 	REG("loginuid",   S_IWUSR|S_IRUGO, loginuid),
++	REG("sessionid",  S_IRUSR, sessionid),
+ #endif
+ #ifdef CONFIG_FAULT_INJECTION
+ 	REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+@@ -2649,6 +2670,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ 	REG("oom_adj",   S_IRUGO|S_IWUSR, oom_adjust),
+ #ifdef CONFIG_AUDITSYSCALL
+ 	REG("loginuid",  S_IWUSR|S_IRUGO, loginuid),
++	REG("sessionid",  S_IRUSR, sessionid),
+ #endif
+ #ifdef CONFIG_FAULT_INJECTION
+ 	REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 0fac822..4108b38 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -127,7 +127,6 @@ header-y += pkt_sched.h
+ header-y += posix_types.h
+ header-y += ppdev.h
+ header-y += prctl.h
+-header-y += ps2esdi.h
+ header-y += qnxtypes.h
+ header-y += quotaio_v1.h
+ header-y += quotaio_v2.h
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 9010f54..b7e4b63 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1045,6 +1045,8 @@ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
+ void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
+ void __iomem * const *pcim_iomap_table(struct pci_dev *pdev);
+ int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
++int pcim_iomap_regions_request_all(struct pci_dev *pdev, u16 mask,
++				   const char *name);
+ void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask);
+ 
+ extern int pci_pci_problems;
+diff --git a/include/linux/ps2esdi.h b/include/linux/ps2esdi.h
+deleted file mode 100644
+index c0e050b..0000000
+--- a/include/linux/ps2esdi.h
++++ /dev/null
+@@ -1,98 +0,0 @@
+-#ifndef _PS2ESDI_H_
+-#define _PS2ESDI_H_
+-
+-#define NRML_ESDI_ID 0xddff
+-#define INTG_ESDI_ID 0xdf9f
+-
+-#define PRIMARY_IO_BASE 0x3510
+-#define ALT_IO_BASE 0x3518
+-
+-#define ESDI_CMD_INT (io_base+0)
+-#define ESDI_STT_INT (io_base+0)
+-#define ESDI_CONTROL (io_base+2)
+-#define ESDI_STATUS  (io_base+2)
+-#define ESDI_ATTN    (io_base+3)
+-#define ESDI_INTRPT  (io_base+3)
+-
+-#define STATUS_ENABLED    0x01
+-#define STATUS_ALTERNATE  0x02
+-#define STATUS_BUSY       0x10
+-#define STATUS_STAT_AVAIL 0x08
+-#define STATUS_INTR       0x01
+-#define STATUS_RESET_FAIL 0xea
+-#define STATUS_CMD_INF	  0x04
+-
+-#define CTRL_SOFT_RESET   0xe4
+-#define CTRL_HARD_RESET   0x80
+-#define CTRL_EOI          0xe2
+-#define CTRL_ENABLE_DMA   0x02
+-#define CTRL_ENABLE_INTR  0x01
+-#define CTRL_DISABLE_INTR  0x00
+-
+-#define ATT_EOI 0x02
+-
+-/* bits of word 0 of configuration status block. more info see p.38 of tech ref */
+-#define CONFIG_IS 0x10 /* Invalid Secondary */
+-#define CONFIG_ZD 0x08 /* Zero Defect */
+-#define CONFIG_SF 0x04 /* Skewed Format */
+-#define CONFIG_FR 0x02 /* Removable */
+-#define CONFIG_RT 0x01 /* Retries */
+-
+-#define PORT_SYS_A   0x92
+-#define PORT_DMA_FN  0x18
+-#define PORT_DMA_EX  0x1a
+-
+-#define ON (unsigned char)0x40
+-#define OFF (unsigned char)~ON
+-#define LITE_ON outb(inb(PORT_SYS_A) | ON,PORT_SYS_A)
+-#define LITE_OFF outb((inb(PORT_SYS_A) & OFF),PORT_SYS_A)
+-
+-#define FAIL 0
+-#define SUCCES 1
+-
+-#define INT_CMD_COMPLETE 0x01
+-#define INT_CMD_ECC      0x03
+-#define INT_CMD_RETRY    0x05
+-#define INT_CMD_FORMAT   0x06
+-#define INT_CMD_ECC_RETRY 0x07
+-#define INT_CMD_WARNING  0x08
+-#define INT_CMD_ABORT    0x09
+-#define INT_RESET        0x0A
+-#define INT_TRANSFER_REQ 0x0B
+-#define INT_CMD_FAILED   0x0C
+-#define INT_DMA_ERR      0x0D
+-#define INT_CMD_BLK_ERR  0x0E
+-#define INT_ATTN_ERROR   0x0F
+-
+-#define DMA_MASK_CHAN 0x90
+-#define DMA_UNMASK_CHAN 0xA0
+-#define DMA_WRITE_ADDR 0x20
+-#define DMA_WRITE_TC 0x40
+-#define DMA_WRITE_MODE 0x70
+-
+-#define CMD_GET_DEV_CONFIG 0x09
+-#define CMD_READ 0x4601
+-#define CMD_WRITE 0x4602
+-#define DMA_READ_16 0x4C
+-#define DMA_WRITE_16 0x44
+-
+-
+-#define MB 1024*1024
+-#define SECT_SIZE 512   
+-
+-#define ERROR 1
+-#define OK 0
+-
+-#define HDIO_GETGEO 0x0301
+-
+-#define FALSE 0
+-#define TRUE !FALSE
+-
+-struct ps2esdi_geometry {
+-	unsigned char heads;
+-	unsigned char sectors;
+-	unsigned short cylinders;
+-	unsigned long start;
+-};
+-
+-#endif /* _PS2ESDI_H_ */
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 11d8e9a..3625fca 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -929,6 +929,9 @@ struct sched_entity {
+ 	u64			vruntime;
+ 	u64			prev_sum_exec_runtime;
+ 
++	u64			last_wakeup;
++	u64			avg_overlap;
++
+ #ifdef CONFIG_SCHEDSTATS
+ 	u64			wait_start;
+ 	u64			wait_max;
+diff --git a/include/linux/topology.h b/include/linux/topology.h
+index 2352f46..2d8dac8 100644
+--- a/include/linux/topology.h
++++ b/include/linux/topology.h
+@@ -138,7 +138,6 @@
+ 				| SD_BALANCE_FORK	\
+ 				| SD_BALANCE_EXEC	\
+ 				| SD_WAKE_AFFINE	\
+-				| SD_WAKE_IDLE		\
+ 				| SD_SHARE_PKG_RESOURCES\
+ 				| BALANCE_FOR_MC_POWER,	\
+ 	.last_balance		= jiffies,		\
+diff --git a/include/linux/virtio.h b/include/linux/virtio.h
+index 260d1fc..12c18ac 100644
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -43,8 +43,9 @@ struct virtqueue
+  *	vq: the struct virtqueue we're talking about.
+  * @enable_cb: restart callbacks after disable_cb.
+  *	vq: the struct virtqueue we're talking about.
+- *	This returns "false" (and doesn't re-enable) if there are pending
+- *	buffers in the queue, to avoid a race.
++ *	This re-enables callbacks; it returns "false" if there are pending
++ *	buffers in the queue, to detect a possible race between the driver
++ *	checking for more work, and enabling callbacks.
+  *
+  * Locking rules are straightforward: the driver is responsible for
+  * locking.  No two operations may be invoked simultaneously.
+diff --git a/kernel/relay.c b/kernel/relay.c
+index d080b9d..4c035a8 100644
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -1066,7 +1066,7 @@ static int subbuf_splice_actor(struct file *in,
+ 			       unsigned int flags,
+ 			       int *nonpad_ret)
+ {
+-	unsigned int pidx, poff, total_len, subbuf_pages, ret;
++	unsigned int pidx, poff, total_len, subbuf_pages, nr_pages, ret;
+ 	struct rchan_buf *rbuf = in->private_data;
+ 	unsigned int subbuf_size = rbuf->chan->subbuf_size;
+ 	uint64_t pos = (uint64_t) *ppos;
+@@ -1097,8 +1097,9 @@ static int subbuf_splice_actor(struct file *in,
+ 	subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
+ 	pidx = (read_start / PAGE_SIZE) % subbuf_pages;
+ 	poff = read_start & ~PAGE_MASK;
++	nr_pages = min_t(unsigned int, subbuf_pages, PIPE_BUFFERS);
+ 
+-	for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
++	for (total_len = 0; spd.nr_pages < nr_pages; spd.nr_pages++) {
+ 		unsigned int this_len, this_end, private;
+ 		unsigned int cur_pos = read_start + total_len;
+ 
+diff --git a/kernel/sched.c b/kernel/sched.c
+index d1ad69b..3f7c5eb 100644
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -1396,6 +1396,12 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
+ {
+ 	s64 delta;
+ 
++	/*
++	 * Buddy candidates are cache hot:
++	 */
++	if (&p->se == cfs_rq_of(&p->se)->next)
++		return 1;
++
+ 	if (p->sched_class != &fair_sched_class)
+ 		return 0;
+ 
+@@ -1855,10 +1861,11 @@ out_activate:
+ 		schedstat_inc(p, se.nr_wakeups_remote);
+ 	update_rq_clock(rq);
+ 	activate_task(rq, p, 1);
+-	check_preempt_curr(rq, p);
+ 	success = 1;
+ 
+ out_running:
++	check_preempt_curr(rq, p);
++
+ 	p->state = TASK_RUNNING;
+ #ifdef CONFIG_SMP
+ 	if (p->sched_class->task_wake_up)
+@@ -1892,6 +1899,8 @@ static void __sched_fork(struct task_struct *p)
+ 	p->se.exec_start		= 0;
+ 	p->se.sum_exec_runtime		= 0;
+ 	p->se.prev_sum_exec_runtime	= 0;
++	p->se.last_wakeup		= 0;
++	p->se.avg_overlap		= 0;
+ 
+ #ifdef CONFIG_SCHEDSTATS
+ 	p->se.wait_start		= 0;
+diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
+index 4b5e24c..ef358ba 100644
+--- a/kernel/sched_debug.c
++++ b/kernel/sched_debug.c
+@@ -288,6 +288,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+ 	PN(se.exec_start);
+ 	PN(se.vruntime);
+ 	PN(se.sum_exec_runtime);
++	PN(se.avg_overlap);
+ 
+ 	nr_switches = p->nvcsw + p->nivcsw;
+ 
+diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
+index f2cc590..b85cac4 100644
+--- a/kernel/sched_fair.c
++++ b/kernel/sched_fair.c
+@@ -73,13 +73,13 @@ unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL;
+ 
+ /*
+  * SCHED_OTHER wake-up granularity.
+- * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds)
++ * (default: 5 msec * (1 + ilog(ncpus)), units: nanoseconds)
+  *
+  * This option delays the preemption effects of decoupled workloads
+  * and reduces their over-scheduling. Synchronous workloads will still
+  * have immediate wakeup/sleep latencies.
+  */
+-unsigned int sysctl_sched_wakeup_granularity = 10000000UL;
++unsigned int sysctl_sched_wakeup_granularity = 5000000UL;
+ 
+ const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+ 
+@@ -556,6 +556,21 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
+ 	account_entity_enqueue(cfs_rq, se);
+ }
+ 
++static void update_avg(u64 *avg, u64 sample)
++{
++	s64 diff = sample - *avg;
++	*avg += diff >> 3;
++}
++
++static void update_avg_stats(struct cfs_rq *cfs_rq, struct sched_entity *se)
++{
++	if (!se->last_wakeup)
++		return;
++
++	update_avg(&se->avg_overlap, se->sum_exec_runtime - se->last_wakeup);
++	se->last_wakeup = 0;
++}
++
+ static void
+ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
+ {
+@@ -566,6 +581,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
+ 
+ 	update_stats_dequeue(cfs_rq, se);
+ 	if (sleep) {
++		update_avg_stats(cfs_rq, se);
+ #ifdef CONFIG_SCHEDSTATS
+ 		if (entity_is_task(se)) {
+ 			struct task_struct *tsk = task_of(se);
+@@ -980,96 +996,121 @@ static inline int wake_idle(int cpu, struct task_struct *p)
+ #endif
+ 
+ #ifdef CONFIG_SMP
+-static int select_task_rq_fair(struct task_struct *p, int sync)
++
++static const struct sched_class fair_sched_class;
++
++static int
++wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq,
++	    struct task_struct *p, int prev_cpu, int this_cpu, int sync,
++	    int idx, unsigned long load, unsigned long this_load,
++	    unsigned int imbalance)
+ {
+-	int cpu, this_cpu;
+-	struct rq *rq;
+-	struct sched_domain *sd, *this_sd = NULL;
+-	int new_cpu;
++	struct task_struct *curr = this_rq->curr;
++	unsigned long tl = this_load;
++	unsigned long tl_per_task;
++
++	if (!(this_sd->flags & SD_WAKE_AFFINE))
++		return 0;
++
++	/*
++	 * If the currently running task will sleep within
++	 * a reasonable amount of time then attract this newly
++	 * woken task:
++	 */
++	if (sync && curr->sched_class == &fair_sched_class) {
++		if (curr->se.avg_overlap < sysctl_sched_migration_cost &&
++				p->se.avg_overlap < sysctl_sched_migration_cost)
++			return 1;
++	}
+ 
+-	cpu      = task_cpu(p);
+-	rq       = task_rq(p);
+-	this_cpu = smp_processor_id();
+-	new_cpu  = cpu;
++	schedstat_inc(p, se.nr_wakeups_affine_attempts);
++	tl_per_task = cpu_avg_load_per_task(this_cpu);
+ 
+-	if (cpu == this_cpu)
+-		goto out_set_cpu;
++	/*
++	 * If sync wakeup then subtract the (maximum possible)
++	 * effect of the currently running task from the load
++	 * of the current CPU:
++	 */
++	if (sync)
++		tl -= current->se.load.weight;
++
++	if ((tl <= load && tl + target_load(prev_cpu, idx) <= tl_per_task) ||
++			100*(tl + p->se.load.weight) <= imbalance*load) {
++		/*
++		 * This domain has SD_WAKE_AFFINE and
++		 * p is cache cold in this domain, and
++		 * there is no bad imbalance.
++		 */
++		schedstat_inc(this_sd, ttwu_move_affine);
++		schedstat_inc(p, se.nr_wakeups_affine);
+ 
++		return 1;
++	}
++	return 0;
++}
++
++static int select_task_rq_fair(struct task_struct *p, int sync)
++{
++	struct sched_domain *sd, *this_sd = NULL;
++	int prev_cpu, this_cpu, new_cpu;
++	unsigned long load, this_load;
++	struct rq *rq, *this_rq;
++	unsigned int imbalance;
++	int idx;
++
++	prev_cpu	= task_cpu(p);
++	rq		= task_rq(p);
++	this_cpu	= smp_processor_id();
++	this_rq		= cpu_rq(this_cpu);
++	new_cpu		= prev_cpu;
++
++	/*
++	 * 'this_sd' is the first domain that both
++	 * this_cpu and prev_cpu are present in:
++	 */
+ 	for_each_domain(this_cpu, sd) {
+-		if (cpu_isset(cpu, sd->span)) {
++		if (cpu_isset(prev_cpu, sd->span)) {
+ 			this_sd = sd;
+ 			break;
+ 		}
+ 	}
+ 
+ 	if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
+-		goto out_set_cpu;
++		goto out;
+ 
+ 	/*
+ 	 * Check for affine wakeup and passive balancing possibilities.
+ 	 */
+-	if (this_sd) {
+-		int idx = this_sd->wake_idx;
+-		unsigned int imbalance;
+-		unsigned long load, this_load;
+-
+-		imbalance = 100 + (this_sd->imbalance_pct - 100) / 2;
+-
+-		load = source_load(cpu, idx);
+-		this_load = target_load(this_cpu, idx);
+-
+-		new_cpu = this_cpu; /* Wake to this CPU if we can */
+-
+-		if (this_sd->flags & SD_WAKE_AFFINE) {
+-			unsigned long tl = this_load;
+-			unsigned long tl_per_task;
+-
+-			/*
+-			 * Attract cache-cold tasks on sync wakeups:
+-			 */
+-			if (sync && !task_hot(p, rq->clock, this_sd))
+-				goto out_set_cpu;
+-
+-			schedstat_inc(p, se.nr_wakeups_affine_attempts);
+-			tl_per_task = cpu_avg_load_per_task(this_cpu);
+-
+-			/*
+-			 * If sync wakeup then subtract the (maximum possible)
+-			 * effect of the currently running task from the load
+-			 * of the current CPU:
+-			 */
+-			if (sync)
+-				tl -= current->se.load.weight;
+-
+-			if ((tl <= load &&
+-				tl + target_load(cpu, idx) <= tl_per_task) ||
+-			       100*(tl + p->se.load.weight) <= imbalance*load) {
+-				/*
+-				 * This domain has SD_WAKE_AFFINE and
+-				 * p is cache cold in this domain, and
+-				 * there is no bad imbalance.
+-				 */
+-				schedstat_inc(this_sd, ttwu_move_affine);
+-				schedstat_inc(p, se.nr_wakeups_affine);
+-				goto out_set_cpu;
+-			}
+-		}
++	if (!this_sd)
++		goto out;
+ 
+-		/*
+-		 * Start passive balancing when half the imbalance_pct
+-		 * limit is reached.
+-		 */
+-		if (this_sd->flags & SD_WAKE_BALANCE) {
+-			if (imbalance*this_load <= 100*load) {
+-				schedstat_inc(this_sd, ttwu_move_balance);
+-				schedstat_inc(p, se.nr_wakeups_passive);
+-				goto out_set_cpu;
+-			}
++	idx = this_sd->wake_idx;
++
++	imbalance = 100 + (this_sd->imbalance_pct - 100) / 2;
++
++	load = source_load(prev_cpu, idx);
++	this_load = target_load(this_cpu, idx);
++
++	if (wake_affine(rq, this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx,
++				     load, this_load, imbalance))
++		return this_cpu;
++
++	if (prev_cpu == this_cpu)
++		goto out;
++
++	/*
++	 * Start passive balancing when half the imbalance_pct
++	 * limit is reached.
++	 */
++	if (this_sd->flags & SD_WAKE_BALANCE) {
++		if (imbalance*this_load <= 100*load) {
++			schedstat_inc(this_sd, ttwu_move_balance);
++			schedstat_inc(p, se.nr_wakeups_passive);
++			return this_cpu;
+ 		}
+ 	}
+ 
+-	new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */
+-out_set_cpu:
++out:
+ 	return wake_idle(new_cpu, p);
+ }
+ #endif /* CONFIG_SMP */
+@@ -1092,6 +1133,10 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
+ 		return;
+ 	}
+ 
++	se->last_wakeup = se->sum_exec_runtime;
++	if (unlikely(se == pse))
++		return;
++
+ 	cfs_rq_of(pse)->next = pse;
+ 
+ 	/*
+diff --git a/lib/devres.c b/lib/devres.c
+index b1d336c..edc27a5 100644
+--- a/lib/devres.c
++++ b/lib/devres.c
+@@ -298,6 +298,31 @@ int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
+ EXPORT_SYMBOL(pcim_iomap_regions);
+ 
+ /**
++ * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
++ * @pdev: PCI device to map IO resources for
++ * @mask: Mask of BARs to iomap
++ * @name: Name used when requesting regions
++ *
++ * Request all PCI BARs and iomap regions specified by @mask.
++ */
++int pcim_iomap_regions_request_all(struct pci_dev *pdev, u16 mask,
++				   const char *name)
++{
++	int request_mask = ((1 << 6) - 1) & ~mask;
++	int rc;
++
++	rc = pci_request_selected_regions(pdev, request_mask, name);
++	if (rc)
++		return rc;
++
++	rc = pcim_iomap_regions(pdev, mask, name);
++	if (rc)
++		pci_release_selected_regions(pdev, request_mask);
++	return rc;
++}
++EXPORT_SYMBOL(pcim_iomap_regions_request_all);
++
++/**
+  * pcim_iounmap_regions - Unmap and release PCI BARs
+  * @pdev: PCI device to map IO resources for
+  * @mask: Mask of BARs to unmap and release
+diff --git a/mm/slub.c b/mm/slub.c
+index 96d63eb..ca71d5b 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -1536,9 +1536,15 @@ new_slab:
+ 	 * That is only possible if certain conditions are met that are being
+ 	 * checked when a slab is created.
+ 	 */
+-	if (!(gfpflags & __GFP_NORETRY) && (s->flags & __PAGE_ALLOC_FALLBACK))
+-		return kmalloc_large(s->objsize, gfpflags);
+-
++	if (!(gfpflags & __GFP_NORETRY) &&
++				(s->flags & __PAGE_ALLOC_FALLBACK)) {
++		if (gfpflags & __GFP_WAIT)
++			local_irq_enable();
++		object = kmalloc_large(s->objsize, gfpflags);
++		if (gfpflags & __GFP_WAIT)
++			local_irq_disable();
++		return object;
++	}
+ 	return NULL;
+ debug:
+ 	if (!alloc_debug_processing(s, c->page, object, addr))
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 09cb3a7..2654c14 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -1621,7 +1621,7 @@ static void sock_def_readable(struct sock *sk, int len)
+ {
+ 	read_lock(&sk->sk_callback_lock);
+ 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+-		wake_up_interruptible(sk->sk_sleep);
++		wake_up_interruptible_sync(sk->sk_sleep);
+ 	sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+@@ -1635,7 +1635,7 @@ static void sock_def_write_space(struct sock *sk)
+ 	 */
+ 	if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
+ 		if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+-			wake_up_interruptible(sk->sk_sleep);
++			wake_up_interruptible_sync(sk->sk_sleep);
+ 
+ 		/* Should agree with poll, otherwise some programs break */
+ 		if (sock_writeable(sk))
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 4bf4807..41a049f 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -800,7 +800,8 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
+ 	mutex_unlock(&newsbsec->lock);
+ }
+ 
+-int selinux_parse_opts_str(char *options, struct security_mnt_opts *opts)
++static int selinux_parse_opts_str(char *options,
++				  struct security_mnt_opts *opts)
+ {
+ 	char *p;
+ 	char *context = NULL, *defcontext = NULL;

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Thu Mar 20 11:32:14 2008
@@ -1,4 +1,4 @@
-+ bugfix/all/patch-2.6.25-rc6-git1
++ bugfix/all/patch-2.6.25-rc6-git3
 + debian/version.patch
 + debian/kernelvariables.patch
 + debian/doc-build-parallel.patch



More information about the Kernel-svn-changes mailing list