diff options
| -rw-r--r-- | linux-core/drm_crtc.c | 365 | 
1 files changed, 164 insertions, 201 deletions
| diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index ed5f1dfa..fcddc7d9 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -433,24 +433,31 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,  	 * on the DPLL.  	 */  	crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); +  	list_for_each_entry(output, &dev->mode_config.output_list, head) { -		if (output->crtc == crtc) { -			dev_warn(&output->dev->pdev->dev, "%s: set mode %s\n", -				output->name, mode->name); -			output->funcs->mode_set(output, mode, adjusted_mode); -		} + +		if (output->crtc != crtc) +			continue; +		 +		DRM_INFO("%s: set mode %s\n", output->name, mode->name); + +		output->funcs->mode_set(output, mode, adjusted_mode);  	}  	/* Now, enable the clocks, plane, pipe, and outputs that we set up. */  	crtc->funcs->commit(crtc); +  	list_for_each_entry(output, &dev->mode_config.output_list, head) { -		if (output->crtc == crtc) { -			output->funcs->commit(output); + +		if (output->crtc != crtc) +			continue; +		 +		output->funcs->commit(output); +  #if 0 // TODO def RANDR_12_INTERFACE -			if (output->randr_output) -				RRPostPendingProperties (output->randr_output); +		if (output->randr_output) +			RRPostPendingProperties (output->randr_output);  #endif -		}  	}  	/* XXX free adjustedmode */ @@ -762,7 +769,7 @@ out_err:   */  static void drm_pick_crtcs (struct drm_device *dev)  { -	int c, o; +	int c, o, assigned;  	struct drm_output *output, *output_equal;  	struct drm_crtc   *crtc;  	struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; @@ -802,11 +809,26 @@ static void drm_pick_crtcs (struct drm_device *dev)  		c = -1;  		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +			assigned = 0; +  			c++;  			if ((output->possible_crtcs & (1 << c)) == 0)  		    		continue; -#if 0 /* should we try and clone ?? - code not tested - FIXME */ +			list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { +				if (output->id == output_equal->id) +					continue; + +				/* Find out if crtc has been assigned before */ +				if (output_equal->crtc == crtc) +					assigned = 1; +			} + +#if 1 /* continue for now */ +			if (assigned) +				continue; +#endif +  			o = -1;  			list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {  				o++; @@ -816,7 +838,9 @@ static void drm_pick_crtcs (struct drm_device *dev)  				list_for_each_entry(modes, &output->modes, head) {  					list_for_each_entry(modes_equal, &output_equal->modes, head) {  						if (drm_mode_equal (modes, modes_equal)) { -							if ((output->possible_clones & (1 << o))) { +							if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) { +								printk("Cloning %s (0x%lx) to %s (0x%lx)\n",output->name,output->possible_clones,output_equal->name,output_equal->possible_clones); +								assigned = 0;  								goto clone;  							}  						} @@ -825,7 +849,10 @@ static void drm_pick_crtcs (struct drm_device *dev)  			}  clone: -#endif +			/* crtc has been assigned skip it */ +			if (assigned) +				continue; +  			/* Found a CRTC to attach to, do it ! */  			output->crtc = crtc;  			output->crtc->desired_mode = des_mode; @@ -856,6 +883,7 @@ clone:  bool drm_initial_config(struct drm_device *dev, bool can_grow)  {  	struct drm_output *output; +	struct drm_crtc *crtc;  	int ret = false;  	mutex_lock(&dev->mode_config.mutex); @@ -864,14 +892,31 @@ bool drm_initial_config(struct drm_device *dev, bool can_grow)  	drm_pick_crtcs(dev); +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + +		/* can't setup the crtc if there's no assigned mode */ +		if (!crtc->desired_mode) +			continue; + +		/* Now setup the fbdev for attached crtcs */ +		dev->driver->fb_probe(dev, crtc); +	} + +	/* This is a little screwy, as we've already walked the outputs  +	 * above, but it's a little bit of magic too. There's the potential +	 * for things not to get setup above if an existing device gets +	 * re-assigned thus confusing the hardware. By walking the outputs +	 * this fixes up their crtc's. +	 */  	list_for_each_entry(output, &dev->mode_config.output_list, head) { -		/* can't setup the output if there's no assigned crtc or mode */ +		/* can't setup the output if there's no assigned mode */  		if (!output->crtc || !output->crtc->desired_mode)  			continue; -		dev->driver->fb_probe(dev, output->crtc); +		drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0);  	} +  	drm_disable_unused_functions(dev);  	mutex_unlock(&dev->mode_config.mutex); @@ -1088,8 +1133,7 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modein  int drm_mode_getresources(struct drm_device *dev,  			  void *data, struct drm_file *file_priv)  { -	struct drm_mode_card_res __user *argp = (void __user *)data; -	struct drm_mode_card_res card_res; +	struct drm_mode_card_res *card_res = data;  	struct list_head *lh;  	struct drm_framebuffer *fb;  	struct drm_output *output; @@ -1122,12 +1166,7 @@ int drm_mode_getresources(struct drm_device *dev,  	list_for_each(lh, &dev->mode_config.usermode_list)  		mode_count++; -	if (copy_from_user(&card_res, argp, sizeof(card_res))) { -		ret = -EFAULT; -		goto out_unlock; -	} - -	if (card_res.count_modes == 0) { +	if (card_res->count_modes == 0) {  		DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height);  		drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);  		mode_count = 0; @@ -1141,78 +1180,58 @@ int drm_mode_getresources(struct drm_device *dev,  	/* handle this in 4 parts */  	/* FBs */ -	if (card_res.count_fbs >= fb_count) { +	if (card_res->count_fbs >= fb_count) {  		copied = 0;  		list_for_each_entry(fb, &dev->mode_config.fb_list, head) { -			if (put_user(fb->id, &card_res.fb_id[copied++])) { -				ret = -EFAULT; -				goto done; -			} +			card_res->fb_id[copied++] = fb->id;  		}  	} -	card_res.count_fbs = fb_count; +	card_res->count_fbs = fb_count;  	/* CRTCs */ -	if (card_res.count_crtcs >= crtc_count) { +	if (card_res->count_crtcs >= crtc_count) {  		copied = 0;  		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){  			DRM_DEBUG("CRTC ID is %d\n", crtc->id); -			if (put_user(crtc->id, &card_res.crtc_id[copied++])) { -				ret = -EFAULT; -				goto done; -			} +			card_res->crtc_id[copied++] = crtc->id;  		}  	} -	card_res.count_crtcs = crtc_count; +	card_res->count_crtcs = crtc_count;  	/* Outputs */ -	if (card_res.count_outputs >= output_count) { +	if (card_res->count_outputs >= output_count) {  		copied = 0;  		list_for_each_entry(output, &dev->mode_config.output_list,  				    head) {   			DRM_DEBUG("OUTPUT ID is %d\n", output->id); -			if (put_user(output->id, &card_res.output_id[copied++])) { -				ret = -EFAULT; -				goto done; -			} +			card_res->output_id[copied++] = output->id;  		}  	} -	card_res.count_outputs = output_count; +	card_res->count_outputs = output_count;  	/* Modes */ -	if (card_res.count_modes >= mode_count) { +	if (card_res->count_modes >= mode_count) {  		copied = 0;  		list_for_each_entry(output, &dev->mode_config.output_list,  				    head) {  			list_for_each_entry(mode, &output->modes, head) {  				drm_crtc_convert_to_umode(&u_mode, mode); -				if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { -					ret = -EFAULT; -					goto done; -				} +				card_res->modes[copied++] = u_mode;  			}  		}  		/* add in user modes */  		list_for_each_entry(mode, &dev->mode_config.usermode_list, head) {  			drm_crtc_convert_to_umode(&u_mode, mode); -			if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { -				ret = -EFAULT; -				goto done; -			} +			card_res->modes[copied++] = u_mode;  		}  	} -	card_res.count_modes = mode_count; +	card_res->count_modes = mode_count; -done: -	DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs, -		  card_res.count_outputs, -		  card_res.count_modes); +	DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, +		  card_res->count_outputs, +		  card_res->count_modes); -	if (copy_to_user(argp, &card_res, sizeof(card_res))) -		ret = -EFAULT; - -out_unlock:  	mutex_unlock(&dev->mode_config.mutex);  	return ret;  } @@ -1237,43 +1256,36 @@ out_unlock:  int drm_mode_getcrtc(struct drm_device *dev,  		     void *data, struct drm_file *file_priv)  { -	struct drm_mode_crtc __user *argp = (void __user *)data; -	struct drm_mode_crtc crtc_resp; +	struct drm_mode_crtc *crtc_resp = data;  	struct drm_crtc *crtc;  	struct drm_output *output;  	int ocount;  	int ret = 0; -	if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp))) -		return -EFAULT; -  	mutex_lock(&dev->mode_config.mutex); -	crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id); -	if (!crtc || (crtc->id != crtc_resp.crtc_id)) { +	crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp->crtc_id); +	if (!crtc || (crtc->id != crtc_resp->crtc_id)) {  		ret = -EINVAL;  		goto out;  	} -	crtc_resp.x = crtc->x; -	crtc_resp.y = crtc->y; -	crtc_resp.fb_id = 1; +	crtc_resp->x = crtc->x; +	crtc_resp->y = crtc->y; +	crtc_resp->fb_id = 1; -	crtc_resp.outputs = 0; +	crtc_resp->outputs = 0;  	if (crtc->enabled) { -		crtc_resp.mode = crtc->mode.mode_id; +		crtc_resp->mode = crtc->mode.mode_id;  		ocount = 0;  		list_for_each_entry(output, &dev->mode_config.output_list, head) {  			if (output->crtc == crtc) -				crtc_resp.outputs |= 1 << (ocount++); +				crtc_resp->outputs |= 1 << (ocount++);  		}  	} else { -		crtc_resp.mode = 0; +		crtc_resp->mode = 0;  	} -	if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp))) -		ret = -EFAULT; -  out:  	mutex_unlock(&dev->mode_config.mutex);  	return ret; @@ -1299,8 +1311,7 @@ out:  int drm_mode_getoutput(struct drm_device *dev,  		       void *data, struct drm_file *file_priv)  { -	struct drm_mode_get_output __user *argp = (void __user *)data; -	struct drm_mode_get_output out_resp; +	struct drm_mode_get_output *out_resp = data;  	struct drm_output *output;  	struct drm_display_mode *mode;  	int mode_count = 0; @@ -1308,16 +1319,13 @@ int drm_mode_getoutput(struct drm_device *dev,  	int copied = 0;  	int i; -	if (copy_from_user(&out_resp, argp, sizeof(out_resp))) -		return -EFAULT;	 - -	DRM_DEBUG("output id %d:\n", out_resp.output); +	DRM_DEBUG("output id %d:\n", out_resp->output);  	mutex_lock(&dev->mode_config.mutex); -	output= idr_find(&dev->mode_config.crtc_idr, out_resp.output); -	if (!output || (output->id != out_resp.output)) { +	output= idr_find(&dev->mode_config.crtc_idr, out_resp->output); +	if (!output || (output->id != out_resp->output)) {  		ret = -EINVAL; -		goto out_unlock; +		goto done;  	}  	list_for_each_entry(mode, &output->modes, head) @@ -1327,42 +1335,32 @@ int drm_mode_getoutput(struct drm_device *dev,  		if (output->user_mode_ids[i] != 0)  			mode_count++; -	strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN); -	out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0; +	strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN); +	out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0; -	out_resp.mm_width = output->mm_width; -	out_resp.mm_height = output->mm_height; -	out_resp.subpixel = output->subpixel_order; -	out_resp.connection = output->status; +	out_resp->mm_width = output->mm_width; +	out_resp->mm_height = output->mm_height; +	out_resp->subpixel = output->subpixel_order; +	out_resp->connection = output->status;  	if (output->crtc) -		out_resp.crtc = output->crtc->id; +		out_resp->crtc = output->crtc->id;  	else -		out_resp.crtc = 0; +		out_resp->crtc = 0; -	if ((out_resp.count_modes >= mode_count) && mode_count) { +	if ((out_resp->count_modes >= mode_count) && mode_count) {  		copied = 0;  		list_for_each_entry(mode, &output->modes, head) { -			if (put_user(mode->mode_id, &out_resp.modes[copied++])) { -				ret = -EFAULT; -				goto done; -			} +			out_resp->modes[copied++] = mode->mode_id;  		}  		for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {  			if (output->user_mode_ids[i] != 0) -				if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) { -					ret = -EFAULT; -					goto done; -				} +				out_resp->modes[copied++] = output->user_mode_ids[i];  		}  	} -	out_resp.count_modes = mode_count; +	out_resp->count_modes = mode_count;  done: -	if (copy_to_user(argp, &out_resp, sizeof(out_resp))) -		ret = -EFAULT; - -out_unlock:  	mutex_unlock(&dev->mode_config.mutex);  	return ret;  } @@ -1387,8 +1385,7 @@ out_unlock:  int drm_mode_setcrtc(struct drm_device *dev,  		     void *data, struct drm_file *file_priv)  { -	struct drm_mode_crtc __user *argp = (void __user *)data; -	struct drm_mode_crtc crtc_req; +	struct drm_mode_crtc *crtc_req = data;  	struct drm_crtc *crtc;  	struct drm_output **output_set = NULL, *output;  	struct drm_display_mode *mode; @@ -1396,29 +1393,26 @@ int drm_mode_setcrtc(struct drm_device *dev,  	int ret = 0;  	int i; -	if (copy_from_user(&crtc_req, argp, sizeof(crtc_req))) -		return -EFAULT; -  	mutex_lock(&dev->mode_config.mutex); -	crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id); -	if (!crtc || (crtc->id != crtc_req.crtc_id)) { -		DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req.crtc_id); +	crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id); +	if (!crtc || (crtc->id != crtc_req->crtc_id)) { +		DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id);  		ret = -EINVAL;  		goto out;  	} -	if (crtc_req.mode) { +	if (crtc_req->mode) {  		/* if we have a mode we need a framebuffer */ -		if (crtc_req.fb_id) { -			fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id); -			if (!fb || (fb->id != crtc_req.fb_id)) { -				DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id); +		if (crtc_req->fb_id) { +			fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id); +			if (!fb || (fb->id != crtc_req->fb_id)) { +				DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id);  				ret = -EINVAL;  				goto out;  			}  		} -		mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode); -		if (!mode || (mode->mode_id != crtc_req.mode)) { +		mode = idr_find(&dev->mode_config.crtc_idr, crtc_req->mode); +		if (!mode || (mode->mode_id != crtc_req->mode)) {  			struct drm_output *output;  			list_for_each_entry(output,  @@ -1431,36 +1425,36 @@ int drm_mode_setcrtc(struct drm_device *dev,  				}  			} -			DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req.mode, mode); +			DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req->mode, mode);  			ret = -EINVAL;  			goto out;  		}  	} else  		mode = NULL; -	if (crtc_req.count_outputs == 0 && mode) { +	if (crtc_req->count_outputs == 0 && mode) {  		DRM_DEBUG("Count outputs is 0 but mode set\n");  		ret = -EINVAL;  		goto out;  	} -	if (crtc_req.count_outputs > 0 && !mode && !fb) { -		DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req.count_outputs); +	if (crtc_req->count_outputs > 0 && !mode && !fb) { +		DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs);  		ret = -EINVAL;  		goto out;  	} -	if (crtc_req.count_outputs > 0) { +	if (crtc_req->count_outputs > 0) {  		u32 out_id; -		output_set = kmalloc(crtc_req.count_outputs * +		output_set = kmalloc(crtc_req->count_outputs *  				     sizeof(struct drm_output *), GFP_KERNEL);  		if (!output_set) {  			ret = -ENOMEM;  			goto out;  		} -		for (i = 0; i < crtc_req.count_outputs; i++) { -			if (get_user(out_id, &crtc_req.set_outputs[i])) { +		for (i = 0; i < crtc_req->count_outputs; i++) { +			if (get_user(out_id, &crtc_req->set_outputs[i])) {  				ret = -EFAULT;  				goto out;  			} @@ -1476,7 +1470,7 @@ int drm_mode_setcrtc(struct drm_device *dev,  		}  	} -	ret = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb); +	ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb);  out:  	mutex_unlock(&dev->mode_config.mutex); @@ -1503,29 +1497,25 @@ out:  int drm_mode_addfb(struct drm_device *dev,  		   void *data, struct drm_file *file_priv)  { -	struct drm_mode_fb_cmd __user *argp = (void __user *)data; -	struct drm_mode_fb_cmd r; +	struct drm_mode_fb_cmd *r = data;  	struct drm_mode_config *config = &dev->mode_config;  	struct drm_framebuffer *fb;  	struct drm_buffer_object *bo;  	struct drm_crtc *crtc;  	int ret = 0; -	if (copy_from_user(&r, argp, sizeof(r))) -		return -EFAULT; - -	if ((config->min_width > r.width) || (r.width > config->max_width)) { +	if ((config->min_width > r->width) || (r->width > config->max_width)) {  		DRM_ERROR("mode new framebuffer width not within limits\n");  		return -EINVAL;  	} -	if ((config->min_height > r.height) || (r.height > config->max_height)) { +	if ((config->min_height > r->height) || (r->height > config->max_height)) {  		DRM_ERROR("mode new framebuffer height not within limits\n");  		return -EINVAL;  	}  	mutex_lock(&dev->mode_config.mutex);  	/* TODO check limits are okay */ -	ret = drm_get_buffer_object(dev, &bo, r.handle); +	ret = drm_get_buffer_object(dev, &bo, r->handle);  	if (ret || !bo) {  		ret = -EINVAL;  		goto out; @@ -1540,23 +1530,18 @@ int drm_mode_addfb(struct drm_device *dev,  		goto out;  	} -	fb->width = r.width; -	fb->height = r.height; -	fb->pitch = r.pitch; -	fb->bits_per_pixel = r.bpp; -	fb->depth = r.depth; +	fb->width = r->width; +	fb->height = r->height; +	fb->pitch = r->pitch; +	fb->bits_per_pixel = r->bpp; +	fb->depth = r->depth;  	fb->offset = bo->offset;  	fb->bo = bo; -	r.buffer_id = fb->id; +	r->buffer_id = fb->id;  	list_add(&fb->filp_head, &file_priv->fbs); -	if (copy_to_user(argp, &r, sizeof(r))) { -		ret = -EFAULT; -		goto out; -	} -		  	/* FIXME: bind the fb to the right crtc */  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  		crtc->fb = fb; @@ -1589,13 +1574,12 @@ int drm_mode_rmfb(struct drm_device *dev,  		   void *data, struct drm_file *file_priv)  {  	struct drm_framebuffer *fb = 0; -	uint32_t id = data; +	uint32_t *id = data;  	int ret = 0; -	mutex_lock(&dev->mode_config.mutex); -	fb = idr_find(&dev->mode_config.crtc_idr, id); +	fb = idr_find(&dev->mode_config.crtc_idr, *id);  	/* TODO check that we realy get a framebuffer back. */ -	if (!fb || (id != fb->id)) { +	if (!fb || (*id != fb->id)) {  		DRM_ERROR("mode invalid framebuffer id\n");  		ret = -EINVAL;  		goto out; @@ -1635,31 +1619,24 @@ out:  int drm_mode_getfb(struct drm_device *dev,  		   void *data, struct drm_file *file_priv)  { -	struct drm_mode_fb_cmd __user *argp = (void __user *)data; -	struct drm_mode_fb_cmd r; +	struct drm_mode_fb_cmd *r = data;  	struct drm_framebuffer *fb;  	int ret = 0; -	if (copy_from_user(&r, argp, sizeof(r))) -		return -EFAULT; -  	mutex_lock(&dev->mode_config.mutex); -	fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); -	if (!fb || (r.buffer_id != fb->id)) { +	fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id); +	if (!fb || (r->buffer_id != fb->id)) {  		DRM_ERROR("invalid framebuffer id\n");  		ret = -EINVAL;  		goto out;  	} -	r.height = fb->height; -	r.width = fb->width; -	r.depth = fb->depth; -	r.bpp = fb->bits_per_pixel; -	r.handle = fb->bo->base.hash.key; -	r.pitch = fb->pitch; - -	if (copy_to_user(argp, &r, sizeof(r))) -		ret = -EFAULT; +	r->height = fb->height; +	r->width = fb->width; +	r->depth = fb->depth; +	r->bpp = fb->bits_per_pixel; +	r->handle = fb->bo->base.hash.key; +	r->pitch = fb->pitch;  out:  	mutex_unlock(&dev->mode_config.mutex); @@ -1713,14 +1690,10 @@ void drm_fb_release(struct file *filp)  int drm_mode_addmode(struct drm_device *dev,  		     void *data, struct drm_file *file_priv)  { -	struct drm_mode_modeinfo __user *argp = (void __user *)data; -	struct drm_mode_modeinfo new_mode; +	struct drm_mode_modeinfo *new_mode = data;  	struct drm_display_mode *user_mode;  	int ret = 0; -	if (copy_from_user(&new_mode, argp, sizeof(new_mode))) -		return -EFAULT; -  	mutex_lock(&dev->mode_config.mutex);  	user_mode = drm_mode_create(dev);  	if (!user_mode) { @@ -1728,16 +1701,14 @@ int drm_mode_addmode(struct drm_device *dev,  		goto out;  	} -	drm_crtc_convert_umode(user_mode, &new_mode); +	drm_crtc_convert_umode(user_mode, new_mode);  	user_mode->type |= DRM_MODE_TYPE_USERDEF;  	user_mode->output_count = 0;  	list_add(&user_mode->head, &dev->mode_config.usermode_list); -	new_mode.id = user_mode->mode_id; -	if (copy_to_user(argp, &new_mode, sizeof(new_mode))) -		ret = -EFAULT; +	new_mode->id = user_mode->mode_id;  out:  	mutex_unlock(&dev->mode_config.mutex); @@ -1761,13 +1732,13 @@ out:  int drm_mode_rmmode(struct drm_device *dev,  		    void *data, struct drm_file *file_priv)  { -	uint32_t id = (uint32_t)data; +	uint32_t *id = data;  	struct drm_display_mode *mode, *t;  	int ret = -EINVAL;  	mutex_lock(&dev->mode_config.mutex);	 -	mode = idr_find(&dev->mode_config.crtc_idr, id); -	if (!mode || (id != mode->mode_id)) { +	mode = idr_find(&dev->mode_config.crtc_idr, *id); +	if (!mode || (*id != mode->mode_id)) {  		ret = -EINVAL;  		goto out;  	} @@ -1812,25 +1783,21 @@ out:  int drm_mode_attachmode(struct drm_device *dev,  			void *data, struct drm_file *file_priv)  { -	struct drm_mode_mode_cmd __user *argp = (void __user *)data; -	struct drm_mode_mode_cmd mode_cmd; +	struct drm_mode_mode_cmd *mode_cmd = data;  	struct drm_output *output;  	struct drm_display_mode *mode;  	int i, ret = 0; -	if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) -		return -EFAULT; -  	mutex_lock(&dev->mode_config.mutex); -	mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id); -	if (!mode || (mode->mode_id != mode_cmd.mode_id)) { +	mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd->mode_id); +	if (!mode || (mode->mode_id != mode_cmd->mode_id)) {  		ret = -EINVAL;  		goto out;  	} -	output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id); -	if (!output || (output->id != mode_cmd.output_id)) { +	output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); +	if (!output || (output->id != mode_cmd->output_id)) {  		ret = -EINVAL;  		goto out;  	} @@ -1867,25 +1834,21 @@ out:  int drm_mode_detachmode(struct drm_device *dev,  			void *data, struct drm_file *file_priv)  { -	struct drm_mode_mode_cmd __user *argp = (void __user *)data; -	struct drm_mode_mode_cmd mode_cmd; +	struct drm_mode_mode_cmd *mode_cmd = data;  	struct drm_output *output;  	struct drm_display_mode *mode;  	int i, found = 0, ret = 0; -	if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd))) -		return -EFAULT; -  	mutex_lock(&dev->mode_config.mutex); -	mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id); -	if (!mode || (mode->mode_id != mode_cmd.mode_id)) { +	mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd->mode_id); +	if (!mode || (mode->mode_id != mode_cmd->mode_id)) {  		ret = -EINVAL;  		goto out;  	} -	output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id); -	if (!output || (output->id != mode_cmd.output_id)) { +	output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id); +	if (!output || (output->id != mode_cmd->output_id)) {  		ret = -EINVAL;  		goto out;  	} | 
