patch-2.3.35 linux/drivers/sbus/char/openprom.c

Next file: linux/drivers/sbus/char/pcikbd.c
Previous file: linux/drivers/sbus/char/jsflash.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
@@ -31,6 +31,7 @@
 
 #define PROMLIB_INTERNAL
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -43,7 +44,10 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/openpromio.h>
-
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#include <asm/pbm.h>
+#endif
 
 /* Private data kept by the driver for each descriptor. */
 typedef struct openprom_private_data
@@ -71,9 +75,15 @@
 
 	get_user_ret(bufsize, &info->oprom_size, -EFAULT);
 
-	if (bufsize == 0 || bufsize > OPROMMAXPARAM)
+	if (bufsize == 0)
 		return -EINVAL;
 
+	/* If the bufsize is too large, just limit it.
+	 * Fix from Jason Rappleye.
+	 */
+	if (bufsize > OPROMMAXPARAM)
+		bufsize = OPROMMAXPARAM;
+
 	if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
 		return -ENOMEM;
 	memset(*opp_p, 0, sizeof(int) + bufsize + 1);
@@ -138,6 +148,7 @@
 	unsigned long flags;
 	int bufsize, len, error = 0;
 	extern char saved_command_line[];
+	static int cnt;
 
 	if (cmd == OPROMSETOPT)
 		bufsize = getstrings((void *)arg, &opp);
@@ -194,20 +205,18 @@
 		buf = opp->oprom_array + strlen(opp->oprom_array) + 1;
 		len = opp->oprom_array + bufsize - buf;
 
-		printk(KERN_DEBUG "OPROMSETOPT%s %s='%s'\n",
-		       (cmd == OPROMSETOPT) ? "" : "2", opp->oprom_array, buf);
-
 		save_and_cli(flags);
 		error = prom_setprop(options_node, opp->oprom_array,
 				     buf, len);
 		restore_flags(flags);
 
-		if (error <= 0)
+		if (error < 0)
 			error = -EINVAL;
 		break;
 
 	case OPROMNEXT:
 	case OPROMCHILD:
+	case OPROMSETCUR:
 		if (bufsize < sizeof(int)) {
 			error = -EINVAL;
 			break;
@@ -216,10 +225,11 @@
 		node = *((int *) opp->oprom_array);
 
 		save_and_cli(flags);
-		if (cmd == OPROMNEXT)
-			node = __prom_getsibling(node);
-		else
-			node = __prom_getchild(node);
+		switch (cmd) {
+		case OPROMNEXT: node = __prom_getsibling(node); break;
+		case OPROMCHILD: node = __prom_getchild(node); break;
+		case OPROMSETCUR: break;
+		}
 		restore_flags(flags);
 
 		data->current_node = node;
@@ -229,6 +239,39 @@
 		error = copyout((void *)arg, opp, bufsize + sizeof(int));
 		break;
 
+	case OPROMPCI2NODE:
+		error = -EINVAL;
+
+		if (bufsize >= 2*sizeof(int)) {
+#ifdef CONFIG_PCI
+			struct pci_dev *pdev;
+			struct pcidev_cookie *pcp;
+			pdev = pci_find_slot (((int *) opp->oprom_array)[0],
+					      ((int *) opp->oprom_array)[1]);
+
+			pcp = pdev->sysdata;
+			if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) {
+				node = pcp->prom_node;
+				data->current_node = node;
+				*((int *)opp->oprom_array) = node;
+				opp->oprom_size = sizeof(int);
+				error = copyout((void *)arg, opp, bufsize + sizeof(int));
+			}
+#endif
+		}
+		break;
+
+	case OPROMPATH2NODE:
+		save_and_cli(flags);
+		node = prom_finddevice(opp->oprom_array);
+		restore_flags(flags);
+		data->current_node = node;
+		*((int *)opp->oprom_array) = node;
+		opp->oprom_size = sizeof(int);
+
+		error = copyout((void *)arg, opp, bufsize + sizeof(int));
+		break;
+
 	case OPROMGETBOOTARGS:
 		buf = saved_command_line;
 
@@ -248,11 +291,13 @@
 	case OPROMU2P:
 	case OPROMGETCONS:
 	case OPROMGETFBNAME:
-		printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n");
+		if (cnt++ < 10)
+			printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n");
 		error = -EINVAL;
 		break;
 	default:
-		printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
+		if (cnt++ < 10)
+			printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
 		error = -EINVAL;
 		break;
 	}
@@ -315,6 +360,7 @@
 	int error, node, len;
 	char *str, *tmp;
 	char buffer[64];
+	static int cnt;
 
 	switch (cmd) {
 	case OPIOCGET:
@@ -459,7 +505,8 @@
 		return 0;
 
 	default:
-		printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
+		if (cnt++ < 10)
+			printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
 		return -EINVAL;
 
 	}
@@ -473,6 +520,7 @@
 			  unsigned int cmd, unsigned long arg)
 {
 	DATA *data = (DATA *) file->private_data;
+	static int cnt;
 
 	switch (cmd) {
 	case OPROMGETOPT:
@@ -502,6 +550,9 @@
 	case OPROMGETCONS:
 	case OPROMGETFBNAME:
 	case OPROMGETBOOTARGS:
+	case OPROMSETCUR:
+	case OPROMPCI2NODE:
+	case OPROMPATH2NODE:
 		if ((file->f_mode & FMODE_READ) == 0)
 			return -EPERM;
 		return openprom_sunos_ioctl(inode, file, cmd, arg, 0);
@@ -521,7 +572,8 @@
 		return openprom_bsd_ioctl(inode,file,cmd,arg);
 
 	default:
-		printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
+		if (cnt++ < 10)
+			printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
 		return -EINVAL;
 	}
 }

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