patch-2.3.99-pre3 linux/drivers/char/atixlmouse.c

Next file: linux/drivers/char/bttv.c
Previous file: linux/drivers/char/applicom.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre2/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c
@@ -92,10 +92,14 @@
 
 static int open_mouse(struct inode * inode, struct file * file)
 {
+	/* Lock module as request_irq may sleep */
+	MOD_INC_USE_COUNT;
 	if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL))
+	{
+		MOD_DEC_USE_COUNT;
 		return -EBUSY;
+	}
 	ATIXL_MSE_INT_ON(); /* Interrupts are really enabled here */
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -107,7 +111,13 @@
 {
 	unsigned char a,b,c;
 
-	if (check_region(ATIXL_MSE_DATA_PORT, 3))
+	/*
+	 *	We must request the resource and claim it atomically
+	 *	nowdays. We can throw it away on error. Otherwise we
+	 *	may race another module load of the same I/O
+	 */
+
+	if (!request_region(ATIXL_MSE_DATA_PORT, 3, "atixlmouse"))
 		return -EIO;
 
 	a = inb( ATIXL_MSE_SIGNATURE_PORT );	/* Get signature */
@@ -116,16 +126,20 @@
 	if (( a != b ) && ( a == c ))
 		printk(KERN_INFO "\nATI Inport ");
 	else
+	{
+		release_region(ATIXL_MSE_DATA_PORT,3);
 		return -EIO;
+	}
 	outb(0x80, ATIXL_MSE_CONTROL_PORT);	/* Reset the Inport device */
 	outb(0x07, ATIXL_MSE_CONTROL_PORT);	/* Select Internal Register 7 */
 	outb(0x0a, ATIXL_MSE_DATA_PORT);	/* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */
 
-	request_region(ATIXL_MSE_DATA_PORT, 3, "atixl");
-
 	msedev = register_busmouse(&atixlmouse);
 	if (msedev < 0)
+	{
 		printk("Bus mouse initialisation error.\n");
+		release_region(ATIXL_MSE_DATA_PORT,3);	/* Was missing */
+	}
 	else
 		printk("Bus mouse detected and installed.\n");
 	return msedev < 0 ? msedev : 0;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)