drm: initial mode object groups.

This creates a default group attached to the legacy drm minor nodes.

It covers all the objects in the set. make set resources only return
objects for this set. Need to fix up other functions to only work on
objects in their allowed set.
This commit is contained in:
Dave Airlie 2008-06-02 16:45:44 +10:00
parent 50d3e5bd02
commit 149b17311a
4 changed files with 137 additions and 39 deletions

View file

@ -792,7 +792,7 @@ struct drm_minor {
struct drm_master *master; /* currently active master for this node */
struct list_head master_list;
/* possibly needs a list of configured modesetting pieces */
struct drm_mode_group mode_group;
};

View file

@ -585,6 +585,45 @@ void drm_mode_config_init(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_mode_config_init);
int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
{
uint32_t total_objects = 0;
total_objects += dev->mode_config.num_crtc;
total_objects += dev->mode_config.num_connector;
total_objects += dev->mode_config.num_encoder;
group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
if (!group->id_list)
return -ENOMEM;
group->num_crtcs = 0;
group->num_connectors = 0;
group->num_encoders = 0;
return 0;
}
int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group)
{
struct drm_crtc *crtc;
struct drm_encoder *encoder;
struct drm_connector *connector;
if (drm_mode_group_init(dev, group))
return -ENOMEM;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
group->id_list[group->num_crtcs++] = crtc->base.id;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
group->id_list[group->num_crtcs + group->num_encoders++] = encoder->base.id;
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
group->id_list[group->num_crtcs + group->num_encoders + group->num_connectors++] = connector->base.id;
return 0;
}
/**
* drm_get_buffer_object - find the buffer object for a given handle
* @dev: DRM device
@ -786,25 +825,37 @@ int drm_mode_getresources(struct drm_device *dev,
int crtc_count = 0;
int fb_count = 0;
int encoder_count = 0;
int copied = 0;
int copied = 0, i;
uint32_t __user *fb_id;
uint32_t __user *crtc_id;
uint32_t __user *connector_id;
uint32_t __user *encoder_id;
struct drm_mode_group *mode_group;
mutex_lock(&dev->mode_config.mutex);
/* for the non-control nodes we need to limit the list of resources by IDs in the
group list for this node */
list_for_each(lh, &file_priv->fbs)
fb_count++;
list_for_each(lh, &dev->mode_config.crtc_list)
crtc_count++;
mode_group = &file_priv->master->minor->mode_group;
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each(lh, &dev->mode_config.connector_list)
connector_count++;
list_for_each(lh, &dev->mode_config.crtc_list)
crtc_count++;
list_for_each(lh, &dev->mode_config.encoder_list)
encoder_count++;
list_for_each(lh, &dev->mode_config.connector_list)
connector_count++;
list_for_each(lh, &dev->mode_config.encoder_list)
encoder_count++;
} else {
crtc_count = mode_group->num_crtcs;
connector_count = mode_group->num_connectors;
encoder_count = mode_group->num_encoders;
}
card_res->max_height = dev->mode_config.max_height;
card_res->min_height = dev->mode_config.min_height;
@ -830,49 +881,82 @@ int drm_mode_getresources(struct drm_device *dev,
if (card_res->count_crtcs >= crtc_count) {
copied = 0;
crtc_id = (uint32_t *)(unsigned long)card_res->crtc_id_ptr;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){
DRM_DEBUG("CRTC ID is %d\n", crtc->base.id);
if (put_user(crtc->base.id, crtc_id + copied)) {
ret = -EFAULT;
goto out;
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
DRM_DEBUG("CRTC ID is %d\n", crtc->base.id);
if (put_user(crtc->base.id, crtc_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
} else {
for (i = 0; i < mode_group->num_crtcs; i++) {
if (put_user(mode_group->id_list[i], crtc_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
copied++;
}
}
card_res->count_crtcs = crtc_count;
/* Connectors */
if (card_res->count_connectors >= connector_count) {
copied = 0;
connector_id = (uint32_t *)(unsigned long)card_res->connector_id_ptr;
list_for_each_entry(connector, &dev->mode_config.connector_list,
head) {
DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id);
if (put_user(connector->base.id, connector_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
}
card_res->count_connectors = connector_count;
/* Encoders */
if (card_res->count_encoders >= encoder_count) {
copied = 0;
encoder_id = (uint32_t *)(unsigned long)card_res->encoder_id_ptr;
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
head) {
DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id);
if (put_user(encoder->base.id, encoder_id + copied)) {
ret = -EFAULT;
goto out;
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
head) {
DRM_DEBUG("ENCODER ID is %d\n", encoder->base.id);
if (put_user(encoder->base.id, encoder_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
copied++;
} else {
for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
if (put_user(mode_group->id_list[i], encoder_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
}
}
card_res->count_encoders = encoder_count;
/* Connectors */
if (card_res->count_connectors >= connector_count) {
copied = 0;
connector_id = (uint32_t *)(unsigned long)card_res->connector_id_ptr;
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
list_for_each_entry(connector, &dev->mode_config.connector_list,
head) {
DRM_DEBUG("CONNECTOR ID is %d\n", connector->base.id);
if (put_user(connector->base.id, connector_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
} else {
int start = mode_group->num_crtcs + mode_group->num_encoders;
for (i = start; i < start + mode_group->num_connectors; i++) {
if (put_user(mode_group->id_list[i], connector_id + copied)) {
ret = -EFAULT;
goto out;
}
copied++;
}
}
}
card_res->count_connectors = connector_count;
DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs,
card_res->count_connectors, card_res->count_encoders);

View file

@ -519,6 +519,15 @@ struct drm_mode_config_funcs {
bool (*resize_fb)(struct drm_device *dev, struct drm_framebuffer *fb);
};
struct drm_mode_group {
uint32_t num_crtcs;
uint32_t num_encoders;
uint32_t num_connectors;
/* list of object IDs for this group */
uint32_t *id_list;
};
/**
* drm_mode_config - Mode configuration control structure
*
@ -591,7 +600,7 @@ extern void drm_encoder_cleanup(struct drm_encoder *encoder);
extern char *drm_get_connector_name(struct drm_connector *connector);
extern char *drm_get_dpms_name(int val);
extern void drm_fb_release(struct file *filp);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);

View file

@ -378,6 +378,11 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
if ((ret = dev->driver->load(dev, ent->driver_data)))
goto err_g5;
/* setup the grouping for the legacy output */
if (drm_core_check_feature(dev, DRIVER_MODESET))
if (drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group))
goto err_g5;
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
driver->name, driver->major, driver->minor, driver->patchlevel,
driver->date, dev->primary->index);