if (length > sizeof (struct ib_mad)) { ret = -EINVAL; goto err_ah; } 
static ssize_t ib_umad_write(struct file *filp, const char __user *buf,			     size_t count, loff_t *pos){	struct ib_umad_file *file = filp->private_data;	struct ib_umad_packet *packet;	struct ib_mad_agent *agent;	struct ib_ah_attr ah_attr;	struct ib_ah *ah;	struct ib_rmpp_mad *rmpp_mad;	u8 method;	__be64 *tid;	int ret, length, hdr_len, rmpp_hdr_size;	int rmpp_active = 0;	if (count < sizeof (struct ib_user_mad))		return -EINVAL;	length = count - sizeof (struct ib_user_mad);	packet = kmalloc(sizeof *packet + sizeof(struct ib_mad_hdr) +			 sizeof (struct ib_rmpp_hdr), GFP_KERNEL);	if (!packet)		return -ENOMEM;	if (copy_from_user(&packet->mad, buf,			    sizeof (struct ib_user_mad) +			    sizeof (struct ib_mad_hdr) +			    sizeof (struct ib_rmpp_hdr))) {		ret = -EFAULT;		goto err;	}	if (packet->mad.hdr.id < 0 ||	    packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {		ret = -EINVAL;		goto err;	}	packet->length = length;	down_read(&file->agent_mutex);	agent = file->agent[packet->mad.hdr.id];	if (!agent) {		ret = -EINVAL;		goto err_up;	}	memset(&ah_attr, 0, sizeof ah_attr);	ah_attr.dlid          = be16_to_cpu(packet->mad.hdr.lid);	ah_attr.sl            = packet->mad.hdr.sl;	ah_attr.src_path_bits = packet->mad.hdr.path_bits;	ah_attr.port_num      = file->port->port_num;	if (packet->mad.hdr.grh_present) {		ah_attr.ah_flags = IB_AH_GRH;		memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);		ah_attr.grh.flow_label 	   = be32_to_cpu(packet->mad.hdr.flow_label);		ah_attr.grh.hop_limit  	   = packet->mad.hdr.hop_limit;		ah_attr.grh.traffic_class  = packet->mad.hdr.traffic_class;	}	ah = ib_create_ah(agent->qp->pd, &ah_attr);	if (IS_ERR(ah)) {		ret = PTR_ERR(ah);		goto err_up;	}	rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data;	if (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE) {		/* RMPP active */		if (!agent->rmpp_version) {			ret = -EINVAL;			goto err_ah;		}		/* Validate that the management class can support RMPP */		if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {			hdr_len = IB_MGMT_SA_HDR;		} else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&			    (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {				hdr_len = IB_MGMT_VENDOR_HDR;		} else {			ret = -EINVAL;			goto err_ah;		}		rmpp_active = 1;	} else {		if (length > sizeof (struct ib_mad)) {			ret = -EINVAL;			goto err_ah;		}		hdr_len = IB_MGMT_MAD_HDR;	}	packet->msg = ib_create_send_mad(agent,					 be32_to_cpu(packet->mad.hdr.qpn),					 0, rmpp_active,					 hdr_len, length - hdr_len,					 GFP_KERNEL);	if (IS_ERR(packet->msg)) {		ret = PTR_ERR(packet->msg);		goto err_ah;	}	packet->msg->ah 	= ah;	packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;	packet->msg->retries 	= packet->mad.hdr.retries;	packet->msg->context[0] = packet;	if (!rmpp_active) {		/* Copy message from user into send buffer */		if (copy_from_user(packet->msg->mad,				   buf + sizeof (struct ib_user_mad), length)) {			ret = -EFAULT;			goto err_msg;		}	} else {		rmpp_hdr_size = sizeof (struct ib_mad_hdr) +				sizeof (struct ib_rmpp_hdr);		/* Only copy MAD headers (RMPP header in place) */		memcpy(packet->msg->mad, packet->mad.data,		       sizeof (struct ib_mad_hdr));		/* Now, copy rest of message from user into send buffer */		if (copy_from_user(((struct ib_rmpp_mad *) packet->msg->mad)->data,				   buf + sizeof (struct ib_user_mad) + rmpp_hdr_size,				   length - rmpp_hdr_size)) {			ret = -EFAULT;			goto err_msg;		}	}	/*	 * If userspace is generating a request that will generate a	 * response, we need to make sure the high-order part of the	 * transaction ID matches the agent being used to send the	 * MAD.	 */	method = ((struct ib_mad_hdr *) packet->msg->mad)->method;	if (!(method & IB_MGMT_METHOD_RESP)       &&	    method != IB_MGMT_METHOD_TRAP_REPRESS &&	    method != IB_MGMT_METHOD_SEND) {		tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;		*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |				   (be64_to_cpup(tid) & 0xffffffff));	}	ret = ib_post_send_mad(packet->msg, NULL);	if (ret)		goto err_msg;	up_read(&file->agent_mutex);	return sizeof (struct ib_user_mad_hdr) + packet->length;err_msg:	ib_free_send_mad(packet->msg);err_ah:	ib_destroy_ah(ah);err_up:	up_read(&file->agent_mutex);err:	kfree(packet);	return ret;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/cb0f0910f4b41772a6771bdb4fb2d419b27bcd77/user_mad.c/clean/drivers/infiniband/core/user_mad.c