## Automatically generated incremental diff
## From:   linux-2.4.21-bk22
## To:     linux-2.4.21-bk23
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.4.21-bk22/Makefile linux-2.4.21-bk23/Makefile
--- linux-2.4.21-bk22/Makefile	2003-07-31 02:53:47.000000000 -0700
+++ linux-2.4.21-bk23/Makefile	2003-07-31 02:53:53.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 21
-EXTRAVERSION = -bk22
+EXTRAVERSION = -bk23
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.21-bk22/arch/ppc/kernel/ppc_ksyms.c linux-2.4.21-bk23/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.4.21-bk22/arch/ppc/kernel/ppc_ksyms.c	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.21-bk23/arch/ppc/kernel/ppc_ksyms.c	2003-07-31 02:53:53.000000000 -0700
@@ -353,6 +353,10 @@
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
 EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
+#ifdef CONFIG_SMP
+extern int *hash_table_lock;
+EXPORT_SYMBOL_NOVERS(hash_table_lock); /* For MOL */
+#endif
 EXPORT_SYMBOL_NOVERS(disarm_decr);
 #ifdef CONFIG_PPC_STD_MMU
 EXPORT_SYMBOL(flush_hash_page); /* For MOL */
diff -urN linux-2.4.21-bk22/drivers/acpi/system.c linux-2.4.21-bk23/drivers/acpi/system.c
--- linux-2.4.21-bk22/drivers/acpi/system.c	2003-07-31 02:53:49.000000000 -0700
+++ linux-2.4.21-bk23/drivers/acpi/system.c	2003-07-31 02:53:54.000000000 -0700
@@ -90,9 +90,7 @@
 static void
 acpi_power_off (void)
 {
-	acpi_enter_sleep_state_prep(ACPI_STATE_S5);
-	ACPI_DISABLE_IRQS();
-	acpi_enter_sleep_state(ACPI_STATE_S5);
+	acpi_suspend(ACPI_STATE_S5);
 }
 
 #endif /*CONFIG_PM*/
@@ -180,7 +178,7 @@
 			return AE_ERROR;
 	}
 
-	if (state < ACPI_STATE_S5) {
+	if (state <= ACPI_STATE_S5) {
 		/* Tell devices to stop I/O and actually save their state.
 		 * It is theoretically possible that something could fail,
 		 * so handle that gracefully..
diff -urN linux-2.4.21-bk22/drivers/char/ipmi/ipmi_kcs_intf.c linux-2.4.21-bk23/drivers/char/ipmi/ipmi_kcs_intf.c
--- linux-2.4.21-bk22/drivers/char/ipmi/ipmi_kcs_intf.c	2003-07-31 02:53:49.000000000 -0700
+++ linux-2.4.21-bk23/drivers/char/ipmi/ipmi_kcs_intf.c	2003-07-31 02:53:54.000000000 -0700
@@ -1025,7 +1025,7 @@
 	return rv;
 }
 
-#ifdef CONFIG_ACPI
+#ifdef CONFIG_ACPI_INTERPRETER
 
 /* Retrieve the base physical address from ACPI tables.  Originally
    from Hewlett-Packard simple bmc.c, a GPL KCS driver. */
@@ -1085,7 +1085,7 @@
 	int		rv = 0;
 	int		pos = 0;
 	int		i = 0;
-#ifdef CONFIG_ACPI
+#ifdef CONFIG_ACPI_INTERPRETER
 	unsigned long	physaddr = 0;
 #endif
 
@@ -1115,7 +1115,7 @@
 	   (because they weren't already specified above). */
 
 	if (kcs_trydefaults) {
-#ifdef CONFIG_ACPI
+#ifdef CONFIG_ACPI_INTERPRETER
 		if ((physaddr = acpi_find_bmc())) {
 			if (!check_mem_region(physaddr, 2)) {
 				rv = init_one_kcs(0, 
diff -urN linux-2.4.21-bk22/drivers/video/matrox/matroxfb_DAC1064.c linux-2.4.21-bk23/drivers/video/matrox/matroxfb_DAC1064.c
--- linux-2.4.21-bk22/drivers/video/matrox/matroxfb_DAC1064.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk23/drivers/video/matrox/matroxfb_DAC1064.c	2003-07-31 02:53:55.000000000 -0700
@@ -1177,6 +1177,7 @@
 
 	DAC1064_restore_1(PMINFO2);
 	matroxfb_vgaHWrestore(PMINFO2);
+	ACCESS_FBINFO(crtc1.panpos) = -1;
 	for (i = 0; i < 6; i++)
 		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
 	DAC1064_restore_2(PMINFO p);
@@ -1203,6 +1204,7 @@
 	if (ACCESS_FBINFO(devflags.support32MB))
 		mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
 #endif
+	ACCESS_FBINFO(crtc1.panpos) = -1;
 	for (i = 0; i < 6; i++)
 		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
 	DAC1064_restore_2(PMINFO p);
diff -urN linux-2.4.21-bk22/drivers/video/matrox/matroxfb_Ti3026.c linux-2.4.21-bk23/drivers/video/matrox/matroxfb_Ti3026.c
--- linux-2.4.21-bk22/drivers/video/matrox/matroxfb_Ti3026.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk23/drivers/video/matrox/matroxfb_Ti3026.c	2003-07-31 02:53:55.000000000 -0700
@@ -716,6 +716,7 @@
 
 	CRITBEGIN
 
+	ACCESS_FBINFO(crtc1.panpos) = -1;
 	for (i = 0; i < 6; i++)
 		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
 
diff -urN linux-2.4.21-bk22/drivers/video/matrox/matroxfb_base.c linux-2.4.21-bk23/drivers/video/matrox/matroxfb_base.c
--- linux-2.4.21-bk22/drivers/video/matrox/matroxfb_base.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk23/drivers/video/matrox/matroxfb_base.c	2003-07-31 02:53:55.000000000 -0700
@@ -152,6 +152,165 @@
 
 /* --------------------------------------------------------------------- */
 
+static void matroxfb_crtc1_panpos(WPMINFO2) {
+	if (ACCESS_FBINFO(crtc1.panpos) >= 0) {
+		unsigned long flags;
+		int panpos;
+		
+		matroxfb_DAC_lock_irqsave(flags);
+		panpos = ACCESS_FBINFO(crtc1.panpos);
+		if (panpos >= 0) {
+			unsigned int extvga_reg;
+			
+			ACCESS_FBINFO(crtc1.panpos) = -1; /* No update pending anymore */
+			extvga_reg = mga_inb(M_EXTVGA_INDEX);
+			mga_setr(M_EXTVGA_INDEX, 0x00, panpos);
+			if (extvga_reg != 0x00) {
+				mga_outb(M_EXTVGA_INDEX, extvga_reg);
+			}
+		}
+		matroxfb_DAC_unlock_irqrestore(flags);
+	}
+}
+
+static void matrox_irq(int irq, void *dev_id, struct pt_regs *fp)
+{
+	u_int32_t status;
+	int handled = 0;
+
+	MINFO_FROM(dev_id);
+
+	status = mga_inl(M_STATUS);
+
+	if (status & 0x20) {
+		mga_outl(M_ICLEAR, 0x20);
+		ACCESS_FBINFO(crtc1.vsync.cnt)++;
+		matroxfb_crtc1_panpos(PMINFO2);
+		wake_up_interruptible(&ACCESS_FBINFO(crtc1.vsync.wait));
+		handled = 1;
+	}
+	if (status & 0x200) {
+		mga_outl(M_ICLEAR, 0x200);
+		ACCESS_FBINFO(crtc2.vsync.cnt)++;
+		wake_up_interruptible(&ACCESS_FBINFO(crtc2.vsync.wait));
+		handled = 1;
+	}
+	return;
+}
+
+int matroxfb_enable_irq(WPMINFO int reenable) {
+	u_int32_t bm;
+	
+	if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
+		bm = 0x220;
+	else
+		bm = 0x020;
+
+	if (!test_and_set_bit(0, &ACCESS_FBINFO(irq_flags))) {
+		if (request_irq(ACCESS_FBINFO(pcidev)->irq, matrox_irq,
+				SA_SHIRQ, "matroxfb", MINFO)) {
+			clear_bit(0, &ACCESS_FBINFO(irq_flags));
+			return -EINVAL;
+		}
+		/* Clear any pending field interrupts */
+		mga_outl(M_ICLEAR, bm);
+		mga_outl(M_IEN, mga_inl(M_IEN) | bm);
+	} else if (reenable) {
+		u_int32_t ien;
+		
+		ien = mga_inl(M_IEN);
+		if ((ien & bm) != bm) {
+			printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
+			mga_outl(M_IEN, ien | bm);
+		}
+	}
+	return 0;
+}
+
+static void matroxfb_disable_irq(WPMINFO2) {
+	if (test_and_clear_bit(0, &ACCESS_FBINFO(irq_flags))) {
+		/* Flush pending pan-at-vbl request... */
+		matroxfb_crtc1_panpos(PMINFO2);
+		if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
+			mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220);
+		else
+			mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20);
+		free_irq(ACCESS_FBINFO(pcidev)->irq, MINFO);
+	}
+}
+
+#ifndef wait_event_interruptible_timeout
+#define __wait_event_interruptible_timeout(wq, condition, ret)		\
+do {									\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
+									\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		set_current_state(TASK_INTERRUPTIBLE);			\
+		if (condition)						\
+			break;						\
+		if (!signal_pending(current)) {				\
+			ret = schedule_timeout(ret);			\
+			if (!ret)					\
+				break;					\
+			continue;					\
+		}							\
+		ret = -ERESTARTSYS;					\
+		break;							\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout)	\
+({									\
+	long __ret = timeout;						\
+	if (!(condition))						\
+		__wait_event_interruptible_timeout(wq, condition, __ret); \
+	__ret;								\
+})
+#endif
+
+int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
+	wait_queue_t __wait;
+	struct matrox_vsync *vs;
+	unsigned int cnt;
+	int ret;
+
+	switch (crtc) {
+		case 0:
+			vs = &ACCESS_FBINFO(crtc1.vsync);
+			break;
+		case 1:
+			if (ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG400) {
+				return -ENODEV;
+			}
+			vs = &ACCESS_FBINFO(crtc2.vsync);
+			break;
+		default:
+			return -ENODEV;
+	}
+	ret = matroxfb_enable_irq(PMINFO 0);
+	if (ret) {
+		return ret;
+	}
+        init_waitqueue_entry(&__wait, current);
+
+	cnt = vs->cnt;
+	ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
+	if (ret < 0) {
+		return ret;
+	}
+	if (ret == 0) {
+		matroxfb_enable_irq(PMINFO 1);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
 static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
 	unsigned int pos;
 	unsigned short p0, p1, p2;
@@ -159,6 +318,8 @@
 	unsigned int p3;
 #endif
 	struct display *disp;
+	int vbl;
+	unsigned long flags;
 	CRITFLAGS
 
 	DBG("matrox_pan_var")
@@ -180,15 +341,27 @@
 	p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21;
 #endif
 
+	/* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */
+	vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(PMINFO 0) == 0);
+
 	CRITBEGIN
 
+	matroxfb_DAC_lock_irqsave(flags);
+
 	mga_setr(M_CRTC_INDEX, 0x0D, p0);
 	mga_setr(M_CRTC_INDEX, 0x0C, p1);
 #ifdef CONFIG_FB_MATROX_32MB
 	if (ACCESS_FBINFO(devflags.support32MB))
 		mga_setr(M_EXTVGA_INDEX, 0x08, p3);
 #endif
-	mga_setr(M_EXTVGA_INDEX, 0x00, p2);
+	if (vbl) {
+		ACCESS_FBINFO(crtc1.panpos) = p2;
+	} else {
+		/* Abort any pending change */
+		ACCESS_FBINFO(crtc1.panpos) = -1;
+		mga_setr(M_EXTVGA_INDEX, 0x00, p2);
+	}
+	matroxfb_DAC_unlock_irqrestore(flags);
 
 	CRITEND
 }
@@ -231,53 +404,61 @@
 
 static int matroxfb_open(struct fb_info *info, int user)
 {
-#define minfo (list_entry(info, struct matrox_fb_info, fbcon))
-	DBG_LOOP("matroxfb_open")
-
-	if (ACCESS_FBINFO(dead)) {
-		return -ENXIO;
+	MINFO_FROM_INFO(info);
+	
+	DBG_LOOP(__FUNCTION__)
+ 
+ 	if (ACCESS_FBINFO(dead)) {
+ 		return -ENXIO;
+ 	}
+ 	ACCESS_FBINFO(usecount)++;
+	if (user) {
+		ACCESS_FBINFO(userusecount)++;
 	}
-	ACCESS_FBINFO(usecount)++;
-#undef minfo
-	return(0);
+	return 0;
 }
 
 static int matroxfb_release(struct fb_info *info, int user)
 {
-#define minfo (list_entry(info, struct matrox_fb_info, fbcon))
-	DBG_LOOP("matroxfb_release")
-
+	MINFO_FROM_INFO(info);
+	
+	DBG_LOOP(__FUNCTION__)
+
+	if (user) {
+		if (0 == --ACCESS_FBINFO(userusecount)) {
+			matroxfb_disable_irq(PMINFO2);
+		}
+	}
 	if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) {
 		matroxfb_remove(PMINFO 0);
 	}
-#undef minfo
-	return(0);
+	return 0;
 }
 
 static int matroxfb_pan_display(struct fb_var_screeninfo *var, int con,
 		struct fb_info* info) {
-#define minfo (list_entry(info, struct matrox_fb_info, fbcon))
-
+	struct display* dsp;
+	MINFO_FROM_INFO(info);
 	DBG("matroxfb_pan_display")
 
+	if (con < 0) {
+		dsp = info->disp;
+	} else {
+		dsp = fb_display + con;
+	}
 	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
-			return -EINVAL;
+		return -EINVAL;
 	} else {
-		if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
-		    var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+		if (var->xoffset+dsp->var.xres > dsp->var.xres_virtual ||
+		    var->yoffset+dsp->var.yres > dsp->var.yres_virtual)
 			return -EINVAL;
 	}
 	if (con == ACCESS_FBINFO(currcon))
 		matrox_pan_var(PMINFO var);
-	fb_display[con].var.xoffset = var->xoffset;
-	fb_display[con].var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-	else
-		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+	dsp->var.xoffset = var->xoffset;
+	dsp->var.yoffset = var->yoffset;
+	dsp->var.vmode &= ~FB_VMODE_YWRAP;
 	return 0;
-#undef minfo
 }
 
 static int matroxfb_updatevar(int con, struct fb_info *info)
@@ -963,10 +1144,11 @@
 #undef minfo
 }
 
-static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank)
+static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank)
 {
 	unsigned int sts1;
 
+	matroxfb_enable_irq(PMINFO 0);
 	memset(vblank, 0, sizeof(*vblank));
 	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC |
 			FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK;
@@ -981,8 +1163,12 @@
 		vblank->flags |= FB_VBLANK_VSYNCING;
 	if (vblank->vcount >= ACCESS_FBINFO(currcon_display)->var.yres)
 		vblank->flags |= FB_VBLANK_VBLANKING;
-	vblank->hcount = 0;
-	vblank->count = 0;
+	if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
+		vblank->flags |= FB_VBLANK_HAVE_COUNT;
+		/* Only one writer, aligned int value... 
+		   it should work without lock and without atomic_t */
+		vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt;
+	}
 	return 0;
 }
 
@@ -1015,6 +1201,15 @@
 					return -EFAULT;
 				return 0;
 			}
+		case FBIO_WAITFORVSYNC:
+			{
+				u_int32_t crt;
+
+				if (get_user(crt, (u_int32_t *)arg))
+					return -EFAULT;
+
+				return matroxfb_wait_for_sync(PMINFO crt);
+			}
 		case MATROXFB_SET_OUTPUT_MODE:
 			{
 				struct matroxioc_output_mode mom;
@@ -2230,6 +2425,10 @@
 	spin_lock_init(&ACCESS_FBINFO(lock.accel));
 	init_rwsem(&ACCESS_FBINFO(crtc2.lock));
 	init_rwsem(&ACCESS_FBINFO(altout.lock));
+	ACCESS_FBINFO(irq_flags) = 0;
+	init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait));
+	init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait));
+	ACCESS_FBINFO(crtc1.panpos) = -1;
 
 	err = initMatrox2(PMINFO d, b);
 	if (!err) {
@@ -2768,6 +2967,8 @@
 EXPORT_SYMBOL(matroxfb_register_driver);
 EXPORT_SYMBOL(matroxfb_unregister_driver);
 EXPORT_SYMBOL(matroxfb_switch);
+EXPORT_SYMBOL(matroxfb_wait_for_sync);
+EXPORT_SYMBOL(matroxfb_enable_irq);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -urN linux-2.4.21-bk22/drivers/video/matrox/matroxfb_base.h linux-2.4.21-bk23/drivers/video/matrox/matroxfb_base.h
--- linux-2.4.21-bk22/drivers/video/matrox/matroxfb_base.h	2003-07-31 02:53:50.000000000 -0700
+++ linux-2.4.21-bk23/drivers/video/matrox/matroxfb_base.h	2003-07-31 02:53:55.000000000 -0700
@@ -468,6 +468,11 @@
 struct matroxfb_driver;
 struct matroxfb_dh_fb_info;
 
+struct matrox_vsync {
+	wait_queue_head_t	wait;
+	unsigned int		cnt;
+};
+
 struct matrox_fb_info {
 	struct fb_info		fbcon;
 
@@ -476,6 +481,9 @@
 	int			dead;
 	unsigned int		usecount;
 
+	unsigned int		userusecount;
+	unsigned long		irq_flags;
+
 	struct matroxfb_par	curr;
 	struct matrox_hw_state	hw;
 
@@ -603,10 +611,13 @@
 			      } cursor;
 	struct matrox_bios	bios;
 	struct {
+		struct matrox_vsync	vsync;
+		int		panpos;
 		unsigned int	pixclock;
 		int		mnp;
 			      } crtc1;
 	struct {
+		struct matrox_vsync	vsync;
 		unsigned int 	pixclock;
 		int		mnp;
 	struct matroxfb_dh_fb_info*	info;
@@ -663,6 +674,8 @@
 #endif
 };
 
+#define info2minfo(info) list_entry(info, struct matrox_fb_info, fbcon)
+
 #ifdef CONFIG_FB_MATROX_MULTIHEAD
 #define ACCESS_FBINFO2(info, x) (info->x)
 #define ACCESS_FBINFO(x) ACCESS_FBINFO2(minfo,x)
@@ -677,12 +690,11 @@
 #define PMINFO   PMINFO2 ,
 
 static inline struct matrox_fb_info* mxinfo(const struct display* p) {
-	return list_entry(p->fb_info, struct matrox_fb_info, fbcon);
+	return info2minfo(p->fb_info);
 }
 
 #define PMXINFO(p)	   mxinfo(p),
 #define MINFO_FROM(x)	   struct matrox_fb_info* minfo = x
-#define MINFO_FROM_DISP(x) MINFO_FROM(mxinfo(x))
 
 #else
 
@@ -700,18 +712,14 @@
 #define PMINFO2
 #define PMINFO
 
-#if 0
-static inline struct matrox_fb_info* mxinfo(const struct display* p) {
-	return &matroxfb_global_mxinfo;
-}
-#endif
-
 #define PMXINFO(p)
 #define MINFO_FROM(x)
-#define MINFO_FROM_DISP(x)
 
 #endif
 
+#define MINFO_FROM_DISP(x) MINFO_FROM(mxinfo(x))
+#define MINFO_FROM_INFO(x) MINFO_FROM(info2minfo(x))
+
 struct matrox_switch {
 	int	(*preinit)(WPMINFO2);
 	void	(*reset)(WPMINFO2);
@@ -793,7 +801,7 @@
 
 #define M_FIFOSTATUS	0x1E10
 #define M_STATUS	0x1E14
-
+#define M_ICLEAR	0x1E18
 #define M_IEN		0x1E1C
 
 #define M_VCOUNT	0x1E20
@@ -916,6 +924,8 @@
 extern struct list_head matroxfb_list;
 extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
 extern int matroxfb_switch(int con, struct fb_info *);
+extern int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc);
+extern int matroxfb_enable_irq(WPMINFO int reenable);
 
 #ifdef MATROXFB_USE_SPINLOCKS
 #define CRITBEGIN  spin_lock_irqsave(&ACCESS_FBINFO(lock.accel), critflags);
diff -urN linux-2.4.21-bk22/drivers/video/matrox/matroxfb_crtc2.c linux-2.4.21-bk23/drivers/video/matrox/matroxfb_crtc2.c
--- linux-2.4.21-bk22/drivers/video/matrox/matroxfb_crtc2.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk23/drivers/video/matrox/matroxfb_crtc2.c	2003-07-31 02:53:55.000000000 -0700
@@ -193,7 +193,7 @@
 	{
 		u_int32_t tmp;
 
-		tmp = 0x0FFF0000;		/* line compare */
+		tmp = mt->VDisplay << 16;		/* line compare */
 		if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
 			tmp |= 0x00000100;
 		if (mt->sync & FB_SYNC_VERT_HIGH_ACT)
@@ -338,8 +338,14 @@
 	MINFO_FROM(m2info->primary_dev);
 
 	if (MINFO) {
-		if (ACCESS_FBINFO(dead)) {
-			return -ENXIO;
+		int err;
+
+ 		if (ACCESS_FBINFO(dead)) {
+ 			return -ENXIO;
+ 		}
+		err = ACCESS_FBINFO(fbcon.fbops)->fb_open(&ACCESS_FBINFO(fbcon), user);
+		if (err) {
+			return err;
 		}
 	}
 	return 0;
@@ -348,11 +354,13 @@
 
 static int matroxfb_dh_release(struct fb_info* info, int user) {
 #define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))
+	int err = 0;
 	MINFO_FROM(m2info->primary_dev);
 
 	if (MINFO) {
+		err = ACCESS_FBINFO(fbcon.fbops)->fb_release(&ACCESS_FBINFO(fbcon), user);
 	}
-	return 0;
+	return err;
 #undef m2info
 }
 
@@ -544,13 +552,19 @@
 static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, int con,
 		struct fb_info* info) {
 #define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))
-	if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
-	    var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+	struct display* dsp;
+
+	if (con < 0)
+		dsp = m2info->fbcon.disp;
+	else
+		dsp = fb_display + con;
+	if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||
+	    var->yoffset + dsp->var.yres > dsp->var.yres_virtual)
 		return -EINVAL;
 	if (con == m2info->currcon)
 		matroxfb_dh_pan_var(m2info, var);
-	fb_display[con].var.xoffset = var->xoffset;
-	fb_display[con].var.yoffset = var->yoffset;
+	dsp->var.xoffset = var->xoffset;
+	dsp->var.yoffset = var->yoffset;
 	return 0;
 #undef m2info
 }
@@ -560,6 +574,7 @@
 static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
 	MINFO_FROM(m2info->primary_dev);
 
+	matroxfb_enable_irq(PMINFO 0);
 	memset(vblank, 0, sizeof(*vblank));
 	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
 	/* mask out reserved bits + field number (odd/even) */
@@ -567,6 +582,12 @@
 	/* compatibility stuff */
 	if (vblank->vcount >= m2info->currcon_display->var.yres)
 		vblank->flags |= FB_VBLANK_VBLANKING;
+	if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
+		vblank->flags |= FB_VBLANK_HAVE_COUNT;
+		/* Only one writer, aligned int value...
+		   it should work without lock and without atomic_t */
+		vblank->count = ACCESS_FBINFO(crtc2).vsync.cnt;
+	}
 	return 0;
 }
 
@@ -594,6 +615,17 @@
 					return -EFAULT;
 				return 0;
 			}
+		case FBIO_WAITFORVSYNC:
+			{
+				u_int32_t crt;
+
+				if (get_user(crt, (u_int32_t *)arg))
+					return -EFAULT;
+
+				if (crt != 0)
+					return -ENODEV;
+				return matroxfb_wait_for_sync(PMINFO 1);
+			}
 		case MATROXFB_SET_OUTPUT_MODE:
 		case MATROXFB_GET_OUTPUT_MODE:
 		case MATROXFB_GET_ALL_OUTPUTS:
diff -urN linux-2.4.21-bk22/drivers/video/matrox/matroxfb_misc.c linux-2.4.21-bk23/drivers/video/matrox/matroxfb_misc.c
--- linux-2.4.21-bk22/drivers/video/matrox/matroxfb_misc.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk23/drivers/video/matrox/matroxfb_misc.c	2003-07-31 02:53:55.000000000 -0700
@@ -223,7 +223,7 @@
 
 int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) {
 	unsigned int hd, hs, he, hbe, ht;
-	unsigned int vd, vs, ve, vt;
+	unsigned int vd, vs, ve, vt, lc;
 	unsigned int wd;
 	unsigned int divider;
 	int i;
@@ -336,6 +336,7 @@
 	vs = m->VSyncStart - 1;
 	ve = m->VSyncEnd - 1;
 	vt = m->VTotal - 2;
+	lc = vd;
 	/* G200 cannot work with (ht & 7) == 6 */
 	if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
 		ht++;
@@ -367,7 +368,8 @@
 	hw->CRTCEXT[2] =  ((vt & 0xC00) >> 10) |
 			  ((vd & 0x400) >>  8) |	/* disp end */
 			  ((vd & 0xC00) >>  7) |	/* vblanking start */
-			  ((vs & 0xC00) >>  5);
+			  ((vs & 0xC00) >>  5) |
+			  ((lc & 0x400) >>  3);
 	if (text)
 		hw->CRTCEXT[3] = 0x00;
 	else
@@ -387,12 +389,13 @@
 		      ((vd & 0x100) >> 7) |
 		      ((vs & 0x100) >> 6) |
 		      ((vd & 0x100) >> 5) |
-		      0x10                |
+		      ((lc & 0x100) >> 4) |
 		      ((vt & 0x200) >> 4) |
 		      ((vd & 0x200) >> 3) |
 		      ((vs & 0x200) >> 2);
 	hw->CRTC[8] = 0x00;
-	hw->CRTC[9] = ((vd & 0x200) >> 4) | 0x40;
+	hw->CRTC[9] = ((vd & 0x200) >> 4) |
+		      ((lc & 0x200) >> 3);
 	if (text)
 		hw->CRTC[9] |= fontheight(p) - 1;
 	if (m->dblscan && !m->interlaced)
@@ -417,7 +420,7 @@
 			hw->CRTC[20] = 0x1F;
 	} else
 		hw->CRTC[23] = 0xC3;
-	hw->CRTC[24] = 0xFF;
+	hw->CRTC[24] = lc;
 	return 0;
 };
 
diff -urN linux-2.4.21-bk22/fs/coda/dir.c linux-2.4.21-bk23/fs/coda/dir.c
--- linux-2.4.21-bk22/fs/coda/dir.c	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.21-bk23/fs/coda/dir.c	2003-07-31 02:53:55.000000000 -0700
@@ -79,6 +79,7 @@
 };
 
 struct file_operations coda_dir_operations = {
+	llseek:		generic_file_llseek,
 	read:		generic_read_dir,
 	readdir:	coda_readdir,
 	open:		coda_open,
@@ -507,7 +508,11 @@
 		ret = coda_venus_readdir(host_file, filldir, dirent, coda_dentry);
 	} else {
 		/* potemkin case: we were handed a directory inode */
-		ret = vfs_readdir(host_file, filldir, dirent);
+		/* We can't call vfs_readdir because we are already holding
+		 * the inode semaphore. */
+		ret = -ENOENT;
+		if (!IS_DEADDIR(host_file->f_dentry->d_inode))
+			ret = host_file->f_op->readdir(host_file, filldir, dirent);
 	}
 
 	coda_file->f_pos = host_file->f_pos;
diff -urN linux-2.4.21-bk22/fs/coda/file.c linux-2.4.21-bk23/fs/coda/file.c
--- linux-2.4.21-bk22/fs/coda/file.c	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.21-bk23/fs/coda/file.c	2003-07-31 02:53:55.000000000 -0700
@@ -117,16 +117,18 @@
 	coda_vfs_stat.open++;
 
 	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
-	if (!cfi) {
-		unlock_kernel();
+	if (!cfi)
 		return -ENOMEM;
-	}
 
 	lock_kernel();
 
 	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
 			   &host_file); 
-	if (error || !host_file) {
+
+	if (!error && !host_file)
+		error = EBADF;
+
+	if (error) {
 		kfree(cfi);
 		unlock_kernel();
 		return error;
diff -urN linux-2.4.21-bk22/fs/namei.c linux-2.4.21-bk23/fs/namei.c
--- linux-2.4.21-bk22/fs/namei.c	2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.21-bk23/fs/namei.c	2003-07-31 02:53:55.000000000 -0700
@@ -627,6 +627,8 @@
 			nd->last_type = LAST_DOT;
 		else if (this.len == 2 && this.name[1] == '.')
 			nd->last_type = LAST_DOTDOT;
+		else
+			goto return_base;
 return_reval:
 		/*
 		 * We bypassed the ordinary revalidation routines.
diff -urN linux-2.4.21-bk22/include/linux/matroxfb.h linux-2.4.21-bk23/include/linux/matroxfb.h
--- linux-2.4.21-bk22/include/linux/matroxfb.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.21-bk23/include/linux/matroxfb.h	2003-07-31 02:53:56.000000000 -0700
@@ -76,5 +76,7 @@
 #define MATROXFB_G_TVOCTRL	_IOWR('V',27,struct matroxfb_control)
 #define MATROXFB_S_TVOCTRL	_IOW ('V',28,struct matroxfb_control)
 
+#define FBIO_WAITFORVSYNC	_IOW('F', 0x20, u_int32_t)
+
 #endif
 
diff -urN linux-2.4.21-bk22/include/linux/ncp.h linux-2.4.21-bk23/include/linux/ncp.h
--- linux-2.4.21-bk22/include/linux/ncp.h	2001-11-22 11:46:18.000000000 -0800
+++ linux-2.4.21-bk23/include/linux/ncp.h	2003-07-31 02:53:56.000000000 -0700
@@ -44,7 +44,7 @@
 };
 
 #define NCP_VOLNAME_LEN (16)
-#define NCP_NUMBER_OF_VOLUMES (64)
+#define NCP_NUMBER_OF_VOLUMES (256)
 struct ncp_volume_info {
 	__u32 total_blocks;
 	__u32 free_blocks;
