kfree(reply); return -EINVAL; 
rcode = -EINVAL; goto cleanup; 
static int i2o_cfg_passthru(unsigned long arg){	struct i2o_cmd_passthru __user *cmd =	    (struct i2o_cmd_passthru __user *)arg;	struct i2o_controller *c;	u32 __user *user_msg;	u32 *reply = NULL;	u32 __user *user_reply = NULL;	u32 size = 0;	u32 reply_size = 0;	u32 rcode = 0;	void *sg_list[SG_TABLESIZE];	u32 sg_offset = 0;	u32 sg_count = 0;	int sg_index = 0;	u32 i = 0;	void *p = NULL;	i2o_status_block *sb;	struct i2o_message __iomem *msg;	u32 m;	unsigned int iop;	if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))		return -EFAULT;	c = i2o_find_iop(iop);	if (!c) {		osm_warn("controller %d not found\n", iop);		return -ENXIO;	}	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);	sb = c->status_block.virt;	if (get_user(size, &user_msg[0]))		return -EFAULT;	size = size >> 16;	if (size > sb->inbound_frame_size) {		osm_warn("size of message > inbound_frame_size");		return -EFAULT;	}	user_reply = &user_msg[size];	size <<= 2;		// Convert to bytes	/* Copy in the user's I2O command */	if (copy_from_user(msg, user_msg, size))		return -EFAULT;	if (get_user(reply_size, &user_reply[0]) < 0)		return -EFAULT;	reply_size >>= 16;	reply_size <<= 2;	reply = kmalloc(reply_size, GFP_KERNEL);	if (!reply) {		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",		       c->name);		return -ENOMEM;	}	memset(reply, 0, reply_size);	sg_offset = (msg->u.head[0] >> 4) & 0x0f;	writel(i2o_config_driver.context, &msg->u.s.icntxt);	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);	if (sg_offset) {		struct sg_simple_element *sg;		if (sg_offset * 4 >= size) {			rcode = -EFAULT;			goto cleanup;		}		// TODO 64bit fix		sg = (struct sg_simple_element *)((&msg->u.head[0]) +						  sg_offset);		sg_count =		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);		if (sg_count > SG_TABLESIZE) {			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",			       c->name, sg_count);			kfree(reply);			return -EINVAL;		}		for (i = 0; i < sg_count; i++) {			int sg_size;			if (!(sg[i].flag_count & 0x10000000			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {				printk(KERN_DEBUG				       "%s:Bad SG element %d - not simple (%x)\n",				       c->name, i, sg[i].flag_count);				rcode = -EINVAL;				goto cleanup;			}			sg_size = sg[i].flag_count & 0xffffff;			/* Allocate memory for the transfer */			p = kmalloc(sg_size, GFP_KERNEL);			if (!p) {				printk(KERN_DEBUG				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",				       c->name, sg_size, i, sg_count);				rcode = -ENOMEM;				goto cleanup;			}			sg_list[sg_index++] = p;	// sglist indexed with input frame, not our internal frame.			/* Copy in the user's SG buffer if necessary */			if (sg[i].			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {				// TODO 64bit fix				if (copy_from_user				    (p, (void __user *)sg[i].addr_bus,				     sg_size)) {					printk(KERN_DEBUG					       "%s: Could not copy SG buf %d FROM user\n",					       c->name, i);					rcode = -EFAULT;					goto cleanup;				}			}			//TODO 64bit fix			sg[i].addr_bus = virt_to_bus(p);		}	}	rcode = i2o_msg_post_wait(c, m, 60);	if (rcode)		goto cleanup;	if (sg_offset) {		u32 msg[128];		/* Copy back the Scatter Gather buffers back to user space */		u32 j;		// TODO 64bit fix		struct sg_simple_element *sg;		int sg_size;		// re-acquire the original message to handle correctly the sg copy operation		memset(&msg, 0, MSG_FRAME_SIZE * 4);		// get user msg size in u32s		if (get_user(size, &user_msg[0])) {			rcode = -EFAULT;			goto cleanup;		}		size = size >> 16;		size *= 4;		/* Copy in the user's I2O command */		if (copy_from_user(msg, user_msg, size)) {			rcode = -EFAULT;			goto cleanup;		}		sg_count =		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);		// TODO 64bit fix		sg = (struct sg_simple_element *)(msg + sg_offset);		for (j = 0; j < sg_count; j++) {			/* Copy out the SG list to user's buffer if necessary */			if (!			    (sg[j].			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {				sg_size = sg[j].flag_count & 0xffffff;				// TODO 64bit fix				if (copy_to_user				    ((void __user *)sg[j].addr_bus, sg_list[j],				     sg_size)) {					printk(KERN_WARNING					       "%s: Could not copy %p TO user %x\n",					       c->name, sg_list[j],					       sg[j].addr_bus);					rcode = -EFAULT;					goto cleanup;				}			}		}	}	/* Copy back the reply to user space */	if (reply_size) {		// we wrote our own values for context - now restore the user supplied ones		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {			printk(KERN_WARNING			       "%s: Could not copy message context FROM user\n",			       c->name);			rcode = -EFAULT;		}		if (copy_to_user(user_reply, reply, reply_size)) {			printk(KERN_WARNING			       "%s: Could not copy reply TO user\n", c->name);			rcode = -EFAULT;		}	}      cleanup:	kfree(reply);	return rcode;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/61fbfa8129c1771061a0e9f47747854293081c5b/i2o_config.c/clean/drivers/message/i2o/i2o_config.c