drm: reorganise minor number handling using backported modesetting code.
rips out the head crap and replaces it with an idr and drm_minor structure Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
7b832b56bd
commit
2c14f28be2
@ -379,13 +379,12 @@ struct drm_buf_entry {
|
||||
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;
|
||||
struct file *filp;
|
||||
@ -630,16 +629,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 */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -647,7 +649,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 */
|
||||
@ -763,7 +764,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 */
|
||||
|
||||
/** \name Drawable information */
|
||||
/*@{ */
|
||||
@ -1030,23 +1031,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
|
||||
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;
|
||||
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);
|
||||
extern int drm_proc_init(struct drm_minor *minor, int minor_id,
|
||||
struct proc_dir_entry *root);
|
||||
extern 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);
|
||||
@ -1071,8 +1069,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)
|
||||
|
@ -122,7 +122,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev)
|
||||
drm_ht_remove(&dev->map_hash);
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
|
||||
DRM_INFO("Module unloaded\n");
|
||||
}
|
||||
|
||||
@ -357,13 +358,7 @@ static int __init drm_core_init(void)
|
||||
{
|
||||
int 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;
|
||||
idr_init(&drm_minors_idr);
|
||||
|
||||
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
|
||||
goto err_p1;
|
||||
@ -391,7 +386,8 @@ static int __init drm_core_init(void)
|
||||
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;
|
||||
}
|
||||
@ -403,7 +399,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);
|
||||
@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, 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);
|
||||
@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
|
||||
|
||||
DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
|
||||
task_pid_nr(current), cmd, nr,
|
||||
(long)old_encode_dev(file_priv->head->device),
|
||||
(long)old_encode_dev(file_priv->minor->device),
|
||||
file_priv->authenticated);
|
||||
|
||||
if ((nr >= DRM_CORE_IOCTL_COUNT) &&
|
||||
|
@ -129,16 +129,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);
|
||||
@ -168,19 +167,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;
|
||||
@ -225,7 +223,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;
|
||||
|
||||
@ -234,7 +232,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", task_pid_nr(current), minor);
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
|
||||
|
||||
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
|
||||
if (!priv)
|
||||
@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
priv->filp = filp;
|
||||
priv->uid = current->euid;
|
||||
priv->pid = task_pid_nr(current);
|
||||
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);
|
||||
@ -297,11 +294,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;
|
||||
@ -324,7 +321,7 @@ EXPORT_SYMBOL(drm_fasync);
|
||||
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;
|
||||
unsigned long irqflags;
|
||||
|
||||
@ -341,7 +338,7 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
|
||||
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
|
||||
task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->head->device),
|
||||
(long)old_encode_dev(file_priv->minor->device),
|
||||
dev->open_count);
|
||||
|
||||
if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
|
||||
|
@ -87,34 +87,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;
|
||||
@ -130,18 +131,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;
|
||||
@ -163,7 +163,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) {
|
||||
@ -205,7 +206,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;
|
||||
@ -261,7 +263,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);
|
||||
@ -284,7 +287,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;
|
||||
@ -334,7 +338,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);
|
||||
@ -357,7 +362,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;
|
||||
@ -406,7 +412,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);
|
||||
@ -429,7 +436,8 @@ static int drm_bufs_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;
|
||||
|
||||
@ -445,7 +453,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);
|
||||
}
|
||||
@ -462,7 +470,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);
|
||||
@ -476,7 +485,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;
|
||||
@ -535,7 +545,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);
|
||||
|
@ -36,23 +36,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)
|
||||
@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
||||
* 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;
|
||||
err_g2:
|
||||
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
|
||||
err_g1:
|
||||
*head = (struct drm_head) {
|
||||
.dev = NULL};
|
||||
|
||||
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:
|
||||
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;
|
||||
}
|
||||
|
||||
@ -222,12 +260,12 @@ 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_g2;
|
||||
}
|
||||
if ((ret = drm_get_head(dev, &dev->primary)))
|
||||
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
|
||||
goto err_g2;
|
||||
|
||||
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;
|
||||
|
||||
@ -276,18 +314,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);
|
||||
|
||||
*head = (struct drm_head) {.dev = NULL};
|
||||
|
||||
drm_heads[minor] = NULL;
|
||||
idr_remove(&drm_minors_idr, minor->index);
|
||||
|
||||
kfree(minor);
|
||||
*minor_p = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -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);
|
||||
@ -120,10 +122,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[] = {
|
||||
@ -152,25 +155,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";
|
||||
|
||||
err = device_register(&dev->dev);
|
||||
snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
|
||||
|
||||
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;
|
||||
}
|
||||
@ -180,8 +186,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;
|
||||
@ -194,11 +200,11 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
|
||||
* 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);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
|
||||
static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
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;
|
||||
@ -207,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
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 void drm_vm_shm_close(struct vm_area_struct *vma)
|
||||
static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
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;
|
||||
@ -321,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
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;
|
||||
@ -402,7 +402,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",
|
||||
@ -420,7 +420,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);
|
||||
@ -438,7 +438,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",
|
||||
@ -473,7 +473,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);
|
||||
@ -543,7 +543,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;
|
||||
@ -661,7 +661,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);
|
||||
|
@ -94,7 +94,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;
|
||||
@ -122,7 +122,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;
|
||||
|
@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
|
||||
drm_i830_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;
|
||||
@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = {
|
||||
|
||||
static int i830_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_i830_buf_priv_t *buf_priv = buf->dev_private;
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
const struct file_operations *old_fops;
|
||||
|
Loading…
Reference in New Issue
Block a user