drm: reorganise minor number handling using code from modesetting branch

Rip out the whole head thing and replace it with an idr and drm_minor
structure.
main
Dave Airlie 2008-03-06 05:21:50 +10:00
parent 638353103d
commit 12574590cd
14 changed files with 263 additions and 207 deletions

View File

@ -408,13 +408,12 @@ enum drm_ref_type {
struct drm_file {
int authenticated;
int master;
int minor;
pid_t pid;
uid_t uid;
drm_magic_t magic;
unsigned long ioctl_count;
struct list_head lhead;
struct drm_head *head;
struct drm_minor *minor;
int remove_auth_on_close;
unsigned long lock_count;
@ -721,16 +720,19 @@ struct drm_driver {
struct pci_driver pci_driver;
};
#define DRM_MINOR_UNASSIGNED 0
#define DRM_MINOR_LEGACY 1
/**
* DRM head structure. This structure represent a video head on a card
* that may contain multiple heads. Embed one per head of these in the
* private drm_device structure.
* DRM minor structure. This structure represents a drm minor number.
*/
struct drm_head {
int minor; /**< Minor device number */
struct drm_minor {
int index; /**< Minor device number */
int type; /**< Control or render */
dev_t device; /**< Device number for mknod */
struct device kdev; /**< Linux device */
struct drm_device *dev;
struct proc_dir_entry *dev_root; /**< proc directory entry */
dev_t device; /**< Device number for mknod */
struct class_device *dev_class;
};
@ -740,7 +742,6 @@ struct drm_head {
* may contain multiple heads.
*/
struct drm_device {
struct device dev; /**< Linux device */
char *unique; /**< Unique identifier: e.g., busid */
int unique_len; /**< Length of unique field */
char *devname; /**< For /proc/interrupts */
@ -870,7 +871,7 @@ struct drm_device {
struct drm_driver *driver;
drm_local_map_t *agp_buffer_map;
unsigned int agp_buffer_token;
struct drm_head primary; /**< primary screen head */
struct drm_minor *primary; /**< render type primary screen head */
struct drm_fence_manager fm;
struct drm_buffer_manager bm;
@ -1187,23 +1188,20 @@ extern void drm_agp_chipset_flush(struct drm_device *dev);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver);
extern int drm_put_dev(struct drm_device *dev);
extern int drm_put_head(struct drm_head * head);
extern int drm_put_minor(struct drm_minor **minor);
extern unsigned int drm_debug; /* 1 to enable debug output */
extern unsigned int drm_cards_limit;
extern struct drm_head **drm_heads;
extern struct class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
extern struct idr drm_minors_idr;
extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
/* Proc support (drm_proc.h) */
extern int drm_proc_init(struct drm_device *dev,
int minor,
struct proc_dir_entry *root,
struct proc_dir_entry **dev_root);
extern int drm_proc_cleanup(int minor,
struct proc_dir_entry *root,
struct proc_dir_entry *dev_root);
int drm_proc_init(struct drm_minor *minor, int minor_id,
struct proc_dir_entry *root);
int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
/* Scatter Gather Support (drm_scatter.h) */
extern void drm_sg_cleanup(struct drm_sg_mem * entry);
@ -1226,8 +1224,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah);
struct drm_sysfs_class;
extern struct class *drm_sysfs_create(struct module *owner, char *name);
extern void drm_sysfs_destroy(void);
extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head);
extern void drm_sysfs_device_remove(struct drm_device *dev);
extern int drm_sysfs_device_add(struct drm_minor *minor);
extern void drm_sysfs_device_remove(struct drm_minor *minor);
/*
* Basic memory manager support (drm_mm.c)

View File

@ -130,7 +130,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return drm_agp_acquire((struct drm_device *) file_priv->head->dev);
return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
}
/**

View File

@ -1190,7 +1190,7 @@ static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle,
struct drm_bo_info_rep *rep)
{
struct drm_buffer_object *bo;
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
int ret = 0;
int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
@ -1262,7 +1262,7 @@ out:
static int drm_buffer_object_unmap(struct drm_file *file_priv, uint32_t handle)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct drm_buffer_object *bo;
struct drm_ref_object *ro;
int ret = 0;
@ -1654,7 +1654,7 @@ int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
struct drm_bo_info_rep *rep,
struct drm_buffer_object **bo_rep)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct drm_buffer_object *bo;
int ret;
@ -1690,7 +1690,7 @@ EXPORT_SYMBOL(drm_bo_handle_validate);
static int drm_bo_handle_info(struct drm_file *file_priv, uint32_t handle,
struct drm_bo_info_rep *rep)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct drm_buffer_object *bo;
mutex_lock(&dev->struct_mutex);
@ -1713,7 +1713,7 @@ static int drm_bo_handle_wait(struct drm_file *file_priv, uint32_t handle,
uint32_t hint,
struct drm_bo_info_rep *rep)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct drm_buffer_object *bo;
int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
int ret;
@ -1833,7 +1833,7 @@ EXPORT_SYMBOL(drm_buffer_object_create);
static int drm_bo_add_user_object(struct drm_file *file_priv,
struct drm_buffer_object *bo, int shareable)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -1881,7 +1881,7 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
if (bo_type == drm_bo_type_user)
req->flags &= ~DRM_BO_FLAG_SHAREABLE;
ret = drm_buffer_object_create(file_priv->head->dev,
ret = drm_buffer_object_create(file_priv->minor->dev,
req->size, bo_type, req->flags,
req->hint, req->page_alignment,
req->buffer_start, &entry);

View File

@ -141,7 +141,7 @@ int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv)
* while holding it.
*/
dev = file_priv->head->dev;
dev = file_priv->minor->dev;
mutex_lock(&dev->struct_mutex);
ret = drm_add_user_object(file_priv, &lock->base, 0);
lock->base.remove = &drm_bo_write_lock_remove;
@ -156,7 +156,7 @@ int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv)
int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct drm_ref_object *ro;
mutex_lock(&dev->struct_mutex);

View File

@ -416,35 +416,35 @@ static void drm_cleanup(struct drm_device * dev)
drm_mm_takedown(&dev->offset_manager);
drm_ht_remove(&dev->object_hash);
drm_put_head(&dev->primary);
drm_put_minor(&dev->primary);
if (drm_put_dev(dev))
DRM_ERROR("Cannot unload module\n");
}
int drm_minors_cleanup(int id, void *ptr, void *data)
{
struct drm_minor *minor = ptr;
struct drm_device *dev;
struct drm_driver *driver = data;
dev = minor->dev;
if (minor->dev->driver != driver)
return 0;
if (minor->type != DRM_MINOR_LEGACY)
return 0;
if (dev)
pci_dev_put(dev->pdev);
drm_cleanup(dev);
return 1;
}
void drm_exit(struct drm_driver *driver)
{
int i;
struct drm_device *dev = NULL;
struct drm_head *head;
DRM_DEBUG("\n");
if (drm_fb_loaded) {
for (i = 0; i < drm_cards_limit; i++) {
head = drm_heads[i];
if (!head)
continue;
if (!head->dev)
continue;
if (head->dev->driver != driver)
continue;
dev = head->dev;
if (dev) {
/* release the pci driver */
if (dev->pdev)
pci_dev_put(dev->pdev);
drm_cleanup(dev);
}
}
idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
} else
pci_unregister_driver(&driver->pci_driver);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
@ -467,6 +467,7 @@ static int __init drm_core_init(void)
unsigned long avail_memctl_mem;
unsigned long max_memctl_mem;
idr_init(&drm_minors_idr);
si_meminfo(&si);
/*
@ -488,11 +489,6 @@ static int __init drm_core_init(void)
drm_init_memctl(avail_memctl_mem/2, avail_memctl_mem*3/4, si.mem_unit);
ret = -ENOMEM;
drm_cards_limit =
(drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
drm_heads = drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
if (!drm_heads)
goto err_p1;
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
goto err_p1;
@ -521,7 +517,8 @@ err_p3:
drm_sysfs_destroy();
err_p2:
unregister_chrdev(DRM_MAJOR, "drm");
drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
idr_destroy(&drm_minors_idr);
err_p1:
return ret;
}
@ -533,7 +530,7 @@ static void __exit drm_core_exit(void)
unregister_chrdev(DRM_MAJOR, "drm");
drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
idr_destroy(&drm_minors_idr);
}
module_init(drm_core_init);
@ -593,7 +590,7 @@ EXPORT_SYMBOL(drm_ioctl);
long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct drm_ioctl_desc *ioctl;
drm_ioctl_t *func;
unsigned int nr = DRM_IOCTL_NR(cmd);
@ -605,7 +602,7 @@ long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
++file_priv->ioctl_count;
DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
current->pid, cmd, nr, (long)old_encode_dev(file_priv->head->device),
current->pid, cmd, nr, (long)old_encode_dev(file_priv->minor->device),
file_priv->authenticated);
if ((nr >= DRM_CORE_IOCTL_COUNT) &&

View File

@ -494,7 +494,7 @@ static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class,
int drm_fence_add_user_object(struct drm_file *priv,
struct drm_fence_object *fence, int shareable)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -590,7 +590,7 @@ void drm_fence_manager_takedown(struct drm_device *dev)
struct drm_fence_object *drm_lookup_fence_object(struct drm_file *priv,
uint32_t handle)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_user_object *uo;
struct drm_fence_object *fence;

View File

@ -128,16 +128,15 @@ static int drm_setup(struct drm_device * dev)
int drm_open(struct inode *inode, struct file *filp)
{
struct drm_device *dev = NULL;
int minor = iminor(inode);
int minor_id = iminor(inode);
struct drm_minor *minor;
int retcode = 0;
if (!((minor >= 0) && (minor < drm_cards_limit)))
minor = idr_find(&drm_minors_idr, minor_id);
if (!minor)
return -ENODEV;
if (!drm_heads[minor])
return -ENODEV;
if (!(dev = drm_heads[minor]->dev))
if (!(dev = minor->dev))
return -ENODEV;
retcode = drm_open_helper(inode, filp, dev);
@ -176,19 +175,18 @@ EXPORT_SYMBOL(drm_open);
int drm_stub_open(struct inode *inode, struct file *filp)
{
struct drm_device *dev = NULL;
int minor = iminor(inode);
struct drm_minor *minor;
int minor_id = iminor(inode);
int err = -ENODEV;
const struct file_operations *old_fops;
DRM_DEBUG("\n");
if (!((minor >= 0) && (minor < drm_cards_limit)))
minor = idr_find(&drm_minors_idr, minor_id);
if (!minor)
return -ENODEV;
if (!drm_heads[minor])
return -ENODEV;
if (!(dev = drm_heads[minor]->dev))
if (!(dev = minor->dev))
return -ENODEV;
old_fops = filp->f_op;
@ -233,7 +231,7 @@ static int drm_cpu_valid(void)
static int drm_open_helper(struct inode *inode, struct file *filp,
struct drm_device * dev)
{
int minor = iminor(inode);
int minor_id = iminor(inode);
struct drm_file *priv;
int ret;
int i, j;
@ -243,7 +241,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
if (!drm_cpu_valid())
return -EINVAL;
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor_id);
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
if (!priv)
@ -254,8 +252,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
priv->filp = filp;
priv->uid = current->euid;
priv->pid = current->pid;
priv->minor = minor;
priv->head = drm_heads[minor];
priv->minor = idr_find(&drm_minors_idr, minor_id);
priv->ioctl_count = 0;
/* for compatibility root is always authenticated */
priv->authenticated = capable(CAP_SYS_ADMIN);
@ -320,11 +317,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
int drm_fasync(int fd, struct file *filp, int on)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
int retcode;
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
(long)old_encode_dev(priv->head->device));
(long)old_encode_dev(priv->minor->device));
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
if (retcode < 0)
return retcode;
@ -374,7 +371,7 @@ static void drm_object_release(struct file *filp)
int drm_release(struct inode *inode, struct file *filp)
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
int retcode = 0;
lock_kernel();
@ -389,7 +386,7 @@ int drm_release(struct inode *inode, struct file *filp)
*/
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
current->pid, (long)old_encode_dev(file_priv->head->device),
current->pid, (long)old_encode_dev(file_priv->minor->device),
dev->open_count);
if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {

View File

@ -33,7 +33,7 @@
int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item,
int shareable)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
int ret;
DRM_ASSERT_LOCKED(&dev->struct_mutex);
@ -58,7 +58,7 @@ EXPORT_SYMBOL(drm_add_user_object);
struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, uint32_t key)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_hash_item *hash;
int ret;
struct drm_user_object *item;
@ -85,7 +85,7 @@ EXPORT_SYMBOL(drm_lookup_user_object);
static void drm_deref_user_object(struct drm_file *priv, struct drm_user_object *item)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
int ret;
if (atomic_dec_and_test(&item->refcount)) {
@ -121,7 +121,7 @@ int drm_add_ref_object(struct drm_file *priv, struct drm_user_object *referenced
struct drm_ref_object *item;
struct drm_open_hash *ht = &priv->refd_object_hash[ref_action];
DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex);
if (!referenced_object->shareable && priv != referenced_object->owner) {
DRM_ERROR("Not allowed to reference this object\n");
return -EINVAL;
@ -178,7 +178,7 @@ struct drm_ref_object *drm_lookup_ref_object(struct drm_file *priv,
struct drm_hash_item *hash;
int ret;
DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex);
ret = drm_ht_find_item(&priv->refd_object_hash[ref_action],
(unsigned long)referenced_object, &hash);
if (ret)
@ -212,7 +212,7 @@ void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item)
struct drm_open_hash *ht = &priv->refd_object_hash[item->unref_action];
enum drm_ref_type unref_action;
DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex);
unref_action = item->unref_action;
if (atomic_dec_and_test(&item->refcount)) {
ret = drm_ht_remove_item(ht, &item->hash);
@ -239,7 +239,7 @@ EXPORT_SYMBOL(drm_remove_ref_object);
int drm_user_object_ref(struct drm_file *priv, uint32_t user_token,
enum drm_object_type type, struct drm_user_object **object)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_user_object *uo;
struct drm_hash_item *hash;
int ret;
@ -269,7 +269,7 @@ out_err:
int drm_user_object_unref(struct drm_file *priv, uint32_t user_token,
enum drm_object_type type)
{
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_user_object *uo;
struct drm_ref_object *ro;
int ret;

View File

@ -90,34 +90,35 @@ static struct drm_proc_list {
* "/proc/dri/%minor%/", and each entry in proc_list as
* "/proc/dri/%minor%/%name%".
*/
int drm_proc_init(struct drm_device * dev, int minor,
struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
int drm_proc_init(struct drm_minor *minor, int minor_id,
struct proc_dir_entry *root)
{
struct proc_dir_entry *ent;
int i, j;
char name[64];
sprintf(name, "%d", minor);
*dev_root = proc_mkdir(name, root);
if (!*dev_root) {
sprintf(name, "%d", minor_id);
minor->dev_root = proc_mkdir(name, root);
if (!minor->dev_root) {
DRM_ERROR("Cannot create /proc/dri/%s\n", name);
return -1;
}
for (i = 0; i < DRM_PROC_ENTRIES; i++) {
ent = create_proc_entry(drm_proc_list[i].name,
S_IFREG | S_IRUGO, *dev_root);
S_IFREG | S_IRUGO, minor->dev_root);
if (!ent) {
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
name, drm_proc_list[i].name);
for (j = 0; j < i; j++)
remove_proc_entry(drm_proc_list[i].name,
*dev_root);
minor->dev_root);
remove_proc_entry(name, root);
minor->dev_root = NULL;
return -1;
}
ent->read_proc = drm_proc_list[i].f;
ent->data = dev;
ent->data = minor;
}
return 0;
}
@ -132,18 +133,17 @@ int drm_proc_init(struct drm_device * dev, int minor,
*
* Remove all proc entries created by proc_init().
*/
int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
struct proc_dir_entry *dev_root)
int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
{
int i;
char name[64];
if (!root || !dev_root)
if (!root || !minor->dev_root)
return 0;
for (i = 0; i < DRM_PROC_ENTRIES; i++)
remove_proc_entry(drm_proc_list[i].name, dev_root);
sprintf(name, "%d", minor);
remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
sprintf(name, "%d", minor->index);
remove_proc_entry(name, root);
return 0;
@ -165,7 +165,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
static int drm_name_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
if (offset > DRM_PROC_LIMIT) {
@ -207,7 +208,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
static int drm__vm_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
struct drm_map *map;
struct drm_map_list *r_list;
@ -264,7 +266,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
static int drm_vm_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -287,7 +290,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
static int drm__queues_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
int i;
struct drm_queue *q;
@ -337,7 +341,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
static int drm_queues_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -360,7 +365,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
struct drm_device_dma *dma = dev->dma;
int i;
@ -409,7 +415,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -432,7 +439,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
static int drm__objects_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
struct drm_buffer_manager *bm = &dev->bm;
struct drm_fence_manager *fm = &dev->fm;
@ -496,7 +504,8 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
static int drm_objects_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -519,7 +528,8 @@ static int drm_objects_info(char *buf, char **start, off_t offset, int request,
static int drm__clients_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
struct drm_file *priv;
@ -535,7 +545,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
list_for_each_entry(priv, &dev->filelist, lhead) {
DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
priv->authenticated ? 'y' : 'n',
priv->minor,
priv->minor->index,
priv->pid,
priv->uid, priv->magic, priv->ioctl_count);
}
@ -552,7 +562,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
static int drm_clients_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);
@ -566,7 +577,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
static int drm__vma_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int len = 0;
struct drm_vma_entry *pt;
struct vm_area_struct *vma;
@ -625,7 +637,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
static int drm_vma_info(char *buf, char **start, off_t offset, int request,
int *eof, void *data)
{
struct drm_device *dev = (struct drm_device *) data;
struct drm_minor *minor = (struct drm_minor *) data;
struct drm_device *dev = minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);

View File

@ -37,23 +37,49 @@
#include "drmP.h"
#include "drm_core.h"
unsigned int drm_cards_limit = 16; /* Enough for one machine */
unsigned int drm_debug = 0; /* 1 to enable debug output */
EXPORT_SYMBOL(drm_debug);
MODULE_AUTHOR(CORE_AUTHOR);
MODULE_DESCRIPTION(CORE_DESC);
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
MODULE_PARM_DESC(debug, "Enable debug output");
module_param_named(cards_limit, drm_cards_limit, int, 0444);
module_param_named(debug, drm_debug, int, 0600);
struct drm_head **drm_heads;
struct idr drm_minors_idr;
struct class *drm_class;
struct proc_dir_entry *drm_proc_root;
static int drm_minor_get_id(struct drm_device *dev, int type)
{
int new_id;
int ret;
int base = 0, limit = 63;
again:
if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
DRM_ERROR("Out of memory expanding drawable idr\n");
return -ENOMEM;
}
mutex_lock(&dev->struct_mutex);
ret = idr_get_new_above(&drm_minors_idr, NULL,
base, &new_id);
mutex_unlock(&dev->struct_mutex);
if (ret == -EAGAIN) {
goto again;
} else if (ret) {
return ret;
}
if (new_id >= limit) {
idr_remove(&drm_minors_idr, new_id);
return -EINVAL;
}
return new_id;
}
static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
const struct pci_device_id *ent,
struct drm_driver *driver)
@ -161,49 +187,60 @@ error_out_unreg:
* create the proc init entry via proc_init(). This routines assigns
* minor numbers to secondary heads of multi-headed cards
*/
static int drm_get_head(struct drm_device * dev, struct drm_head * head)
static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
{
struct drm_head **heads = drm_heads;
struct drm_minor *new_minor;
int ret;
int minor;
int minor_id;
DRM_DEBUG("\n");
for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
if (!*heads) {
minor_id = drm_minor_get_id(dev, type);
if (minor_id < 0)
return minor_id;
*head = (struct drm_head) {
.dev = dev,
.device = MKDEV(DRM_MAJOR, minor),
.minor = minor,
};
if ((ret =
drm_proc_init(dev, minor, drm_proc_root,
&head->dev_root))) {
printk(KERN_ERR
"DRM: Failed to initialize /proc/dri.\n");
goto err_g1;
}
ret = drm_sysfs_device_add(dev, head);
if (ret) {
printk(KERN_ERR
"DRM: Error sysfs_device_add.\n");
goto err_g2;
}
*heads = head;
DRM_DEBUG("new minor assigned %d\n", minor);
return 0;
}
new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
if (!new_minor) {
ret = -ENOMEM;
goto err_idr;
}
DRM_ERROR("out of minors\n");
return -ENOMEM;
new_minor->type = type;
new_minor->device = MKDEV(DRM_MAJOR, minor_id);
new_minor->dev = dev;
new_minor->index = minor_id;
idr_replace(&drm_minors_idr, new_minor, minor_id);
if (type == DRM_MINOR_LEGACY) {
ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
if (ret) {
DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
goto err_mem;
}
} else
new_minor->dev_root = NULL;
ret = drm_sysfs_device_add(new_minor);
if (ret) {
printk(KERN_ERR
"DRM: Error sysfs_device_add.\n");
goto err_g2;
}
*minor = new_minor;
DRM_DEBUG("new minor assigned %d\n", minor_id);
return 0;
err_g2:
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
err_g1:
*head = (struct drm_head) {
.dev = NULL};
if (new_minor->type == DRM_MINOR_LEGACY)
drm_proc_cleanup(new_minor, drm_proc_root);
err_mem:
kfree(new_minor);
err_idr:
idr_remove(&drm_minors_idr, minor_id);
*minor = NULL;
return ret;
}
@ -246,22 +283,29 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
printk(KERN_ERR "DRM: fill_in_dev failed\n");
goto err_g3;
}
if ((ret = drm_get_head(dev, &dev->primary)))
/* only add the control node on a modesetting platform */
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
goto err_g3;
if (dev->driver->load)
if ((ret = dev->driver->load(dev, ent->driver_data)))
goto err_g4;
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
driver->name, driver->major, driver->minor, driver->patchlevel,
driver->date, dev->primary.minor);
driver->date, dev->primary->index);
return 0;
err_g3:
err_g4:
drm_put_minor(&dev->primary);
err_g3:
if (!drm_fb_loaded)
pci_disable_device(pdev);
err_g2:
err_g2:
if (!drm_fb_loaded)
pci_release_regions(pdev);
err_g1:
err_g1:
if (!drm_fb_loaded)
pci_set_drvdata(pdev, NULL);
@ -310,17 +354,18 @@ int drm_put_dev(struct drm_device * dev)
* last minor released.
*
*/
int drm_put_head(struct drm_head * head)
int drm_put_minor(struct drm_minor **minor_p)
{
int minor = head->minor;
struct drm_minor *minor = *minor_p;
DRM_DEBUG("release secondary minor %d\n", minor->index);
DRM_DEBUG("release secondary minor %d\n", minor);
if (minor->type == DRM_MINOR_LEGACY)
drm_proc_cleanup(minor, drm_proc_root);
drm_sysfs_device_remove(minor);
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
drm_sysfs_device_remove(head->dev);
idr_remove(&drm_minors_idr, minor->index);
*head = (struct drm_head) {.dev = NULL};
drm_heads[minor] = NULL;
kfree(minor);
*minor_p = NULL;
return 0;
}

View File

@ -19,7 +19,7 @@
#include "drm_core.h"
#include "drmP.h"
#define to_drm_device(d) container_of(d, struct drm_device, dev)
#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
/**
* drm_sysfs_suspend - DRM class suspend hook
@ -31,7 +31,8 @@
*/
static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
{
struct drm_device *drm_dev = to_drm_device(dev);
struct drm_minor *drm_minor = to_drm_minor(dev);
struct drm_device *drm_dev = drm_minor->dev;
printk(KERN_ERR "%s\n", __FUNCTION__);
@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
*/
static int drm_sysfs_resume(struct device *dev)
{
struct drm_device *drm_dev = to_drm_device(dev);
struct drm_minor *drm_minor = to_drm_minor(dev);
struct drm_device *drm_dev = drm_minor->dev;
if (drm_dev->driver->resume)
return drm_dev->driver->resume(drm_dev);
@ -122,10 +124,11 @@ void drm_sysfs_destroy(void)
static ssize_t show_dri(struct device *device, struct device_attribute *attr,
char *buf)
{
struct drm_device *dev = to_drm_device(device);
if (dev->driver->dri_library_name)
return dev->driver->dri_library_name(dev, buf);
return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
struct drm_minor *drm_minor = to_drm_minor(device);
struct drm_device *drm_dev = drm_minor->dev;
if (drm_dev->driver->dri_library_name)
return drm_dev->driver->dri_library_name(drm_dev, buf);
return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
}
static struct device_attribute device_attrs[] = {
@ -154,25 +157,28 @@ static void drm_sysfs_device_release(struct device *dev)
* as the parent for the Linux device, and make sure it has a file containing
* the driver we're using (for userspace compatibility).
*/
int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
int drm_sysfs_device_add(struct drm_minor *minor)
{
int err;
int i, j;
char *minor_str;
dev->dev.parent = &dev->pdev->dev;
dev->dev.class = drm_class;
dev->dev.release = drm_sysfs_device_release;
dev->dev.devt = head->device;
snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor);
minor->kdev.parent = &minor->dev->pdev->dev;
minor->kdev.class = drm_class;
minor->kdev.release = drm_sysfs_device_release;
minor->kdev.devt = minor->device;
minor_str = "card%d";
snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
err = device_register(&dev->dev);
err = device_register(&minor->kdev);
if (err) {
DRM_ERROR("device add failed: %d\n", err);
goto err_out;
}
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
err = device_create_file(&dev->dev, &device_attrs[i]);
err = device_create_file(&minor->kdev, &device_attrs[i]);
if (err)
goto err_out_files;
}
@ -182,8 +188,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
err_out_files:
if (i > 0)
for (j = 0; j < i; j++)
device_remove_file(&dev->dev, &device_attrs[i]);
device_unregister(&dev->dev);
device_remove_file(&minor->kdev, &device_attrs[i]);
device_unregister(&minor->kdev);
err_out:
return err;
@ -196,11 +202,11 @@ err_out:
* This call unregisters and cleans up a class device that was created with a
* call to drm_sysfs_device_add()
*/
void drm_sysfs_device_remove(struct drm_device *dev)
void drm_sysfs_device_remove(struct drm_minor *minor)
{
int i;
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
device_remove_file(&dev->dev, &device_attrs[i]);
device_unregister(&dev->dev);
device_remove_file(&minor->kdev, &device_attrs[i]);
device_unregister(&minor->kdev);
}

View File

@ -86,7 +86,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
unsigned long address)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_map *map = NULL;
struct drm_map_list *r_list;
struct drm_hash_item *hash;
@ -204,7 +204,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
static void drm_vm_shm_close(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_vma_entry *pt, *temp;
struct drm_map *map;
struct drm_map_list *r_list;
@ -286,7 +286,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_device_dma *dma = dev->dma;
unsigned long offset;
unsigned long page_nr;
@ -323,7 +323,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
{
struct drm_map *map = (struct drm_map *) vma->vm_private_data;
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_sg_mem *entry = dev->sg;
unsigned long offset;
unsigned long map_offset;
@ -419,7 +419,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
static void drm_vm_open_locked(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_vma_entry *vma_entry;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@ -437,7 +437,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
static void drm_vm_open(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
mutex_lock(&dev->struct_mutex);
drm_vm_open_locked(vma);
@ -455,7 +455,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
static void drm_vm_close(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_vma_entry *pt, *temp;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@ -491,7 +491,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
struct drm_device_dma *dma;
unsigned long length = vma->vm_end - vma->vm_start;
dev = priv->head->dev;
dev = priv->minor->dev;
dma = dev->dma;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
vma->vm_start, vma->vm_end, vma->vm_pgoff);
@ -556,7 +556,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
struct drm_map *map = NULL;
unsigned long offset = 0;
struct drm_hash_item *hash;
@ -677,7 +677,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->head->dev;
struct drm_device *dev = priv->minor->dev;
int ret;
mutex_lock(&dev->struct_mutex);

View File

@ -113,7 +113,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
drm_i810_buf_priv_t *buf_priv;
lock_kernel();
dev = priv->head->dev;
dev = priv->minor->dev;
dev_priv = dev->dev_private;
buf = dev_priv->mmap_buffer;
buf_priv = buf->dev_private;
@ -141,7 +141,7 @@ static const struct file_operations i810_buffer_fops = {
static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
drm_i810_private_t *dev_priv = dev->dev_private;
const struct file_operations *old_fops;

View File

@ -988,7 +988,7 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle,
struct drm_i915_validate_buffer *buffers,
uint32_t buf_count)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
struct i915_relocatee_info relocatee;
int ret = 0;
int b;
@ -1195,7 +1195,7 @@ void i915_fence_or_sync(struct drm_file *file_priv,
struct drm_fence_arg *fence_arg,
struct drm_fence_object **fence_p)
{
struct drm_device *dev = file_priv->head->dev;
struct drm_device *dev = file_priv->minor->dev;
int ret;
struct drm_fence_object *fence;