no need to copy to/from user as the unlocked ioctl does

that for us.

other small cleanups.
main
Alan Hourihane 2007-09-26 15:40:40 +01:00
parent b2c4c7ae5e
commit dfcf9272ce
1 changed files with 164 additions and 201 deletions

View File

@ -433,25 +433,32 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
* on the DPLL. * on the DPLL.
*/ */
crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
list_for_each_entry(output, &dev->mode_config.output_list, head) { 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", if (output->crtc != crtc)
output->name, mode->name); continue;
DRM_INFO("%s: set mode %s\n", output->name, mode->name);
output->funcs->mode_set(output, mode, adjusted_mode); output->funcs->mode_set(output, mode, adjusted_mode);
} }
}
/* Now, enable the clocks, plane, pipe, and outputs that we set up. */ /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
crtc->funcs->commit(crtc); crtc->funcs->commit(crtc);
list_for_each_entry(output, &dev->mode_config.output_list, head) { list_for_each_entry(output, &dev->mode_config.output_list, head) {
if (output->crtc == crtc) {
if (output->crtc != crtc)
continue;
output->funcs->commit(output); output->funcs->commit(output);
#if 0 // TODO def RANDR_12_INTERFACE #if 0 // TODO def RANDR_12_INTERFACE
if (output->randr_output) if (output->randr_output)
RRPostPendingProperties (output->randr_output); RRPostPendingProperties (output->randr_output);
#endif #endif
} }
}
/* XXX free adjustedmode */ /* XXX free adjustedmode */
drm_mode_destroy(dev, adjusted_mode); drm_mode_destroy(dev, adjusted_mode);
@ -762,7 +769,7 @@ out_err:
*/ */
static void drm_pick_crtcs (struct drm_device *dev) static void drm_pick_crtcs (struct drm_device *dev)
{ {
int c, o; int c, o, assigned;
struct drm_output *output, *output_equal; struct drm_output *output, *output_equal;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_display_mode *des_mode = NULL, *modes, *modes_equal; 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; c = -1;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
assigned = 0;
c++; c++;
if ((output->possible_crtcs & (1 << c)) == 0) if ((output->possible_crtcs & (1 << c)) == 0)
continue; 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; o = -1;
list_for_each_entry(output_equal, &dev->mode_config.output_list, head) { list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
o++; 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, &output->modes, head) {
list_for_each_entry(modes_equal, &output_equal->modes, head) { list_for_each_entry(modes_equal, &output_equal->modes, head) {
if (drm_mode_equal (modes, modes_equal)) { 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; goto clone;
} }
} }
@ -825,7 +849,10 @@ static void drm_pick_crtcs (struct drm_device *dev)
} }
clone: clone:
#endif /* crtc has been assigned skip it */
if (assigned)
continue;
/* Found a CRTC to attach to, do it ! */ /* Found a CRTC to attach to, do it ! */
output->crtc = crtc; output->crtc = crtc;
output->crtc->desired_mode = des_mode; output->crtc->desired_mode = des_mode;
@ -856,6 +883,7 @@ clone:
bool drm_initial_config(struct drm_device *dev, bool can_grow) bool drm_initial_config(struct drm_device *dev, bool can_grow)
{ {
struct drm_output *output; struct drm_output *output;
struct drm_crtc *crtc;
int ret = false; int ret = false;
mutex_lock(&dev->mode_config.mutex); 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); 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) { 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) if (!output->crtc || !output->crtc->desired_mode)
continue; 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); drm_disable_unused_functions(dev);
mutex_unlock(&dev->mode_config.mutex); 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, int drm_mode_getresources(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_card_res __user *argp = (void __user *)data; struct drm_mode_card_res *card_res = data;
struct drm_mode_card_res card_res;
struct list_head *lh; struct list_head *lh;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_output *output; 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) list_for_each(lh, &dev->mode_config.usermode_list)
mode_count++; mode_count++;
if (copy_from_user(&card_res, argp, sizeof(card_res))) { if (card_res->count_modes == 0) {
ret = -EFAULT;
goto out_unlock;
}
if (card_res.count_modes == 0) {
DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height); 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); drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
mode_count = 0; mode_count = 0;
@ -1141,78 +1180,58 @@ int drm_mode_getresources(struct drm_device *dev,
/* handle this in 4 parts */ /* handle this in 4 parts */
/* FBs */ /* FBs */
if (card_res.count_fbs >= fb_count) { if (card_res->count_fbs >= fb_count) {
copied = 0; copied = 0;
list_for_each_entry(fb, &dev->mode_config.fb_list, head) { list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
if (put_user(fb->id, &card_res.fb_id[copied++])) { card_res->fb_id[copied++] = fb->id;
ret = -EFAULT;
goto done;
} }
} }
} card_res->count_fbs = fb_count;
card_res.count_fbs = fb_count;
/* CRTCs */ /* CRTCs */
if (card_res.count_crtcs >= crtc_count) { if (card_res->count_crtcs >= crtc_count) {
copied = 0; copied = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){
DRM_DEBUG("CRTC ID is %d\n", crtc->id); DRM_DEBUG("CRTC ID is %d\n", crtc->id);
if (put_user(crtc->id, &card_res.crtc_id[copied++])) { card_res->crtc_id[copied++] = crtc->id;
ret = -EFAULT;
goto done;
} }
} }
} card_res->count_crtcs = crtc_count;
card_res.count_crtcs = crtc_count;
/* Outputs */ /* Outputs */
if (card_res.count_outputs >= output_count) { if (card_res->count_outputs >= output_count) {
copied = 0; copied = 0;
list_for_each_entry(output, &dev->mode_config.output_list, list_for_each_entry(output, &dev->mode_config.output_list,
head) { head) {
DRM_DEBUG("OUTPUT ID is %d\n", output->id); DRM_DEBUG("OUTPUT ID is %d\n", output->id);
if (put_user(output->id, &card_res.output_id[copied++])) { card_res->output_id[copied++] = output->id;
ret = -EFAULT;
goto done;
} }
} }
} card_res->count_outputs = output_count;
card_res.count_outputs = output_count;
/* Modes */ /* Modes */
if (card_res.count_modes >= mode_count) { if (card_res->count_modes >= mode_count) {
copied = 0; copied = 0;
list_for_each_entry(output, &dev->mode_config.output_list, list_for_each_entry(output, &dev->mode_config.output_list,
head) { head) {
list_for_each_entry(mode, &output->modes, head) { list_for_each_entry(mode, &output->modes, head) {
drm_crtc_convert_to_umode(&u_mode, mode); drm_crtc_convert_to_umode(&u_mode, mode);
if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { card_res->modes[copied++] = u_mode;
ret = -EFAULT;
goto done;
}
} }
} }
/* add in user modes */ /* add in user modes */
list_for_each_entry(mode, &dev->mode_config.usermode_list, head) { list_for_each_entry(mode, &dev->mode_config.usermode_list, head) {
drm_crtc_convert_to_umode(&u_mode, mode); drm_crtc_convert_to_umode(&u_mode, mode);
if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) { card_res->modes[copied++] = u_mode;
ret = -EFAULT;
goto done;
} }
} }
} card_res->count_modes = mode_count;
card_res.count_modes = mode_count;
done: DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs,
DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs, card_res->count_outputs,
card_res.count_outputs, card_res->count_modes);
card_res.count_modes);
if (copy_to_user(argp, &card_res, sizeof(card_res)))
ret = -EFAULT;
out_unlock:
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
return ret; return ret;
} }
@ -1237,43 +1256,36 @@ out_unlock:
int drm_mode_getcrtc(struct drm_device *dev, int drm_mode_getcrtc(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_crtc __user *argp = (void __user *)data; struct drm_mode_crtc *crtc_resp = data;
struct drm_mode_crtc crtc_resp;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_output *output; struct drm_output *output;
int ocount; int ocount;
int ret = 0; int ret = 0;
if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp)))
return -EFAULT;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp->crtc_id);
if (!crtc || (crtc->id != crtc_resp.crtc_id)) { if (!crtc || (crtc->id != crtc_resp->crtc_id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
crtc_resp.x = crtc->x; crtc_resp->x = crtc->x;
crtc_resp.y = crtc->y; crtc_resp->y = crtc->y;
crtc_resp.fb_id = 1; crtc_resp->fb_id = 1;
crtc_resp.outputs = 0; crtc_resp->outputs = 0;
if (crtc->enabled) { if (crtc->enabled) {
crtc_resp.mode = crtc->mode.mode_id; crtc_resp->mode = crtc->mode.mode_id;
ocount = 0; ocount = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head) { list_for_each_entry(output, &dev->mode_config.output_list, head) {
if (output->crtc == crtc) if (output->crtc == crtc)
crtc_resp.outputs |= 1 << (ocount++); crtc_resp->outputs |= 1 << (ocount++);
} }
} else { } else {
crtc_resp.mode = 0; crtc_resp->mode = 0;
} }
if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp)))
ret = -EFAULT;
out: out:
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
return ret; return ret;
@ -1299,8 +1311,7 @@ out:
int drm_mode_getoutput(struct drm_device *dev, int drm_mode_getoutput(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_get_output __user *argp = (void __user *)data; struct drm_mode_get_output *out_resp = data;
struct drm_mode_get_output out_resp;
struct drm_output *output; struct drm_output *output;
struct drm_display_mode *mode; struct drm_display_mode *mode;
int mode_count = 0; int mode_count = 0;
@ -1308,16 +1319,13 @@ int drm_mode_getoutput(struct drm_device *dev,
int copied = 0; int copied = 0;
int i; int i;
if (copy_from_user(&out_resp, argp, sizeof(out_resp))) DRM_DEBUG("output id %d:\n", out_resp->output);
return -EFAULT;
DRM_DEBUG("output id %d:\n", out_resp.output);
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
output= idr_find(&dev->mode_config.crtc_idr, out_resp.output); output= idr_find(&dev->mode_config.crtc_idr, out_resp->output);
if (!output || (output->id != out_resp.output)) { if (!output || (output->id != out_resp->output)) {
ret = -EINVAL; ret = -EINVAL;
goto out_unlock; goto done;
} }
list_for_each_entry(mode, &output->modes, head) 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) if (output->user_mode_ids[i] != 0)
mode_count++; mode_count++;
strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN); strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN);
out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0; out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0;
out_resp.mm_width = output->mm_width; out_resp->mm_width = output->mm_width;
out_resp.mm_height = output->mm_height; out_resp->mm_height = output->mm_height;
out_resp.subpixel = output->subpixel_order; out_resp->subpixel = output->subpixel_order;
out_resp.connection = output->status; out_resp->connection = output->status;
if (output->crtc) if (output->crtc)
out_resp.crtc = output->crtc->id; out_resp->crtc = output->crtc->id;
else 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; copied = 0;
list_for_each_entry(mode, &output->modes, head) { list_for_each_entry(mode, &output->modes, head) {
if (put_user(mode->mode_id, &out_resp.modes[copied++])) { out_resp->modes[copied++] = mode->mode_id;
ret = -EFAULT;
goto done;
}
} }
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) { for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
if (output->user_mode_ids[i] != 0) if (output->user_mode_ids[i] != 0)
if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) { out_resp->modes[copied++] = output->user_mode_ids[i];
ret = -EFAULT;
goto done;
}
} }
} }
out_resp.count_modes = mode_count; out_resp->count_modes = mode_count;
done: done:
if (copy_to_user(argp, &out_resp, sizeof(out_resp)))
ret = -EFAULT;
out_unlock:
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
return ret; return ret;
} }
@ -1387,8 +1385,7 @@ out_unlock:
int drm_mode_setcrtc(struct drm_device *dev, int drm_mode_setcrtc(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_crtc __user *argp = (void __user *)data; struct drm_mode_crtc *crtc_req = data;
struct drm_mode_crtc crtc_req;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_output **output_set = NULL, *output; struct drm_output **output_set = NULL, *output;
struct drm_display_mode *mode; struct drm_display_mode *mode;
@ -1396,29 +1393,26 @@ int drm_mode_setcrtc(struct drm_device *dev,
int ret = 0; int ret = 0;
int i; int i;
if (copy_from_user(&crtc_req, argp, sizeof(crtc_req)))
return -EFAULT;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id); crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id);
if (!crtc || (crtc->id != crtc_req.crtc_id)) { if (!crtc || (crtc->id != crtc_req->crtc_id)) {
DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req.crtc_id); DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (crtc_req.mode) { if (crtc_req->mode) {
/* if we have a mode we need a framebuffer */ /* if we have a mode we need a framebuffer */
if (crtc_req.fb_id) { if (crtc_req->fb_id) {
fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id); fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id);
if (!fb || (fb->id != crtc_req.fb_id)) { if (!fb || (fb->id != crtc_req->fb_id)) {
DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id); DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
} }
mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode); mode = idr_find(&dev->mode_config.crtc_idr, crtc_req->mode);
if (!mode || (mode->mode_id != crtc_req.mode)) { if (!mode || (mode->mode_id != crtc_req->mode)) {
struct drm_output *output; struct drm_output *output;
list_for_each_entry(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; ret = -EINVAL;
goto out; goto out;
} }
} else } else
mode = NULL; 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"); DRM_DEBUG("Count outputs is 0 but mode set\n");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (crtc_req.count_outputs > 0 && !mode && !fb) { 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); DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (crtc_req.count_outputs > 0) { if (crtc_req->count_outputs > 0) {
u32 out_id; u32 out_id;
output_set = kmalloc(crtc_req.count_outputs * output_set = kmalloc(crtc_req->count_outputs *
sizeof(struct drm_output *), GFP_KERNEL); sizeof(struct drm_output *), GFP_KERNEL);
if (!output_set) { if (!output_set) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
for (i = 0; i < crtc_req.count_outputs; i++) { for (i = 0; i < crtc_req->count_outputs; i++) {
if (get_user(out_id, &crtc_req.set_outputs[i])) { if (get_user(out_id, &crtc_req->set_outputs[i])) {
ret = -EFAULT; ret = -EFAULT;
goto out; 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: out:
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
@ -1503,29 +1497,25 @@ out:
int drm_mode_addfb(struct drm_device *dev, int drm_mode_addfb(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_fb_cmd __user *argp = (void __user *)data; struct drm_mode_fb_cmd *r = data;
struct drm_mode_fb_cmd r;
struct drm_mode_config *config = &dev->mode_config; struct drm_mode_config *config = &dev->mode_config;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_buffer_object *bo; struct drm_buffer_object *bo;
struct drm_crtc *crtc; struct drm_crtc *crtc;
int ret = 0; int ret = 0;
if (copy_from_user(&r, argp, sizeof(r))) if ((config->min_width > r->width) || (r->width > config->max_width)) {
return -EFAULT;
if ((config->min_width > r.width) || (r.width > config->max_width)) {
DRM_ERROR("mode new framebuffer width not within limits\n"); DRM_ERROR("mode new framebuffer width not within limits\n");
return -EINVAL; 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"); DRM_ERROR("mode new framebuffer height not within limits\n");
return -EINVAL; return -EINVAL;
} }
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
/* TODO check limits are okay */ /* 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) { if (ret || !bo) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@ -1540,23 +1530,18 @@ int drm_mode_addfb(struct drm_device *dev,
goto out; goto out;
} }
fb->width = r.width; fb->width = r->width;
fb->height = r.height; fb->height = r->height;
fb->pitch = r.pitch; fb->pitch = r->pitch;
fb->bits_per_pixel = r.bpp; fb->bits_per_pixel = r->bpp;
fb->depth = r.depth; fb->depth = r->depth;
fb->offset = bo->offset; fb->offset = bo->offset;
fb->bo = bo; fb->bo = bo;
r.buffer_id = fb->id; r->buffer_id = fb->id;
list_add(&fb->filp_head, &file_priv->fbs); 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 */ /* FIXME: bind the fb to the right crtc */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
crtc->fb = fb; crtc->fb = fb;
@ -1589,13 +1574,12 @@ int drm_mode_rmfb(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_framebuffer *fb = 0; struct drm_framebuffer *fb = 0;
uint32_t id = data; uint32_t *id = data;
int ret = 0; 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. */ /* 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"); DRM_ERROR("mode invalid framebuffer id\n");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@ -1635,31 +1619,24 @@ out:
int drm_mode_getfb(struct drm_device *dev, int drm_mode_getfb(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_fb_cmd __user *argp = (void __user *)data; struct drm_mode_fb_cmd *r = data;
struct drm_mode_fb_cmd r;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
int ret = 0; int ret = 0;
if (copy_from_user(&r, argp, sizeof(r)))
return -EFAULT;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id); fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id);
if (!fb || (r.buffer_id != fb->id)) { if (!fb || (r->buffer_id != fb->id)) {
DRM_ERROR("invalid framebuffer id\n"); DRM_ERROR("invalid framebuffer id\n");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
r.height = fb->height; r->height = fb->height;
r.width = fb->width; r->width = fb->width;
r.depth = fb->depth; r->depth = fb->depth;
r.bpp = fb->bits_per_pixel; r->bpp = fb->bits_per_pixel;
r.handle = fb->bo->base.hash.key; r->handle = fb->bo->base.hash.key;
r.pitch = fb->pitch; r->pitch = fb->pitch;
if (copy_to_user(argp, &r, sizeof(r)))
ret = -EFAULT;
out: out:
mutex_unlock(&dev->mode_config.mutex); 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, int drm_mode_addmode(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_modeinfo __user *argp = (void __user *)data; struct drm_mode_modeinfo *new_mode = data;
struct drm_mode_modeinfo new_mode;
struct drm_display_mode *user_mode; struct drm_display_mode *user_mode;
int ret = 0; int ret = 0;
if (copy_from_user(&new_mode, argp, sizeof(new_mode)))
return -EFAULT;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
user_mode = drm_mode_create(dev); user_mode = drm_mode_create(dev);
if (!user_mode) { if (!user_mode) {
@ -1728,16 +1701,14 @@ int drm_mode_addmode(struct drm_device *dev,
goto out; 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->type |= DRM_MODE_TYPE_USERDEF;
user_mode->output_count = 0; user_mode->output_count = 0;
list_add(&user_mode->head, &dev->mode_config.usermode_list); list_add(&user_mode->head, &dev->mode_config.usermode_list);
new_mode.id = user_mode->mode_id; new_mode->id = user_mode->mode_id;
if (copy_to_user(argp, &new_mode, sizeof(new_mode)))
ret = -EFAULT;
out: out:
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
@ -1761,13 +1732,13 @@ out:
int drm_mode_rmmode(struct drm_device *dev, int drm_mode_rmmode(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
uint32_t id = (uint32_t)data; uint32_t *id = data;
struct drm_display_mode *mode, *t; struct drm_display_mode *mode, *t;
int ret = -EINVAL; int ret = -EINVAL;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
mode = idr_find(&dev->mode_config.crtc_idr, id); mode = idr_find(&dev->mode_config.crtc_idr, *id);
if (!mode || (id != mode->mode_id)) { if (!mode || (*id != mode->mode_id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@ -1812,25 +1783,21 @@ out:
int drm_mode_attachmode(struct drm_device *dev, int drm_mode_attachmode(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_mode_cmd __user *argp = (void __user *)data; struct drm_mode_mode_cmd *mode_cmd = data;
struct drm_mode_mode_cmd mode_cmd;
struct drm_output *output; struct drm_output *output;
struct drm_display_mode *mode; struct drm_display_mode *mode;
int i, ret = 0; int i, ret = 0;
if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd)))
return -EFAULT;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
mode = idr_find(&dev->mode_config.crtc_idr, 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)) { if (!mode || (mode->mode_id != mode_cmd->mode_id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id); output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
if (!output || (output->id != mode_cmd.output_id)) { if (!output || (output->id != mode_cmd->output_id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@ -1867,25 +1834,21 @@ out:
int drm_mode_detachmode(struct drm_device *dev, int drm_mode_detachmode(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
struct drm_mode_mode_cmd __user *argp = (void __user *)data; struct drm_mode_mode_cmd *mode_cmd = data;
struct drm_mode_mode_cmd mode_cmd;
struct drm_output *output; struct drm_output *output;
struct drm_display_mode *mode; struct drm_display_mode *mode;
int i, found = 0, ret = 0; int i, found = 0, ret = 0;
if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd)))
return -EFAULT;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
mode = idr_find(&dev->mode_config.crtc_idr, 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)) { if (!mode || (mode->mode_id != mode_cmd->mode_id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id); output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
if (!output || (output->id != mode_cmd.output_id)) { if (!output || (output->id != mode_cmd->output_id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }